考虑以下代码:
#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() 创建了当前进程的近乎完美的副本。最显着的区别(对于大多数目的)是fork()
父子之间的返回值不同。(由于此代码忽略了返回值,因此没有区别。)
所以,起初,有一个过程。这将创建第二个过程,这两个过程都打印一个点和循环。在他们的第二次迭代中,每个人都会创建另一个副本,因此有四个进程打印一个点,然后退出。所以我们可以很容易地解释六个点,就像你期望的那样。
然而,printf()
真正做的是缓冲它的输出。因此,只有两个进程时的第一个点在写入时不会出现。这些点保留在缓冲区中——在 fork() 中被复制。直到进程即将退出缓冲点才出现。四个过程打印一个缓冲点,加上新的一个提供 8 个点。
如果您想避免这种行为,请致电fflush(stdout);
after printf()
。
您在输出流中有未提交的缓冲区。stdout 是行缓冲的,并且缓冲区与进程的其余部分一起复制。当程序终止时,未提交的缓冲区被写入两次(每个进程一次)。两者都使用
printf("a\n");
和
printf("a "); fflush(stdout);
不要表现出问题。
在您的第一个示例中,您创建了四个进程,每个进程在其输出流缓冲区中都有两个点。当每个流终止时,它会刷新其缓冲区,生成八个点。
当 i=0
Process_1:缓冲文本= 1 点
Process_2(由 Process_1 创建):缓冲文本 = 1 点
当 i=1
Process_3(由 Process_1 创建):从 Process_1 继承 1 个缓冲点并自行打印 1 个点。Process_3 总共打印 2 个点。
Process_4(由 Process_2 创建):从 Process_2 继承 1 个缓冲点并自行打印 1 个点。Process_4 总共打印 2 个点。
Process_1:打印 2 个点(当 i=0 时打印一个缓冲点,当 i=1 时打印另一个点)
Process_2:打印 2 个点(当 i=0 时打印一个缓冲点,当 i=1 时打印另一个点)
最终输出:8 点。:)