子进程在fork语句之后的最后一个停止的确切位置开始执行。如果语句包含多个fork(),如下所示的条件表达式,该怎么办?准确执行子进程的程序执行的位置。在担心创建了多少进程之前,我想知道创建的每个子进程是否都尝试评估fork() && fork() || fork();
语句。如果是这样的话。由于第二个fork()语句而创建的子进程如何从第一个fork()获取信息以评估fork() && fork()
。
main(){
fork() && fork() || fork();
}
答案 0 :(得分:7)
第二个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
就是这样 - 他们都退出了。
答案 1 :(得分:1)
我不确定什么可能令人困惑。调用fork
函数时,它会创建第二个进程,该进程与现有进程重复。这两个过程都从他们中断的地方继续。孩子知道如何继续以与父母相同的方式进行评估,因为它恰好在需要的地方准确地提供了所需的信息,因为它是一个克隆。
答案 2 :(得分:1)
fork() && fork()
相当于写作:
pid_t x = fork();
if ( x > 0 )
{
fork();
}
也就是说,父进程将分叉两次,因为两个条件都被评估;两个孩子都不会fork()
,因为他们都从分叉返回0。但是,fork() || fork ()
相当于:
pid_t x = fork();
if ( x == 0 )
{
fork();
}
因此,父进程将fork()
一次,其子进程将fork()
一次。
如果你说asm,试着吐出这两个表达式的输出:
movl %edi, -4(%rbp)
movq %rsi, -16(%rbp)
call fork
testl %eax, %eax
je .L3 // jump if eax is zero
call fork
testl %eax, %eax
nop
.L3:
call fork
testl %eax, %eax
jne .L7 // jump if eax is non-zero.
call fork
testl %eax, %eax
请注意,call fork
是您的流程失去控制权然后将eax
设置为返回值重新获得控制权的点。 This question有助于了解testl
。
您应该能够使用operator precedence规则计算出组合示例中会发生什么。