2

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

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

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

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

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

谢谢!

4

2 回答 2

9

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

fork()的回报是:

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

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

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

假设您的父母是 PID=0 †</sup>,第一个孩子是 PID=1 †</sup>,等等。代码的第一次运行将类似于:

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,但是它们比真正的随机字符串更容易阅读,所以我正在使用它们。

于 2013-04-30T12:45:53.637 回答
6
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 执行。

于 2013-04-30T12:41:26.253 回答