【问题标题】:Explanation of a output of a C program involving fork()涉及 fork() 的 C 程序的输出解释
【发布时间】:2012-06-23 17:56:56
【问题描述】:

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

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

int main(){

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

  printf("forked!\n");

  return 0;
}

【问题讨论】:

  • 可能重复 1000 个其他问题...这是由于缓冲,除非您的问题更具体。
  • 您预计它会打印多少次?
  • 尝试将布尔表达式写成嵌套的 if-then-elses,然后绘制递归树。

标签: c fork


【解决方案1】:

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

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

还要注意,在子进程中,表达式的计算在父进程中的同一点继续进行。

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

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

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

考虑fork() &amp;&amp; fork()的简化示例

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

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

【讨论】:

    【解决方案2】:

    与我在评论中所说的不同,这与缓冲无关。进程分叉。父母执行第二次分叉,而孩子短路第二次并执行第三次。第一个孙子将第一个 &amp;&amp; 评估为 false 并执行第三个分叉。这会产生 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; } 
    

    【讨论】:

    • 只是为了澄清:fork为孩子返回0(false),为父母返回孩子的PID(true)
    猜你喜欢
    • 1970-01-01
    • 2013-10-20
    • 2014-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-08
    • 2013-12-30
    • 2017-07-19
    相关资源
    最近更新 更多