我只是好奇应该满足哪些条件才能自动刷新stdout缓冲区。
首先,我很困惑这个伪代码每次迭代都不打印输出:
while (1) {
printf("Any text");
sleep(1);
}
但如果我添加换行符,它会。
经过几次实验后,我发现在我的机器上stdout缓冲区被冲洗了:
第一个条件是完全清楚的 - 当缓冲区已满时,应该刷新它。第二个也是合理的。但为什么换行符导致潮红?其他隐含条件是什么?
答案 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节功能提供更方便的界面。
printf
,scanf
,getchar
,fputs
和其他FILE *
函数都是委托给write()
和{的第3部分函数{1}},这是第2部分的功能。 read()
和read()
不缓冲。 write()
与printf()
结构中的缓冲区进行交互,偶尔会决定通过FILE
发送该缓冲区的内容。
答案 2 :(得分:3)
每当输出换行符时,都应刷新行缓冲的输出流。
每当尝试从任何行缓冲的输入流进行读取时,实现可以(但不是必须)刷新所有行缓冲的输出流。
默认情况下,不允许实现使流完全缓冲,除非可以确定它们与“交互设备”无关。所以当stdin / stdout是终端时,它们不能完全缓冲,只能进行行缓冲(或无缓冲)。
如果您只需要在输出到终端时进行刷新,则可以假设写入换行符会导致刷新。否则,您应该在需要刷新的地方明确地调用fflush
。
答案 3 :(得分:1)
在很多情况下,流上的缓冲输出会自动刷新:
echo "$foo";
output: 10;
默认为行缓冲。
如果您想在其他时间刷新缓冲的输出,可以调用fflush。
答案 4 :(得分:1)
7.21.3档案
...
3当流 unbuffered 时,字符应从源或其中显示 目的地尽快。否则可能会累积字符 作为块传输到主机环境或从主机环境传输。当流完全缓冲时, 字符旨在作为块时传输到主机环境或从主机环境传输 填充缓冲区。 当流行缓冲时,字符应为 当换行字符时,作为块发送到主机环境或从主机环境发送 遇到。此外,字符旨在作为块传输到主机 填充缓冲区时,在无缓冲流上请求输入时的环境,或 当在需要传输的线路缓冲流上请求输入时 来自主机环境的字符。支持这些特征是 实施定义,可能会受到setbuf
和setvbuf
函数的影响 ...
7在程序启动时,预定义了三个文本流,无需显式打开 - 标准输入(用于读取传统输入),标准输出(用于写入 常规输出)和标准错误(用于写入诊断输出)。最初 打开后,标准错误流未完全缓冲; 标准输入和标准 当且仅当可以确定流不被引用时,输出流被完全缓冲 到交互式设备。
因此,行缓冲流将在换行符上刷新。在我经验丰富的大多数系统上,stdout
在交互式会话中进行行缓冲。