fork()调用打印的次数比预期的多

时间:2017-10-14 00:45:47

标签: c 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());
}

在大多数情况下,输出在跟踪时表现如预期。也就是说,如果我们以身份n开头,我们会打印n+1n+5。但是,当我打印起始进程ID时,它会被打印5次,我不知道为什么。任何帮助将不胜感激

示例运行的输出如下所示

  

启动进程ID为27252 pc @ pc-VirtualBox:〜/ Desktop $   开始porcess id是27252开始porcess id是27252开始   porcess id是27252 27253开始的porcess id是27252开始   进程ID是27252 27257

但我希望看到

  

凝视过程id为27252 27253 27257

2 个答案:

答案 0 :(得分:2)

这是因为printf正在缓冲输出,而不是立即将其刷新到设备。

因此,当您进行分叉时,进程的副本也会缓存该信息,每个进程都会输出完整的字符串。

你应该在每个分支前尝试调用fflush(stdout)(可能还有fsync(fileno(stdout)),具体取决于你的平台)。

答案 1 :(得分:1)

您的初始printf不会以换行符结束,默认情况下,连接到终端的stdout是行缓冲的。因此,当您fork时,stdout缓冲区不为空,并且当exit上的每个子进程刷新时,它会刷新它继承的缓冲区中剩余的相同数据。 / p>

要修复,请执行以下操作:

    fflush(stdout) 之前
  1. fork
  2. 使用_exit而不是exit退出分叉的子进程(这可以防止刷新缓冲区,尽管它依赖于实现,因此您无法保证,但它也会阻塞{{1}函数在子进程中执行,这通常是所希望的行为)
  3. 作为#1的可选替代或补充,您可以使用tcflush清除atexit之前的缓冲输出。