问题如下:
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
- 首先父进程pid0开始执行,相应的进程PID为50159
- 调用左侧的fork(),父进程得到返回值pid1 = 50160,相应的执行进程PID为50159; 此时pid2仍为初始值-8
- 调用左侧的fork()后,子进程中得到的返回值为0,相应的PID为50160
- 子进程得到的fork()返回值为0,或操作还无法得到最终值,故紧接着执行右侧的fork(),返回pid2 = 50161, 执行进程PID为50160
- 由于PID为50160的进程中pid1 = 0, 故PID为50161的子进程fork了PID为50160的父进程的pid1值,返回了
pid1 child process...
- 最后在PID为50161的子进程中由于fork()返回值为0,执行了
pid2 == 0
的语句。
参考链接
- 一个fork的面试题 | 酷 壳 - CoolShell.cn - 一定要去拜读一下,分析透彻,尤其是对printf()中是否使用了
\n
做了详细的解释。 - linux中fork()函数详解(原创!!实例讲解) - jason的专栏 - 作者做了很多实验和流程图说明了fork()执行的步骤和原理,非常清晰。