fork() 和输出
- 2024-11-01 08:41:00
- admin 原创
- 42
问题描述:
我有一个简单的程序:
int main()
{
std::cout << " Hello World";
fork();
}
程序执行后,我的输出是:Hello World Hello World
。为什么会发生这种情况而不是单个Hello world
?我猜测子进程在后台重新运行,并且输出缓冲区在进程之间共享或类似的事情,但情况确实如此还是发生了其他事情?
解决方案 1:
这和你最初的想法不太一样。输出缓冲区不共享 - 当你执行 fork 时,两个进程都会获得同一个缓冲区的副本。因此,在 fork 之后,两个进程最终都会刷新缓冲区并分别将内容打印到屏幕上。
这种情况只会因为 cout 是缓冲 IO 而发生。如果你使用非缓冲的 cerr,你应该只会看到一次消息,即预分叉。
解决方案 2:
标准输出使用缓冲 IO。调用时,fork()
标准输出不会被刷新,缓冲内容会被复制到子进程中。进程退出时,这些缓冲区会被刷新,从而产生您看到的两个输出。
如果将程序更改为:
std::cout << " Hello World;" << std::endl;
您应该只看到一个。
解决方案 3:
因为您在没有先刷新所有缓冲区的情况下就调用了 fork()。
cout.flush();
fork();
解决方案 4:
输出的代码"Hello World"
只执行一次。问题是输出缓冲区没有被刷新。因此,当您分叉进程时,"Hello World"
仍然位于输出缓冲区中。当两个程序都退出时,它们的输出缓冲区将被刷新,您将看到两次输出。
演示此操作的最简单方法是在字符串末尾添加换行符,这将导致隐式刷新,或使用 显式刷新std::cout.flush();
。然后您只会看到一次输出。
解决方案 5:
如果您使用:
std::cout << " Hello World" << std::flush;
您只能看到一个。我猜fork()
是复制输出缓冲区std::cout
写入的内容。
解决方案 6:
该字符串不会立即写入屏幕;而是写入内部缓冲区。子进程继承了输出缓冲区的副本,因此当子进程的cout
自动刷新时,Hello World
会将 打印到屏幕上。父进程也会打印Hello World
。
如果您cout
在之前冲洗fork()
,问题几乎肯定会消失。
解决方案 7:
原因是,调用std::cout<<
它时实际上并没有执行输出本身,而是将数据留在系统的缓冲区中。执行 fork 时,代码和数据以及所有相关缓冲区都会被复制。最后,父进程和子进程都会将它们刷新到标准输出,因此您会看到输出被复制。
解决方案 8:
您在这里看到的可能是缓冲的效果。通常,输出会被缓冲,直到明确刷新或隐式执行(例如输出新行)为止。由于输出被缓冲,因此分叉进程的两个副本都具有缓冲输出,因此在进程终止并刷新缓冲区时都会显示它
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件