让子进程 printf 正确重定向 stdout

Having child processes printf to redirected stdout correctly

我正在使用 freopen() 重定向 stdout 一个进程,只要它只是一个进程,一切都很好。

但是,如果我这样做:

freopen("stdout.txt", "a+", stdout);
printf("Initial line.\n");

int i=0;
while(i<1000)
    {
        if(fork())
            wait(NULL);
        else
            printf("Line %d.\n", i);
        i++;
    }

最初打印的行一遍又一遍地重新打印在文件上。我应该做些什么来避免这种情况发生?

The first printed lines are re-printed on the file over and over.

这是因为标准 C 库在使用 stdio 函数时将 缓冲 ​​ 应用于标准输出流。特别是,当 stdout 被重定向到一个文件时,缓冲模式从 line-buffered 变为完全缓冲(具有由库定义的大小的缓冲区)。在 line-buffered 模式下,仅当遇到换行符时才刷新缓冲区(以及实际写入的数据), 但是 在完全缓冲模式下,这仅在最大缓冲区大小为达到。

当您创建多个进程时,它们都共享 parent 的同一个缓冲区。由于在生成新 children 之前您没有到达缓冲区的末尾,并且您没有清空它,因此它们都将具有相同的缓冲区内容。之后,当每个 children 死亡时,缓冲区将被标准库自动刷新。

Is there anything particular I should do to avoid this from happening?

是的。在创建 children.

之前刷新缓冲区
freopen("stdout.txt", "a+", stdout);
printf("Initial line.\n");
fflush(stdout);

// ...

您可能还想 exit() 在 child 完成其工作后的下一个周期之前:

int i=0;
while(i<1000)
{
    if(fork()) {
        wait(NULL);
    } else {
        printf("Line %d.\n", i);
        exit(0);
    }

    i++;
}