C中自动stdout缓冲区刷新的规则是什么?

时间:2016-09-16 16:28:18

标签: c buffer stdio

我只是好奇应该满足哪些条件才能自动刷新stdout缓冲区。

首先,我很困惑这个伪代码每次迭代都不打印输出:

while (1) {
    printf("Any text");
    sleep(1);
}

但如果我添加换行符,它会。

经过几次实验后,我发现在我的机器上stdout缓冲区被冲洗了:

  1. 当我输入1025个字符或更多字符时;
  2. 当我读到stdin;
  3. 当我将换行符添加到stdout时;
  4. 第一个条件是完全清楚的 - 当缓冲区已满时,应该刷新它。第二个也是合理的。但为什么换行符导致潮红?其他隐含条件是什么?

5 个答案:

答案 0 :(得分:9)

自动刷新stdout缓冲区的规则是实现定义(ID)。当流 unbuffered 完全缓冲行缓冲时,它是ID。

  

当流 unbuffered 时,字符应尽快从源或目的地出现。否则,可以将字符作为块累积并发送到主机环境或从主机环境发送。

     

当流完全缓冲时,当填充缓冲区时,字符将作为块传输到主机环境或从主机环境传输。

     

当流行缓冲时,当遇到换行符时,字符将作为块传输到主机环境或从主机环境传输。此外,当填充缓冲区,在无缓冲流上请求输入时,或者在需要从主机环境传输字符的行缓冲流上请求输入时,字符旨在作为块传输到主机环境。 。

     

对这些特征的支持是实现定义的,...C11dr§7.21.33

  

我只是好奇要自动刷新stdout缓冲区应满足哪些条件。

如果代码想要确保输出肯定是已刷新,请使用fflush()。可以自动刷新流的其他条件是实现定义的。

答案 1 :(得分:4)

the man page for setbuf(3)。默认情况下,stdout设置为行缓冲模式。

printf()及其变体使用缓冲输出,并委托给write()。因此,此缓冲由printf的C库实现控制,缓冲区和缓冲区设置位于FILE结构中。

同样值得注意的是unix手册页的第3节和第2节之间的区别。第2节由直接与操作系统通信的函数调用组成,并执行从纯用户程序无法完成的操作。第3节由用户可以自己复制的函数调用组成,这些函数调用通常委托给第2节调用。第2节功能包含低级"魔法"允许C程序与外部世界交互并执行I / O.第3节功能可以为第2节功能提供更方便的界面。

printfscanfgetcharfputs和其他FILE *函数都是委托给write()和{的第3部分函数{1}},这是第2部分的功能。 read()read()不缓冲。 write()printf()结构中的缓冲区进行交互,偶尔会决定通过FILE发送该缓冲区的内容。

答案 2 :(得分:3)

  • 每当输出换行符时,都应刷新行缓冲的输出流。

  • 每当尝试从任何行缓冲的输入流进行读取时,实现可以(但不是必须)刷新所有行缓冲的输出流。

  • 默认情况下,不允许实现使流完全缓冲,除非可以确定它们与“交互设备”无关。所以当stdin / stdout是终端时,它们不能完全缓冲,只能进行行缓冲(或无缓冲)。

如果您只需要在输出到终端时进行刷新,则可以假设写入换行符会导致刷新。否则,您应该在需要刷新的地方明确地调用fflush

答案 3 :(得分:1)

在很多情况下,流上的缓冲输出会自动刷新:

  1. 当您尝试输出并且输出缓冲区已满时。
  2. 当流关闭时。
  3. 当程序通过调用exit终止时。
  4. 当写入换行符时,如果流是行缓冲的。
  5. 每当任何流上的输入操作实际上从其文件中读取数据时。
  6. echo "$foo"; output: 10; 默认为行缓冲。

    如果您想在其他时间刷新缓冲的输出,可以调用fflush。

答案 4 :(得分:1)

Online C2011 standard

7.21.3档案
...
3当流 unbuffered 时,字符应从源或其中显示 目的地尽快。否则可能会累积字符 作为块传输到主机环境或从主机环境传输。当流完全缓冲时, 字符旨在作为块时传输到主机环境或从主机环境传输 填充缓冲区。 当流行缓冲时,字符应为 当换行字符时,作为块发送到主机环境或从主机环境发送 遇到。此外,字符旨在作为块传输到主机 填充缓冲区时,在无缓冲流上请求输入时的环境,或 当在需要传输的线路缓冲流上请求输入时 来自主机环境的字符。支持这些特征是 实施定义,可能会受到setbufsetvbuf函数的影响 ...
7在程序启动时,预定义了三个文本流,无需显式打开 - 标准输入(用于读取传统输入),标准输出(用于写入 常规输出)和标准错误(用于写入诊断输出)。最初 打开后,标准错误流未完全缓冲; 标准输入和标准 当且仅当可以确定流不被引用时,输出流被完全缓冲 到交互式设备。

因此,行缓冲流将在换行符上刷新。在我经验丰富的大多数系统上,stdout在交互式会话中进行行缓冲。