fork()分支比预期更多?
考虑下面的一段代码:
#include <stdio.h> #include <sys/types.h> #include <unistd.h> int main(void) { int i; for(i = 0; i < 2; i++) { fork(); printf("."); } return 0; }
该程序输出8个点。 这怎么可能? 不应该有6个点呢?
fork()
原始经常延伸想象力。 在你感觉到它之前,你应该在纸上描述每个操作是什么,并说明进程的数量。 不要忘记fork()创build了当前进程的近乎完美的副本。 最显着的差异(对于大多数目的而言)是fork()
的父类和子类的返回值不同。 (由于这段代码忽略了返回值,所以没有区别。)
所以,起初有一个过程。 这创build了第二个过程,这两个过程打印点和循环。 在第二次迭代中,每个都创build另一个副本,所以有四个进程打印一个点,然后退出。 所以我们可以很容易地解释六个点,就像你期望的那样。
但是, printf()
真正做的是缓冲它的输出。 所以当只有两个进程的第一个点在写入时不会出现。 这些点保留在缓冲区中 – 在fork()中被复制。 直到过程即将退出,缓冲点出现。 四个进程打印一个缓冲点,加上新的一个点给出8个点。
如果你想避免这种行为,请调用fflush(stdout);
在printf()
。
输出stream中有未提交的缓冲区 。 标准输出是行缓冲的,缓冲区与其他进程一起被复制。 当程序终止时,未提交的缓冲区被写入两次(每个进程一次)。 两者都使用
printf("a\n");
和
printf("a "); fflush(stdout);
不要出现问题。
在您的第一个示例中,您将创build四个在其输出stream缓冲区中各有两个点的进程。 当每个stream终止时,刷新缓冲区,产生8个点。
当我= 0
Process_1:缓冲文本= 1点
Process_2(由Process_1创build):缓冲文本= 1点
当我= 1
Process_3(由Process_1创build):从Process_1inheritance1个缓冲点,并自行打印1个点。 总共Process_3打印2个点。
Process_4(由Process_2创build):从Process_2inheritance1个缓冲点,并自行打印1个点。 总共Process_4打印2个点。
Process_1:打印2个点(i = 0时为一个缓冲点,i = 1时为另一个点)
Process_2:打印2个点(i = 0时为一个缓冲点,i = 1时为另一个点)
最终输出:8点。 🙂