深入理解进程(四)——进程创建

本篇文章主要介绍了与进程创建有关的两个函数fork和vfork,以及他们之间的区别
再使用fork和vfork函数时需要添加头文件:

#include<unistd.h>   //fork和vfrok函数需要的
 
#include<sys/types.h> //pid_t 需要的

(1)fork函数

  1. 函数原型:

    pid_t fork()。该函数是通过复制父进程来创建子进程。

  2. 返回值:

    调用一次fork函数却能够返回两个值。 在fork函数执行完毕后,如果创建新进程成功,则出现两个进程,一个是子进程,一个是父进程。在子进程中,fork函数返回0,在父进程中,fork返回新创建子进程的进程ID。我们可以通过fork返回的值来判断当前进程是子进程还是父进程。

  3. fork出错可能的原因
    (1)当前的进程数已经达到了系统规定的上限,这时errno的值被设置为EAGAIN。
    (2)系统内存不足,这时errno的值被设置为ENOMEM。

  4. 写时拷贝技术

    为什么要用使用写时拷贝技术?

    ​ 在说写时拷贝技术之前,我先来分析fork函数。上面我说过,fork函数是通过复制父进程的方式来创建子进程的,也就是说,子进程和父进程是完全相同的。换句话说,就是子进程的pcb与父进程的pcb是一样的,那么他们也就具备相同的虚拟地址空间,这代表他们所映射的内存空间也是一样的,这也就意味着两个进程的数据是完全相同的。那么问题来了,如果我们在子进程中对一些数据进行修改,是不是也会影响到父进程,而一旦影响到父进程势必就会破坏进程的独立性。那么大佬们是如何解决这个问题的呢?答案就是利用了写时拷贝技术

    什么是写时拷贝技术?

    ​ 开始时,两进程的虚拟地址空间相同,但是当子进程想要修改数据时,操作系统会在物理内存中重新开辟一个新的空间,并且将原来的数据拷贝到新空间中,那么此时子进程修改数据就修改的是这个新空间的数据,修改完后,会同时更新页表信息,这就意味着虚拟地址映射的物理地址发生改变,原来的虚拟地址不在对应原来的物理地址,而是对应一个新的物理地址。这样子进程修改的就是自己的数据,而不会波及到父进程,从而保证了进程之间的独立性。这就是写时拷贝技术。

    写时拷贝的作用

    ​ 目的就是提高进程的创建效率。按理说,每个进程都应该有独立的空间,但是若是在子进程创建时就为其开辟空间,这就需要将原来的数据拷贝过去,那么创建过程就很慢。其次,如果将数据拷贝过来,但是子进程就一直没有修改的意思,那么是不是就浪费了。所以开始时,两个进程用同一个空间的数据,只有当子进程要修改某个数据时,才会为其开辟空间。

(2)vfork函数

  1. 函数原型pid_t vfork()

    创建一个子进程,并且阻塞父进程,直到子进程exit退出或者程序替换之后,父进程才开始运行。

  2. 返回值:

    成功: 子进程中返回 0,父进程中返回子进程 ID。

    失败: 返回 -1。

  3. 特点:

    1. vfork 的创建效率较高,因为它创建的子进程与父进程共用同一块虚拟地址空间。
    2. 共用同一块虚拟地址空间意味着,共用相同的数据段、代码段,这样的话,父子进程同时运行会造成调用栈混乱,因此必须子进程运行,父进程阻塞;直到子进程退出,所有函数出栈才行。
    3. vfork创建的子进程不能再main函数中使用return退出,因为main中return会释放掉进程资源。你把资源释放掉了,那父进程还咋玩。
  4. 解释父子进程同时运行会造成调用栈混乱

    因为是同一个虚拟地址空间,所以用的栈相同。我们知道执行函数时,必须先入栈。假如父进程先执行fun1函数,将其入栈,但是还没有执行完毕,此时进程切换。于是子进程开始执行fun2函数,再将函数入栈,同样此时没有执行完毕发生进程切换,轮到父进程。但是此时栈中最上面一层是fun2函数,而不是父进程想要执行的fun1函数,所以着就造成调用栈混乱。

    (3)fork函数与vfork函数的区别

    1. fork函数是子进程拷贝父进程的虚拟地址空间,也就是说,子进程会新建立一个,只不过内容和父进程一样;vfork函数是与父进程共享同一个虚拟地址空间。
    2. fork函数创建的子进程,如果对其修改的话,并不会改变父进程的值;但是vfork函数创建的子进程,如果对其修改的话,会影响到父进程
    3. fork函数创建的子进程可以和父进程同时运行,只不过运行的顺序不确定(这与操作系统的异步性有关);vfork函数只能由子进程先运行,直到子进程exit退出或者程序替换之后,父进程才开始运行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值