fork()分支超过预期?

时间:2012-06-21 06:43:34

标签: c++ c 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个点吗?

3 个答案:

答案 0 :(得分:243)

fork()原语经常延伸想象力。在您了解它之前,您应该在纸上找出每项操作的内容并说明进程数。不要忘记fork()创建了一个近乎完美的当前进程副本。最重要的区别(对于大多数用途)是fork()的父级和子级之间的返回值不同。 (由于此代码忽略了返回值,因此没有区别。)

所以,首先,有一个过程。这创建了第二个进程,两个进程都打印了一个点和循环。在第二次迭代中,每个都创建另一个副本,因此有四个进程打印一个点,然后退出。因此,我们可以像您期望的那样轻松地占据六个点。

然而,printf()真正做的是缓冲其输出。因此,只有两个进程的第一个点在写入时不会出现。这些点保留在缓冲区中 - 在fork()处重复。直到该过程即将退出,才会出现缓冲点。打印缓冲点的四个过程加上新的点可以得到8个点。

如果您想避免这种行为,请在fflush(stdout);之后致电printf()

答案 1 :(得分:70)

您在输出流中有未提交的缓冲区。 stdout是行缓冲的,缓冲区与进程的其余部分一起复制。程序终止时,未提交的缓冲区被写入两次(每个进程一次)。两者都使用

printf("a\n");

printf("a "); fflush(stdout);

不要表现出问题。

在第一个示例中,您创建了四个进程,其输出流缓冲区中每两个点都有一个。当每个流终止时,它会刷新缓冲区,产生8个点。

答案 2 :(得分:2)

当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点。 :)