为什么“行缓冲区标准输出以确保线条原子立即写入”

时间:2015-04-13 15:57:46

标签: c linux wc

我正在阅读wc命令的源代码,在main函数中我找到了以下代码:

  /* Line buffer stdout to ensure lines are written atomically and immediately
     so that processes running in parallel do not intersperse their output.  */
  setvbuf (stdout, NULL, _IOLBF, 0);

那么为什么行缓冲区标准输出确保了?

1 个答案:

答案 0 :(得分:3)

假设块缓冲用于stdout而不是行缓冲。 (例如,如果stdout引用常规文件,则这是默认值。)让缓冲区大小为1024字节(以便每1024字节将输出刷新到文件中),并假装两个进程正在写入同一文件。

假设第一个进程当前在其I / O缓冲区中有1020个字节,并将行"foo_file 37\n"写入stdout。这会将"foo_"放在I / O缓冲区的末尾,将缓冲区刷新到文件中(因为缓冲区现在已满),然后将"file 37\n"放在缓冲区的开头。假设第二个进程随后出现并刷新其缓冲区,该缓冲区恰好以"bar_file 48\n"开头。输出文件中的结果行将是"foo_bar_file 48",这显然不是我们想要的。

基本问题是当使用块缓冲时,缓冲区边界不一定对应于线边界。

您可以使用以下程序的两个实例写入同一文件,以便自己查看此效果:

#include <stdio.h>

int main(void) {
    setvbuf (stdout, NULL, _IOLBF, 0);
    for (;;)
        puts("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
    return 0;
}

setvbuf()调用注释掉后,您会看到一些行与其他行混淆。请注意,这将使程序快速写入一个巨大的文件,当然。 :)