【问题标题】:fork() and outputfork() 和输出
【发布时间】:2012-03-10 23:41:39
【问题描述】:

我有一个简单的程序:

int main()
{
    std::cout << " Hello World";
    fork();
}

程序执行后我的输出是:Hello World Hello World。为什么会发生这种情况而不是单个Hello world?我猜想子进程在幕后重新运行,并且输出缓冲区在进程之间共享或类似的东西,但是这种情况还是发生了其他事情?

【问题讨论】:

  • 这就是 fork 的作用,它使用父进程的内存生成进程。 linux.die.net/man/2/fork
  • 最近肯定有很多fork()问题...嗯...
  • hm.. 子进程在调用 fork 后开始执行程序代码。所以子进程不能执行fork之上的代码。
  • 我不认为是采访。我认为是一个操作系统类。查看最新的 refactormycode.com:refactormycode.com/codes/2011-linux-shell

标签: c++ linux unix fork


【解决方案1】:

原因是当您调用std::cout&lt;&lt; 时,它本身并没有真正执行输出,而是将数据留在系统的缓冲区中。当您执行 fork 时,代码和数据以及所有关联的缓冲区都会被复制。最后,父亲和儿子都将它们刷新到标准输出,因此您会看到输出重复。

【讨论】:

    【解决方案2】:

    输出"Hello World" 的代码只执行一次。问题是输出缓冲区没有被刷新。因此,当您分叉该进程时,"Hello World" 仍位于输出缓冲区中。当两个程序退出时,它们的输出缓冲区将被刷新,您将看到两次输出。

    证明这一点的最简单方法是在字符串末尾添加一个换行符,这将导致隐式刷新,或使用std::cout.flush(); 显式刷新。然后你只会看到一次输出。

    【讨论】:

      【解决方案3】:

      这与您最初的想法不太一样。输出缓冲区不共享 - 当您执行分叉时,两个进程都会获得同一个缓冲区的副本。因此,在你 fork 之后,两个进程最终都会刷新缓冲区并将内容分别打印到屏幕上。

      只有在 cout 是缓冲 IO 时才会发生。如果你使用了没有缓冲的 cerr,你应该只会看到一次消息,pre-fork。

      【讨论】:

      • 这只是因为 cout 是用户空间缓冲的 IO。 ^_^
      【解决方案4】:

      您可能在这里看到的是缓冲效果。一般来说,输出会被缓冲,直到它被显式刷新或隐式完成,比如输出一个新行。因为输出是缓冲的,所以分叉进程的两个副本都有缓冲输出,因此在进程终止和刷新缓冲区时都会显示它

      【讨论】:

        【解决方案5】:

        因为你调用 fork() 时没有先刷新所有缓冲区。

        cout.flush();
        fork();
        

        【讨论】:

          【解决方案6】:

          标准输出使用缓冲 IO。当fork() 被调用时,标准输出不会被刷新,缓冲的内容会被复制到子进程中。当进程退出时,这些缓冲区会被刷新,从而产生您看到的两个输出。

          如果您将程序更改为:

          std::cout << " Hello World;" << std::endl;
          

          你应该只看到一个。

          【讨论】:

            【解决方案7】:

            字符串不会立即写入屏幕;相反,它被写入内部缓冲区。子进程继承了输出缓冲区的副本,因此当子进程的cout 自动刷新时,Hello World 会打印到屏幕上。父级也打印Hello World

            如果在fork() 之前刷新cout,问题几乎肯定会消失。

            【讨论】:

            • 我不会说分析完全正确。子进程不是“在幕后重新运行”。
            • @MichaelMior:你是对的。我错过了“重新运行”位。我已经编辑了语言。
            【解决方案8】:

            如果你使用:

            std::cout << " Hello World" << std::flush;
            

            你只看到一个。我猜fork() 会复制std::cout 写入的任何输出缓冲区。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2012-01-12
              • 2012-10-04
              • 2019-07-17
              • 1970-01-01
              • 2016-12-07
              • 2020-05-08
              • 1970-01-01
              相关资源
              最近更新 更多