C++ fork()和输出
我有一个简单的程序:C++ fork()和输出,c++,linux,unix,fork,C++,Linux,Unix,Fork,我有一个简单的程序: int main() { std::cout << " Hello World"; fork(); } intmain() { std::cout如果您使用: std::cout << " Hello World" << std::flush; std::cout字符串不会立即写入屏幕,而是写入内部缓冲区。子进程继承输出缓冲区的副本,因此当子进程的cout自动刷新时,Hello World会打印到屏幕上。父进程也会打印
int main()
{
std::cout << " Hello World";
fork();
}
intmain()
{
std::cout如果您使用:
std::cout << " Hello World" << std::flush;
std::cout字符串不会立即写入屏幕,而是写入内部缓冲区。子进程继承输出缓冲区的副本,因此当子进程的cout
自动刷新时,Hello World
会打印到屏幕上。父进程也会打印Hello World
如果在fork()之前刷新cout
,问题几乎肯定会消失。标准输出使用缓冲IO。当fork()
被称为标准输出未刷新,缓冲内容在子进程中复制。这些缓冲区在进程退出时刷新,从而产生您看到的两个输出
如果将程序更改为:
std::cout << " Hello World;" << std::endl;
std::cout因为调用fork()时没有首先刷新所有缓冲区
cout.flush();
fork();
这与您最初的想法不同。输出缓冲区不是共享的-当您执行fork时,两个进程都会获得同一缓冲区的副本。因此,fork之后,两个进程最终会刷新缓冲区并将内容分别打印到屏幕上
发生这种情况的唯一原因是cout是缓冲IO。。如果使用未缓冲的cerr,您应该只会看到一次消息,pre fork。您可能在这里看到的是缓冲的效果。通常,输出会被缓冲,直到显式刷新或隐式完成,例如输出新行。由于输出是缓冲的,分叉进程的两个副本都有缓冲的输出,因此在进程终止并刷新缓冲区时都会显示输出。要输出的代码只执行一次。问题是输出缓冲区没有刷新。因此,分叉进程时,“Hello World”
仍在输出缓冲区中。当两个程序退出时,它们的输出缓冲区将被刷新,您将看到两次输出
证明这一点的最简单方法是在字符串末尾添加一个换行符,这将导致隐式刷新,或显式刷新std::cout.flush();
。那么您只会看到一次输出。原因是当您调用std::coutt时,这就是fork的作用,它使用父进程的内存生成进程。确实有很多fork()
最近的问题…嗯…嗯…子进程在调用fork之后开始执行程序的代码。因此子进程无法执行fork之上的代码。我不认为是访问。我认为是操作系统类。请参阅最新的refactormycode.com:我不会说分析完全正确。子进程不是“在幕后重新运行”。@MichaelMior:你说得对。我错过了“重新运行”部分。我编辑了语言。这只是因为cout是用户空间缓冲IO^_^