2017-10-14 98 views
-1

的代码看起来是这样的fork()调用打印更多的时间比预期的

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
int main() { 
printf("Starting process id is %d\t", getpid()); 
if (fork() == 0) 
fork(); 
else { 
fork(); 
fork(); 
exit(0); 
} 
printf("%d\t", getpid()); 
} 

对于输出像预期的那样在那里追踪的大部分。也就是说,如果我们开始与ID n我们得到被打印n+1n+5。但是,当我打印启动进程ID它打印5次,我不知道为什么。任何帮助,将不胜感激

从样本来看

输出看起来像这样

开始的进程ID是27252 PC @ PC-VirtualBox的:〜/桌面$ 开始porcess ID是27252起porcess ID是27252启动 porcess ID是27252 27253起porcess ID是27252起 进程ID是27252 27257

不过我本来期望看到

凝望进程ID是27252 27253 27257

+0

你什么输出,以及你期望什么样的产出? – aschepler

+0

叉/行缓冲多重复数据删除:( –

回答

1

你的初始printf不换行结束,并且通过连接到终端默认stdout被行缓冲。因此,当你fork,在stdout缓冲区不是空的,并且当每个子进程上exit刷新,它刷新留在它继承了缓冲区中的数据相同。

要解决,做到以下几点:

  1. fflush(stdout)荷兰国际集团
  2. 退出之前fork_exit的派生的子进程,而不是exit(这可以防止刷新缓冲区,但它的实现依赖于这样你就可以“T作出保证,但是它也阻止在子进程来执行,这通常是所希望的行为)
  3. 作为一种可选的替代或补充#1 atexit功能,则可以使用tcflush到清除_exit之前的缓冲输出。
+0

所以,如果我理解正确,当我打电话的printf()什么我尝试打印,而我的程序正在运行保存在一个缓冲区,然后当程序终止缓冲区被打印到标准输出? – Mitchel0022

+0

@ Mitchel0022:通常的规则是'stderr'没有缓冲,'stdout'在连接到终端时被行缓冲(所以当它看到输出中的换行符或底层缓冲区填充时,先冲洗缓冲区),和“stdout”连接到其他任何东西,并且所有其他打开的句柄都被块缓冲(所以它们在缓冲区填充时进行刷新,缓冲区的大小被定义为实现)。当手柄关闭时(也就是在程序退出时隐式发生),缓冲区也被刷新,这就是为什么你所有的孩子都在打印。 – ShadowRanger

+0

啊,用'\ n'替换'\ t'确实强制它清除缓冲区。谢谢你的解释 – Mitchel0022

2

这是因为printf是缓冲你的输出,没有立即刷新到该设备。

所以,当你叉,过程的副本具有缓冲的信息和各过程将输出完整的字符串。

在每次分岔之前,您应该尝试拨打fflush(stdout)(并且可能还有fsync(fileno(stdout)),具体取决于您的平台)。

+0

大谢谢! – Mitchel0022