fork() 分支超出预期?

Posted

技术标签:

【中文标题】fork() 分支超出预期?【英文标题】:fork() branches more than expected? 【发布时间】:2012-06-23 09:00:35 【问题描述】:

考虑以下代码:

#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个点吗?

【问题讨论】:

Check this post ideone.com/B9HXL 【参考方案1】:

fork() 原语通常会扩展想象力。在您对它有感觉之前,您应该在纸上追踪每个操作是什么,并说明进程的数量。不要忘记 fork() 创建了当前进程的近乎完美的副本。最显着的区别(对于大多数用途)是 fork() 的返回值在父子之间不同。 (由于这段代码忽略了返回值,所以没有区别。)

所以,起初,只有一个过程。这将创建第二个过程,这两个过程都打印一个点和循环。在他们的第二次迭代中,每个人都会创建另一个副本,因此有四个进程打印一个点,然后退出。因此,我们可以轻松计算出六个点,正如您所期望的那样。

然而,printf() 真正做的是缓冲它的输出。因此,只有两个进程时的第一个点在写入时不会出现。这些点保留在缓冲区中——在 fork() 中被复制。直到进程即将退出缓冲点才出现。四个进程打印一个缓冲点,再加上新的一个会产生 8 个点。

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

【讨论】:

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

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

printf("a\n");

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

不要表现出问题。

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

【讨论】:

【参考方案3】:

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

【讨论】:

以上是关于fork() 分支超出预期?的主要内容,如果未能解决你的问题,请参考以下文章

在 fork 中更新主分支 [重复]

同步github上fork出来的分支

同步 Github fork 出来的分支

使用git/github进行团队协作

如何同步master的代码到fork分支代码

git 合并两个远程分支