请使用fork()帮助解释这个C / linux代码

时间:2013-04-30 12:30:47

标签: c linux fork

这是一篇过去的纸质考试问题,我无法解决。四个标记:

考虑以下使用Unix系统中的fork()系统调用的C片段:

while (fork()==0) {
  if (fork()==0) break;
}

绘制一个图表(以树的形式),清楚地说明了通过执行此代码生成的父子结构。在实践中运行此代码的最终效果是什么?

我认为它不断创建子进程,但我无法在代码的上下文中解释它。 while每次都会不断调用fork,或者每次只调用if语句吗?

谢谢!

2 个答案:

答案 0 :(得分:8)

while循环将一直运行,直到括号中的条件为false。在这种情况下,这将是:直到fork()的返回值不等于0.

fork()的回报是:

  

成功时,子进程的PID在父进程中返回,并在子进程中返回0。失败时,在父项中返回-1,不创建子进程,并正确设置errno。

因此,一旦fork成功执行,就会有2个进程(父进程和一个新进程)。其中一个将返回0(子进程),另一个(父进程)将返回一些其他值(子进程的PID)。

因此,这告诉您代码将永远运行,因为每个子进程将继续执行while()循环。

假设你的父母是PID = 0 ,第一个孩子是PID = 1 等等。第一次运行的代码是这样的:

while(fork()==0)  // now there are two processes, the child which returns 0 and the
{                 // parent which returns 1 (the new child's pid)

    if(fork() == 0) break;  // this code is now only executed by the child (1) as the 
                            // parent already left the while loop since it's return was
                            // not == 0
                            // once this code executes there are 2 processes running
                            // child(1) will return child(2)'s PID, child(2) will
                            // return 0 and will enter the if and break from the loop 
    // now here it's only the original child(1) running again
}

所以你最终会得到类似的东西:

0 is the original parent, it makes a child and leaves
1 is the original child, it creates a child(2) and then goes to the while loop again
     where it generates 3 before leaving
2 is the child of 1 where it leaves because of the break in the if
3 now hits the if and generates 4 (which leaves because of the break)
3 now goes back to while and generates 5 then leaves, 
etc
etc
              +--> 4
              |
              | (if)
              |
0 --> 1 -+--> 3 ---> 5
         |
         |(if)
         |
         +--> 2

† - 在任何现代Linux发行版上运行用户空间代码时,这些都不是真实的PID,但它们更容易阅读,然后是真正的随机字符串,所以我正在使用它们。功能

答案 1 :(得分:5)

while (fork()==0) {
  if (fork()==0) break;
}

在第一行之前,假设有一个id为6282的进程。

执行

while (fork()==0)   

现在,有两个进程,原始的一个id为6282,另一个进程有另一个id 6283(比如说),现在第二个进程被认为是原始进程的子进程。 现在只有id 6283的子进程进入循环,因为在子上下文中,fork()的返回值为零,而在父上下文中,返回值是创建的子进程的进程ID。

以下第二个陈述由流程6283执行

if (fork()==0) break;

现在6283的子进程将执行break语句,因为上述原因是fork()的返回值在子上下文中为零,因此子进程6283从环。

现在,while()循环的下一次迭代仅由进程6283执行。