4

运行这个程序正在打印“forked!” 7次。有人可以解释如何“分叉”!正在打印 7 次?

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

int main(){

  fork() && fork() || fork() && fork();

  printf("forked!\n");

  return 0;
}
4

2 回答 2

5

这里使用了几个概念,第一个是知道fork在某些情况下会做什么以及它会返回什么。很快,当它被调用时,它会创建调用者的重复进程,并在子进程中返回0(对于逻辑表达式),对于父进程返回false非零值(对于逻辑表达式)。true实际上,如果发生错误,它可能会返回一个负(非零)值,但这里我们假设它总是成功。

第二个概念是逻辑表达式的短路计算,例如&&and ||,具体来说,0 && fork()不会调用,因为fork()如果第一个操作数是false(零),则不需要计算第二个操作数。同样,1 || fork()也不会调用fork()

另请注意,在子进程中,表达式的计算在与父进程相同的点继续进行。

另外,请注意,由于优先级,表达式按以下顺序计算:

(fork() && fork()) || (fork() && fork())

这些观察结果应该会引导您找到正确的答案。

考虑简化的例子fork() && fork()

   fork()        
  /     \
false   true && fork()
                /   \
             false  true

所以这里我们创建了三个进程,其中两个false作为结果返回,一个返回true。然后因为||我们让所有进程返回false尝试再次运行相同的语句,所以我们有2 * 3 + 1 = 7答案。

于 2012-06-21T13:42:37.880 回答
4

与我在评论中所说的不同,这与缓冲无关。进程分叉。父母执行第二次分叉,而孩子短路第二次并执行第三次。第一个孙子将第一个评估&&为假并执行第三个分叉。这会产生 2 个进程,其中一个会评估第 4 个分叉。同时(或之前,或之后......有一个竞争条件!),另一个孩子在评估||. 总共有 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; } 
于 2012-06-21T13:39:38.270 回答