让子进程将printf正确地重定向到标准输出

问题描述

我正在使用stdout重定向一个进程上的freopen(),只要它是一个进程,就可以了。

但是,如果我做这样的事情:

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++;
    }

最初打印的行会一遍又一遍地重新打印在文件上。我有什么特别的措施可以避免这种情况的发生?

解决方法

一遍又一遍地将第一行打印的行重新打印在文件上。

这是因为在使用stdio函数时,标准C库将 buffering 应用于标准输出流。特别是,当stdout重定向到文件时,缓冲模式将从行缓冲更改为完全缓冲(使用库定义的大小的缓冲区)。在行缓冲模式下,仅当遇到换行符时才刷新缓冲区(并实际写入数据),但 在完全缓冲模式下仅在达到最大缓冲区大小时才会发生。

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

我应该采取什么特别措施来避免这种情况的发生?

是的。在创建子代之前先冲洗缓冲区。

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

// ...

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

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

    i++;
}