fork()和输出

我有一个简单的程序:

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

程序执行后我的输出是: Hello World Hello World 。 为什么这会发生,而不是一个单一的Hello world ? 我猜测subprocess是在幕后重新运行的,输出缓冲区是在进程之间共享的,或者是沿着这些线的东西,但是这种情况还是发生了什么?

这不像你原先想的那样。 输出缓冲区不共享 – 当您执行fork时, 两个进程都会获得相同缓冲区的副本 。 所以,在fork之后,这两个进程最终都会刷新缓冲区并将内容分别打印到屏幕上。

这只发生,因为cout是缓冲的IO 。 如果您使用了未被缓冲的cerr,则应该只能看到一条消息,即pre-fork。

标准输出使用缓冲IO。 当调用fork() ,标准输出不会被刷新,并且缓冲的内容在subprocess中被复制。 当进程退出时,这些缓冲区被刷新,导致你看到的两个输出。

如果您将程序更改为:

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

你应该只看到一个。

因为你先调用fork()而不先冲洗所有的缓冲区。

 cout.flush(); fork(); 

输出"Hello World"的代码只执行一次。 问题是输出缓冲区没有被刷新。 所以当你fork这个进程时, "Hello World"仍然在输出缓冲区中。 当两个程序都退出时,它们的输出缓冲区将被刷新,你会看到输出两次。

certificate这一点的最简单的方法是在string末尾添加一个换行符,这将导致一个隐式刷新,或者用std::cout.flush();显式刷新std::cout.flush(); 。 那么你只会看到一次输出。

如果你使用:

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

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

string不会立即写入屏幕; 而是写入内部缓冲区。 subprocessinheritance了输出缓冲区的副本,所以当孩子的cout被自动刷新时, Hello World被打印到屏幕上。 父母也打印Hello World

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

原因是当你调用std::cout<<它并不真正执行输出,而是将数据留在系统的缓冲区中。 当你做叉时,代码和数据都被复制,以及所有相关的缓冲区。 最后,父亲和儿子把他们冲到标准输出,因此你看到输出重复。

你可能在这里看到的是缓冲的效果。 一般情况下,输出会被缓冲,直到显式刷新或隐式地执行一个像输出新行这样的操作。 因为输出被caching,分叉进程的两个副本都有缓冲区输出,因此在进程终止和刷新缓冲区时显示它