运行此程序正在打印“分叉!” 7次。有人可以解释一下“分叉!”正在印刷7次?
#include<stdio.h>
#include<unistd.h>
int main(){
fork() && fork() || fork() && fork();
printf("forked!\n");
return 0;
}
答案 0 :(得分:5)
这里使用了几个概念,第一个是知道fork
在某些情况下做了什么以及它返回了什么。很快,当它被调用时,它会创建一个重复的调用者进程,并在子进程中返回0
(false
(逻辑表达式为true
),对于逻辑表达式返回非零(&&
为逻辑表达式)父进程。
实际上,如果出现错误,它可能会返回一个负(非零)值,但在这里我们假设它总是成功。
第二个概念是逻辑表达式的短路计算,例如||
和0 && fork()
,具体而言,fork()
将不调用{{1}因为如果第一个操作数是false
(零),那么就不需要计算第二个操作数。同样,1 || fork()
也不会调用fork()
。
另请注意,在子进程中,表达式的计算将继续与父进程中的计算相同。
另请注意,由于优先级,表达式按以下顺序计算:
(fork() && fork()) || (fork() && fork())
这些观察结果应该会引导您找到正确答案。
考虑fork() && fork()
fork()
/ \
false true && fork()
/ \
false true
所以我们在这里创建了三个进程,其中两个返回false
作为结果,一个返回true
。然后,对于||
,我们让所有返回false
的进程再次尝试运行相同的语句,因此我们将2 * 3 + 1 = 7
作为答案。
答案 1 :(得分:4)
与我在评论中所说的不同,这与缓冲无关。过程分叉。父进程执行第二个分叉,而子进程短路第二个分支并执行第三个分支。第一个孙子将第一个&&
评估为false并执行第3个fork。这产生了2个进程,其中一个进程评估第4个分支。与此同时(或之前或之后......存在竞争条件!),另一个孩子在评估||
的RHS时已成为3个过程。总之,7个进程最终运行。画一棵树。
为简化计算,请考虑:
int f( void )
{
int k;
k = fork();
printf( "%d\n", (int) getpid());
fflush( stdout );
return k;
}
int main( void ) { f() && f() || f() && f(); return 0; }