对于fork这个函数相信大家都不陌生。我们知道他会创建一个子进程,返回两个值,也有fork会返回两次这么个说法。那今天在这里我们就来整理一下对这个函数的认识。 对于fork会返回两次这个说法我不知道大家都是怎么理解的,“返回一次然后又返回了一次”,在刚接触这个函数的时候有许多同学都是这样认为的。那在这里呢我们就来对这个说法进行一下剖析。 首先我们知道,在进程内调用fork之后,如果调用成功会怎样啊?没错,他会创建出一个子进程,但是创建出来的这个子进程在哪里呢?这里呢就涉及到了进程结构的组成知识。首先我们来看,一个进程在虚拟地址上由低到高依次存储着正文段,数据段(这里我们把初始化和未初始化的数据统称为数据段),和堆栈段,主要呢是这三个段。那我们说正文段,它有着只读共享的属性。也就是说,对于一个程序,我们可以多次运行,但是它们运行起来却是不同的进程。那这些不同的进程是不是共享着同一个正文段啊。那我们的fork函数也一样,在进程调用fork函数之后,子进程产生,子进程与调用fork的进程,也就是父进程共享着同一个正文段。在fork函数成功返回之后,也就是有两个进程同时运行着同一个正文段。我们来看一下下面这段注释: pid = fork(); if(pid < 0) { perror{}; exit(1); } /* 此时有两个程序运行到这 */ else if(pid == 0) { /*子进程代码*/ }else { /*父进程代码*/ } 我们来看上面这段代码的注释,也就是说在fork成功返回之后,会有两个程序同时运行到 /*此时有两个程序运行到这*/这个注释处,此时父子进程里的fork便已经返回了不同的值。在父进程中,父进程的fork返回了一个大于0的数,我们都知道那是子进程的PID;在子进程中,子进程的fork返回了一个0,表示此进程是由别的进程fork出来的。那我们的父子进程都会接着向下运行,判断下面的else if。在父进程中,由于fork返回值大于0,故else if(pid == 0)这个判断语句不成立,然后执行下面的else里面的代码。在子进程中,pid是等于0的,也就是说子进程在判断了else if(pid == 0)条件后发现条件成立,然后它去执行里面的代码。这样的fork框架就可以让我们父子进程在同一个正文段中区分各自进程的代码块。 那现在我们再来看这个“fork会返回两次”的说法还严谨吗?没错,我们fork也是只会返回一次的,只不过在不同的进程中(调用者和被创建者)它返回的值不一样罢了,然后由于共用同一个正文段,所以会给我们造成返回两次的错觉。
|