我试图了解 fork 是如何工作的,并且我知道当您调用 fork() 时,会创建另一个进程,该进程会从复制到其中的堆和堆栈的完全相同的行恢复。对于父进程,fork() 返回子进程的 PID,对于子进程,它返回 0。
我偶然发现了这个问题:“以下序列创建了多少个进程?”
fork();fork();wait(0);fork();wait(0);
答案是8,包括父级,但我不清楚wait(0)是否真的在等待。我发现这与“等待”手册有关:
如果调用 wait() 时至少有一个子进程正在运行,则调用者将被阻塞,直到其中一个子进程退出。此时,调用者恢复执行。 如果调用 wait() 时没有子进程在运行,则此 wait() 根本不起作用。也就是说,就好像没有 wait() 一样。
我对此的理解可以是这样的:
最左边的分支是父分支,黑色圆圈是分叉的地方。这让我相信 wait(0) 不会执行任何操作,因为没有子进程可以等待,因此它会被忽略。不过,我对代码做了一些修改,为每个进程添加了一个“索引”。
#include <stdio.h>
int main()
{
int index = 0;
if (fork()==0)
index++;
if (fork()==0)
index++;
wait(0);
if (fork()==0)
index++;
wait(0);
printf("%d\n",index);
}
打印出 21312021
注释掉wait(0)后,所以代码是:
#include <stdio.h>
int main()
{
int index = 0;
if (fork()==0)
index++;
if (fork()==0)
index++;
if (fork()==0)
index++;
printf("%d\n",index);
}
它打印出0112223,所以有些东西明显不同。为什么结果不同?
我看不到你的图像,但这是应该准确反映该程序的运行时行为的图像。添加显式
exit(0)
调用有助于理解:
fork() ----------------------------,
| |
fork() -----, fork() -------,
| | | |
| wait(0) | wait(0)
| | | |
| fork()------, | fork() ------,
| | | | | |
| | wait(0) | | wait(0)
| | | | | |
| | exit(0) | | exit(0)
| | | | | |
| wait(0) <---´ | wait(0) <----´
| | | |
| exit(0) | exit(0)
| | | |
| | wait(0) <-----´
| | |
| | fork() -------,
| | | |
| | | wait(0)
| | | |
| | | exit(0)
| | | |
| | wait(0) <-----´
| | |
| | exit(0)
| | |
wait(0) <---+----------------------´
|
fork()------,
| |
| wait(0)
| |
| exit(0)
| |
wait(0) <---´
|
exit(0)
这里,每个子进程都绘制在父进程的右侧。每个
wait(0)
将等待从上面的 fork()
出现的那些行。
有一件事无法准确显示:第一个进程在第一个
wait()
处于有 2 个子进程正在运行的位置,因此它将等待 以先完成者为准。我的图片中的+
应理解为或(我想不出更好的方式来以图形方式显示这一点)。
wait(0)
将阻塞父进程,直到其任何子进程完成并且存在子进程等待,因为所有父进程都执行相同的
wait(0)
(分叉的子进程,成为新子进程的父进程)。