问题如下:

int main(){fork()||fork();}中,其共创建了几个进程?

此题考查fork的原理和或操作的求值操作。fork()的核心在于执行之后父子进程即在此分道扬镳(并不是复制完整的一份代码运行,和递归概念完全不一样),从此以后父子即为路人。不要问我为什么不是『妈女进程』…

首先执行main函数为一个进程(记为pid0),或操作符左侧的fork()调用一次为一子进程(记为pid1)。对于父进程pid0来说,调用fork()产生的pid1在父进程pid0中返回其进程ID,而在自己的进程pid1中则返回0. 故在父进程pid0中,由于fork()返回的值不为0,或操作不需要执行后面的运算;而在子进程pid1中,由于fork()返回的值为0,故还需执行后面的运算——再次fork()产生子进程pid2. 由于执行完第二个fork()后再无fork(),不再产生新的子进程,故共产生3个进程。

口说无凭,下面用一段程序验证之,运行环境为OS X, Linux下程序也可直接运行。

#include <unistd.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
        pid_t pid1 = -8, pid2 = -8;

        printf("I am the boss process, PID = %d\n", getpid());

        (pid1 = fork()) || (pid2 = fork());

        if (pid1 < 0) {
                printf("pid1 = %d, PID = %d\n", pid1++, getpid());
        } else if (pid1 == 0) {
                printf("pid1 child process, PID = %d\n", getpid());
        } else if (pid1 > 0){
                printf("pid1 = %d, parent process, PID = %d\n", pid1, getpid());
        }

        if (pid2 < 0) {
                printf("pid2 = %d, PID = %d\n", pid2++, getpid());
        } else if (pid2 == 0) {
                printf("pid2 child process, PID = %d.\n", getpid());
        } else if (pid2 > 0){
                printf("pid2 = %d, parent process, PID = %d\n", pid2, getpid());
        }

        return 0;
}

上面这段程序的执行输出为:

I am the boss process, PID = 50159
pid1 = 50160, parent process, PID = 50159
pid2 = -8, PID = 50159
pid1 child process, PID = 50160
pid2 = 50161, parent process, PID = 50160
pid1 child process, PID = 50161
pid2 child process, PID = 50161
  1. 首先父进程pid0开始执行,相应的进程PID为50159
  2. 调用左侧的fork(),父进程得到返回值pid1 = 50160,相应的执行进程PID为50159; 此时pid2仍为初始值-8
  3. 调用左侧的fork()后,子进程中得到的返回值为0,相应的PID为50160
  4. 子进程得到的fork()返回值为0,或操作还无法得到最终值,故紧接着执行右侧的fork(),返回pid2 = 50161, 执行进程PID为50160
  5. 由于PID为50160的进程中pid1 = 0, 故PID为50161的子进程fork了PID为50160的父进程的pid1值,返回了pid1 child process...
  6. 最后在PID为50161的子进程中由于fork()返回值为0,执行了pid2 == 0的语句。

参考链接

  1. 一个fork的面试题 | 酷 壳 - CoolShell.cn - 一定要去拜读一下,分析透彻,尤其是对printf()中是否使用了\n做了详细的解释。
  2. linux中fork()函数详解(原创!!实例讲解) - jason的专栏 - 作者做了很多实验和流程图说明了fork()执行的步骤和原理,非常清晰。