第二个fork() 产生的子进程知道第一个fork() 的结果,因为它是父进程的精确副本。
您可以通过为自己画一棵小树来弄清楚会发生什么。从第一个分叉开始:
fork()
/\
/ \
parent --/ \-- child1
父进程取回child1进程的PID,child1取回0。所以我们有类似的东西:
PID(child1) && fork() || fork()
在父级中,并且:
0 && fork() || fork()
在孩子身上。短路意味着原始表达式的中间 fork() 不会在子级中执行,而只会在父级中执行。那么现在这棵树会发生什么?
fork()
/\
/ \
parent --/ \-- child1
fork()
/\
/ \
parent --/ \-- child2
parent是原始进程,得到child2的PID。 child2,就像child1一样,得到0。我们的表达式现在是什么样子的?
parent: PID(child1) && PID(child2) || fork() = 1 || fork()
child: 0 || fork()
child2: PID(child1) && 0 || fork() = 0 || fork()
现在,再次通过短路,parent 完成,并且不执行最后一个 fork()。但是,child 和 child2 都必须这样做。这给我们留下了以下树:
fork()
/\
/ \
parent --/ \-- child1
fork() fork()
/\ /\
/ \ / \
/ \ child1 --/ \-- child1-1
/ \
/ \
parent --/ \-- child2
fork()
/\
/ \
child2 --/ \-- child2-1
就是这样。 child1 和 child2 分别获取其各自孩子的 PID,child1-1 和 child2-1 各自返回 0。将这些值代入,最终表达式为:
parent: 1
child1: 0 || PID(child1-1) = 1
child2: 0 || PID(child2-1) = 1
child1-1: 0 || 0 = 0
child2-1: 0 || 0 = 0
就是这样 - 他们都退出了。