为什么标准输出缓冲?
Why is stdout buffering?
我正在努力学习 libuv
api 并编写了以下测试:
#include <stdio.h>
#include <stdlib.h>
#include <uv.h>
void timer_cb(uv_timer_t* timer) {
int* i = timer->data;
--*i;
if(*i == 0) {
uv_timer_stop(timer);
}
printf("timer %d\n", *i);
//fflush(stdout);
}
int main() {
uv_loop_t* loop = uv_default_loop();
uv_timer_t* timer = malloc(sizeof(uv_timer_t));
uv_timer_init(loop, timer);
int i = 5;
timer->data = &i;
uv_timer_start(timer, timer_cb, 1000, 2000);
uv_run(loop, UV_RUN_DEFAULT);
printf("Now quitting.\n");
uv_close(timer, 0);
uv_loop_close(loop);
return 0;
}
当运行它时,直到程序完成运行ning,才显示任何输出,然后一次显示所有输出。如果我取消注释 fflush
行,它会按预期工作,每 2 秒写入一次。
有人可以给我解释一下吗?为什么 stdout
没有在换行符之后刷新,正如 here 和其他地方所解释的那样?为什么我需要手动冲洗它?
流缓冲是实现定义的。
根据 7.21.3 文件,C Standard 的第 3 段:
When a stream is
unbuffered, characters are intended to appear from the source or at the destination as soon as possible. Otherwise characters
may be accumulated and transmitted to or from the host
environment as a block. When a stream is
fully buffered, characters are intended to be transmitted to or from the host environment as a block when a buffer is filled. When a
stream is
line buffered, characters are intended to be transmitted to or from the host environment as a block when a new-line
character is encountered. Furthermore, characters are intended to be
transmitted as a block to the host environment when a buffer is
filled, when input is requested on an unbuffered stream, or when
input is requested on a line buffered stream that requires
the transmission of characters from the host
environment. Support for these characteristics is
implementation-defined, and may be affected via the setbuf
and
setvbuf
functions.
缓冲的类型取决于您的实现,并且您的实现在您的示例中显然不是行缓冲。
没有严格的要求,stdout
是行缓冲的。它也可能被完全缓冲(或根本没有缓冲),在这种情况下 \n
不会触发刷新流。
C11 (N1570) 7.21.3/7 文件:
As initially opened, the standard error stream is not fully buffered;
the standard input and standard output streams are fully buffered if
and only if the stream can be determined not to refer to an
interactive device.
C11 (N1570) 5.1.2.3/7 程序执行:
What constitutes an interactive device is implementation-defined.
您可以尝试通过 setvbuf
标准函数强制执行特定类型的缓冲。例如,要为 stdout
设置行缓冲,您可以尝试使用:
setvbuf(stdout, buff, _IOLBF, size);
其中 buff
声明为 size
个元素的字符数组(例如 1024)。
请注意,必须在对流执行任何其他 I/O 操作之前调用 setvbuf
。
出于某种原因,您的系统认为您的标准输出不是交互式的。你是在做一些奇怪的 stdout 重定向还是在你的终端上做一些奇怪的事情?您应该能够使用 setbuf 进行覆盖,或者您可以使用 stderr 而不是 stdout。
我正在努力学习 libuv
api 并编写了以下测试:
#include <stdio.h>
#include <stdlib.h>
#include <uv.h>
void timer_cb(uv_timer_t* timer) {
int* i = timer->data;
--*i;
if(*i == 0) {
uv_timer_stop(timer);
}
printf("timer %d\n", *i);
//fflush(stdout);
}
int main() {
uv_loop_t* loop = uv_default_loop();
uv_timer_t* timer = malloc(sizeof(uv_timer_t));
uv_timer_init(loop, timer);
int i = 5;
timer->data = &i;
uv_timer_start(timer, timer_cb, 1000, 2000);
uv_run(loop, UV_RUN_DEFAULT);
printf("Now quitting.\n");
uv_close(timer, 0);
uv_loop_close(loop);
return 0;
}
当运行它时,直到程序完成运行ning,才显示任何输出,然后一次显示所有输出。如果我取消注释 fflush
行,它会按预期工作,每 2 秒写入一次。
有人可以给我解释一下吗?为什么 stdout
没有在换行符之后刷新,正如 here 和其他地方所解释的那样?为什么我需要手动冲洗它?
流缓冲是实现定义的。
根据 7.21.3 文件,C Standard 的第 3 段:
When a stream is unbuffered, characters are intended to appear from the source or at the destination as soon as possible. Otherwise characters may be accumulated and transmitted to or from the host environment as a block. When a stream is fully buffered, characters are intended to be transmitted to or from the host environment as a block when a buffer is filled. When a stream is line buffered, characters are intended to be transmitted to or from the host environment as a block when a new-line character is encountered. Furthermore, characters are intended to be transmitted as a block to the host environment when a buffer is filled, when input is requested on an unbuffered stream, or when input is requested on a line buffered stream that requires the transmission of characters from the host environment. Support for these characteristics is implementation-defined, and may be affected via the
setbuf
andsetvbuf
functions.
缓冲的类型取决于您的实现,并且您的实现在您的示例中显然不是行缓冲。
没有严格的要求,stdout
是行缓冲的。它也可能被完全缓冲(或根本没有缓冲),在这种情况下 \n
不会触发刷新流。
C11 (N1570) 7.21.3/7 文件:
As initially opened, the standard error stream is not fully buffered; the standard input and standard output streams are fully buffered if and only if the stream can be determined not to refer to an interactive device.
C11 (N1570) 5.1.2.3/7 程序执行:
What constitutes an interactive device is implementation-defined.
您可以尝试通过 setvbuf
标准函数强制执行特定类型的缓冲。例如,要为 stdout
设置行缓冲,您可以尝试使用:
setvbuf(stdout, buff, _IOLBF, size);
其中 buff
声明为 size
个元素的字符数组(例如 1024)。
请注意,必须在对流执行任何其他 I/O 操作之前调用 setvbuf
。
出于某种原因,您的系统认为您的标准输出不是交互式的。你是在做一些奇怪的 stdout 重定向还是在你的终端上做一些奇怪的事情?您应该能够使用 setbuf 进行覆盖,或者您可以使用 stderr 而不是 stdout。