fork()分支超过预期?

Nik*_*nko 186 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;
}
Run Code Online (Sandbox Code Playgroud)

该程序输出8个点.怎么可能呢?不应该有6个点吗?

wal*_*lyk 245

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

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

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

如果你想避免这种行为,称fflush(stdout);printf().

  • 谢谢,我不知道缓冲区与fork()重复.它解释了这种奇怪的行为. (12认同)
  • @psusi第二代流程之一_是第一代流程.`fork()`不创建2然后退出,它只创建1个进程. (12认同)
  • 不是应该给 10 点,而不是 8 点吗?由于 4 个第二代子进程继承了缓冲点,添加了自己的缓冲点,然后在退出时刷新,它们总共会打印 8 个点,但是 2 个第一代进程仍然每个缓冲一个点,并在退出时刷新这些点,总共给出10个。 (2认同)

thi*_*ton 70

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

printf("a\n");
Run Code Online (Sandbox Code Playgroud)

printf("a "); fflush(stdout);
Run Code Online (Sandbox Code Playgroud)

不要表现出这个问题.

在第一个示例中,您将创建四个进程,这些进程在其输出流缓冲区中分别包含两个点.当每个流终止时,它会刷新其缓冲区,生成8个点.