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,分叉进程的两个副本都有缓冲区输出,因此在进程终止和刷新缓冲区时显示它