为什么程序输出重定向会导致其子进程的输出乱序?

pab*_*ouk 2 c subprocess buffering io-redirection

在我在 Linux 上运行的 C 程序中,它使用创建子进程system()我注意到,当我将stdout重定向到管道或文件时,子进程的输出在缓冲 I/O 函数的输出之前发送,例如printf(). 当stdout被留在终端时,输出按预期顺序排列。我将程序简化为以下示例:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    printf("1. output from printf()\n");
    system("echo '2. output from a command called using system()'");

    return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)

stdout进入终端时的预期输出:

$ ./iobuffer
1. output from printf()
2. output from a command called using system()
Run Code Online (Sandbox Code Playgroud)

stdout重定向到管道或文件时的输出乱序:

$ ./iobuffer | cat
2. output from a command called using system()
1. output from printf()
Run Code Online (Sandbox Code Playgroud)

Mar*_*ers 5

终端通常使用行缓冲,而管道将使用块缓冲。

这意味着您的printf调用(包括换行符)将填充行缓冲区,从而触发刷新。重定向时,在程序完成之前不会发生刷新。

echo另一方面,当完成时总是刷新它正在写入的缓冲区。

使用行缓冲(终端输出),顺序为:

  • printf()用换行符打印一行,刷新缓冲区,您会看到1. output from printf()正在打印。
  • echo写入输出,退出,刷新缓冲区,你会看到2. output from a command called using system()打印出来的。

使用块缓冲,顺序是:

  • printf() 用换行符打印一行,而不是完全填充缓冲区。
  • echo写入输出,退出,刷新缓冲区,你会看到2. output from a command called using system()打印出来的。
  • 您的程序退出,刷新其块缓冲区,您会看到1. output from printf()正在打印。

您的选项是用来冲洗明确使用fflush()或设置缓冲上stdout与明确setvbuf()