我正在编写一个小程序,它根据不同的事件有各种控制台输出字符串。当我查找发送这些消息的最佳方式时,我遇到了一些有点令人困惑的事情。
我已经读过stderr
用于直接向控制台发送消息 - not buffered
。相反,我读到stdout
是buffered
,并且通常用于将消息重定向到各种streams?
,可能是也可能不是错误消息,输出文件或其他介质。
当某些东西被称为缓冲而不是缓冲时有什么区别?当我读到消息是直接射到输出并且不缓冲时,这是有道理的。但同时我意识到我并不完全确定缓冲是什么意思。
答案 0 :(得分:3)
通常,stdout是行缓冲的,这意味着发送到stdout的字符“堆叠”直到换行符到达,此时全部输出。
答案 1 :(得分:2)
缓冲流是指在一定阈值之前继续写入的流。此阈值可以是特定字符,如Konrad提到的行缓冲,或其他阈值,例如写入的特定字符数。
缓冲旨在加快输入/输出操作。计算机执行的最慢的事情之一是写入流(无论是控制台还是文件)。当不需要立即看到东西时,它可以节省一段时间来存储它。
您是对的,stderr
通常是无缓冲的流,而stdout
通常是缓冲的。因此,有时您可以将内容输出到stdou
,然后输出到stderr
,并且stderr
首先出现在控制台上。如果您想使stdout
行为相似,则每次写入后都必须flush
。
答案 2 :(得分:2)
当缓冲输出流时,这意味着当您告诉它时,流不一定输出数据。每个IO操作可能会产生大量开销,因此大量的小IO操作可能会造成瓶颈。通过缓冲IO操作然后立即刷新多个操作,可以减少这种开销。
虽然stdout
和stderr
在缓冲方面可能表现不同,但这通常不是它们之间的决定因素,不应该依赖。如果您绝对需要立即输出,请始终手动flush
流。
答案 3 :(得分:1)
假设
int main(void)
{
printf("foo\n");
sleep(10);
printf("bar\n");
}
在控制台上执行时
$ ./a.out
您将看到foo
行,10秒后bar
行( - >行缓冲)。将输出重定向到文件或管道时
$ ./a.out > /tmp/file
文件保持为空( - >缓冲),直到程序终止( - >退出时隐式fflush())。
如果上面的行不包含\n
,则在程序终止之前,您不会在控制台上看到任何内容。
在内部,printf()
将一个字符添加到缓冲区。为了让事情变得更轻松,让我来描述一下fputs(char const *s, FILE *f)
而不是。 FILE
可能被定义为
struct FILE {
int fd; /* is 0 for stdin, 1 for stdout, 2 for stderr (usually) */
enum buffer_mode mode;
char buf[4096];
size_t count; /* number of chars in buf[] */
};
typedef struct FILE *FILE;
int fflush(FILE *f)
{
write(f->fd, f->buf, f->count);
f->count = 0;
}
int fputc(int c, FILE *f)
{
if (f->count >= ARRAY_SIZE(f->buf))
fflush(f);
f->buf[f->count++] = c;
}
int fputs(char const *s, FILE *f)
{
while (*s) {
char c = *s++;
fputc(c, f);
if (f->mode == LINE_BUFFERED && c == '\n')
fflush(f);
}
if (f->mode == UNBUFFERED)
fflush(f);
}