简述Linux下fork与vfork的使用与区别

发布时间:2024年01月17日

在讲述区别之前,先说一说下面的五个问题

①什么是程序,什么是进程,有什么区别?

程序是代码的集合,完成系统的复杂任务;程序跑起来就会产生进程。程序是静态的概念,进程是动态的概念。就比如我们桌面上的这些图标,你可以认为他们不运行的时候就是程序,可是你打开它,就要运行,就会产生对应的进程。

比如说我在Windows操作系统下写博客,我打开可微信和QQ浏览器。这两个软件运行的时候就会产生对应的进程,我按ctrl+shift+Esc就可以在任务管理器中看到

②如何在linux查看系统中有哪些进程?

输入ps可以查看当前用户的进程。

输入ps -aux就可以查看所有的进程并显示详细的用户信息

输入top可以实现类似于windows的任务管理器功能

③什么是进程标识符?

进程的进程标识符就像是人类的身份证一样,每个进程标识符都有自己唯一的非负ID

④什么叫父进程,什么叫子进程?

进程A创建了进程B,那么A叫做父进程,B叫做子进程,父子进程是相对的概念,理解为人类中的父子关系。这里不理解没关系,后面会在细说。

⑤C程序的存储空间是如何分配?

大家可以看一下这位大佬的博客,这是链接,我觉得说的很详细

http://t.csdnimg.cn/7woLW,下图就是他文章的东西,我之前有很多的疑惑,包括在学单片机的时候关于ROM和RAM的疑惑这里也有解释,说的很通透。

一、验证fork函数使用的API函数

①getpid(void);获取自身的进程标识符

无参数

返回自身进程ID

②getppid(void);获取父进程的进程标识符

无参数

返回父进程ID

③pid_t fork(void);创建进程

无参数

fork函数调用成功,返回两次

返回值为0,???? 代表当前进程是子进程

返回值大于0,代表当前进程为父进程

调用失败,返回-1

二、代码验证

1.验证getpid函数的功能以及fork函数作用,下面是代码

这是运行后的结果

那么问题来了,为啥会有这样的结果?

我们可以看到的是after fork这句话出现了两次,为什么会有这样的结果呢?

让我们回到程序首先程序运行的时候,从头开始,都没有问题,当走到fork之后,程序就又创建了一个新的进程,新的进程就叫做子进程。我们原来的进程就叫做父进程。

那么程序到底是怎么运行的呢?

你可以这样想,把程序的运行分为两节。一节是父进程,另一节是子进程。

回到程序开头,我们程序刚开始的时候也就是我们的父进程刚开始的时候,我们用getpid函数获取了父进程的ID,之后程序会一直走下去。在if里面,因为此时仍然是父进程,左移ID值不变,接着在return 0之前父进程停止;然后我们的子进程进开始工作了,这时候程序是从fork函数开始工作,而不是从头开始工作的,所以就又会开始新一轮的if else比较。

2.验证fork函数的返回值,下面是代码

这是运行的结果

从运行结果上我们可以看到父进程的返回值大于0,子进程的返回值等于0。而且不知道大家发现了没有,父进程的返回值等于子进程的ID号。这不是巧合,就是有这样的关系。

同时父进程和子进程在运行的时候是两个独立的个体,大家互不影响。老版本的linux里,子进程运行时需要完全拷贝父进程的内容,然后用啥改啥,因为是拷贝出去单独运行,所以不管是两者运行的时候对对方都是没有影响的。新版本的linux带有共享机制,如果子进程不去改变父进程的一些参数,那么就和父进程一起使用,如果需要改变参数,则会拷贝父进程对应的内容,然后修改,但是也不影响父进程的值。

3.fork函数创建子进程的简单应用,代码如下

这里想要实现的是当我们输入1的时候,我们就会使用fork函数创造一个子进程,并且让子进程不断打印自己的ID值。当我们输入其他的数字的时候,就会显示wait donothing。

运行结果

我们可以看到我们的输入和子进程的工作并不冲突,这就好比我们的服务器和客户端,无论客户端给服务器多少消息,服务器总能给客户端创造一个子进程满足你的需求,并且还不影响服务器继续接收外来请求。

三、验证fork函数使用的API函数

1.fork与vfork很像但是也是有区别的

vfork 直接使用父进程存储空间,不拷贝;fork是需要拷贝的。

vfork保证子进程先运行,当子进程调用exit退出后,父进程才执行;fork的父进程和子进程的运行顺序是由系统调度决定的。

pid_t vfork(void);创建进程

无参数

vfork函数调用成功,返回两次

返回值为0,???? 代表当前进程是子进程

返回值大于0,代表当前进程为父进程

2.fork与vfork区别的验证

下面的两段代码除了pid=fork();和pid=vfork();不一样以外,其余的地方都一样。但是他们运行的结果却不一样,如下图。

其中fork的运行结果如下图所示,我们可以看到子进程和父进程是在争夺进程的控制权一样,很乱,没有顺序。

而vfork的运行结果如下图所示,我们可以看到子进程不是用exit函数,父进程就不会开始。

下面我们略微修改一下程序,采用计数的方法,当cnt从0到3是调用exit函数结束子进程,父进程开始工作,程序如下图

运行结果如下

文章来源:https://blog.csdn.net/weixin_51374594/article/details/135651509
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。