#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
fork();
fork();
fork();
puts("hi");
return 0;
}
该程序打印 8 次“hi”并退出。为什么?是不是每个递归fork
调用main
都如:f(): "hi"; f()
?
答案1
不,fork
不是传统意义上的“递归”递归。调用会fork()
复制当前进程,因此它“返回两次”。对于子进程,返回值为0,对于父进程,返回值为子PID。 fork()
做不是重新启动main
- 这更像是fork
后面跟着exec
.
你的程序是这样工作的。首先让我们插入一些行号:
1: #include <stdio.h>
2: #include <stdlib.h>
3: #include <string.h>
4:
5: int main(int argc, char *argv[])
6: {
7: fork();
8: fork();
9: fork();
10:
11: puts("hi");
12:
13: return 0;
14: }
假设你启动了你的程序,它的 PID 为磷。
第 7 行之后,调用
fork
会产生两个单独的进程,都在8号线, 1个带PID磷(原始)和一个 pid 为C1(新孩子)。磷运行第 8 行并生成一个带有 PID 的新子进程C2。两个都磷和C2现在在9号线。同时,C1运行第 8 行并生成一个新的子进程,CC1。两个都CC1和C1也在9号线。 (不完全相关,但上述两句话发生的顺序是不确定的。它们可能在多处理器系统上同时发生。)
现在共有4个进程:磷,C1,C2, 和CC1。正如您所看到的,每次连续的fork
进程数量都会增加一倍。由于有 3 个fork
调用,因此最终会得到 2、3或8 个进程。家谱看起来像这样:
P (initial process, started by you)
+-- C1 (created on line 7)
| +-- CC1 (created on line 8)
| | +-- CCC1 (created on line 9)
| +-- CC2 (created on line 9)
+-- C2 (created on line 8)
| +-- CC3 (created on line 9)
+-- C3 (created on line 9)
每个进程都是由树中的父进程创建的。
答案2
main()
|
|
fork() ------------------
| |
fork() ------- -------
| | | |
fork() ---- ---- --- ---
| | | | | | | |
这是上面代码的进程树,这就是 fork() 的工作原理。以及为什么它的打印 8 意味着它总是 2 的 n 次方(其中 n 是调用次数,即 fork() 。