【问题标题】:Why does this program with fork print twice? [duplicate]为什么这个带有 fork 的程序打印两次? [复制]
【发布时间】:2017-07-30 03:13:33
【问题描述】:

根据我对fork() 的理解,这应该打印“Hello, World!”一次,因为在调用fork 之前只有一个进程。但是,它会打印两次。奇怪的是,如果我在字符串中添加\n 或使用puts() 而不是printf(),它只会打印一次。

#include<unistd.h>
#include<stdio.h>

int main() {
    printf("Hello, World!");
    fork();
}

【问题讨论】:

  • 布赖恩,请在询问之前使用搜索。许多问题已经有了答案。
  • @2501 我做到了。我可能没有使用正确的术语。我还查看了在我输入问题时可能回答我的问题的最佳建议。
  • 尝试使用第三方搜索引擎,缩小本站的搜索范围。
  • @2501 这就是我使用的。我想我没有将printf 作为一个术语,因为我没有意识到这是一个printf 问题;我假设 fork 之前的所有内容都运行了两次。
  • 我认为这是一个比链接副本更好(更清晰)的问题,并且会为这个问题提供一个很好的规范版本。

标签: c fork


【解决方案1】:

我能提供的解释:

printf("Hello, World!"); 不会立即打印,因为输出未刷新到 stdout

fork() 复制进程内存时,它会复制内部缓冲区,当两个进程都终止时,两个进程都会刷新它们的缓冲区并输出两次文本。

【讨论】:

    【解决方案2】:

    缓冲。

    由于默认情况下系统上的标准输出是缓冲的,因此不会立即打印。但是,缓冲区将在进程退出之前被刷新。

    由于fork复制了父级整个内存空间、文件描述符状态等,它也会复制需要打印的缓冲数据。

    因此,除非您在分叉之前显式刷新标准输出缓冲区(通过将\n 附加到输出或调用fflush(stdout);),否则两个进程都将缓冲输出以进行打印。

    【讨论】:

    • @Jean-FrançoisFabre 当该技术有这样令人讨厌的陷阱时,它会有所帮助......我花了一个多小时试图在我的代码中找到问题,然后才缩小到这个范围。跨度>
    • 实际上是重复的。该死。太糟糕了:)
    • 在哪里指定“标准输出默认缓冲”? AIUI,初始缓冲模式完全由实现,最常见的选择是stdin and stdout are line-buffered when associated with a terminal, and fully-buffered otherwise。因此,我建议fflush() 胜过\n
    • @TobySpeight - 如果我的陈述暗示我指的是任何特定的标准,我不是(尽管我不确定如何更正它以便更清楚)。这只是对该程序的可观察行为的解释。
    【解决方案3】:

    输出到stdout(这是printf 写入输出的位置)默认情况下是行缓冲。这意味着当您打印换行符(或缓冲区已满)时,其缓冲区将被刷新(并实际写入输出)。

    如果您不打印换行符,则缓冲的输出将被子进程复制,并且父进程和子进程都会在进程结束时各自刷新自己的缓冲区,从而导致打印两个输出。

    【讨论】:

    • 正如我在对 StoryTeller 的回答的评论中指出的那样,stdout 可能最初是行缓冲的,但这取决于实施。在这种情况下,您只能说输出在该程序的特定运行中被缓冲。当然,一般建议(如果您不希望父母和孩子都写入缓冲输出,请使用fflush())仍然有效。
    猜你喜欢
    • 2011-10-28
    • 2012-03-23
    • 1970-01-01
    • 2015-04-21
    • 1970-01-01
    • 2018-01-07
    • 2018-07-17
    • 2021-08-31
    相关资源
    最近更新 更多