C - 标准输出和标准输出 - 未缓冲与缓冲



我正在编写一个小程序,该程序根据不同的事件具有各种控制台输出字符串。当我查找发送这些消息的最佳方式时,我遇到了一些有点令人困惑的事情。

我已经读到stderr用于将消息直接发送到控制台 - not buffered.相比之下,我读到stdoutbuffered的,通常用于将消息重定向到各种streams?,这可能是也可能不是错误消息,输出文件或其他介质。

当某物被称为缓冲和不缓冲时,有什么区别?当我阅读消息直接拍摄到输出并且没有缓冲时,这是有道理的。但与此同时,我意识到我不完全确定缓冲意味着什么。

通常,stdout 是行缓冲的,这意味着发送到 stdout 的字符"堆叠",直到换行符到达,此时全部输出。

缓冲

流是你一直写入到某个阈值的流。 此阈值可以是特定字符,如 Konrad 提到的行缓冲,也可以是另一个阈值,例如写入的特定字符数。

缓冲旨在加快输入/输出操作的速度。 计算机执行的最慢的操作之一是写入流(无论是控制台还是文件)。 当东西不需要立即看到时,可以节省时间将其存放一段时间。

你是对的,stderr通常是未缓冲的流,而stdout通常是缓冲的。 因此,有时您可以将内容输出到 stdou t,然后输出到 stderrstderr首先出现在控制台上。 如果你想让stdout的行为相似,你必须在每次写入后flush它。

当输出流被缓冲时,这意味着该流不一定在您告诉它时输出数据。每个 IO 操作可能会产生大量开销,因此大量小 IO 操作可能会造成瓶颈。通过缓冲 IO 操作,然后一次刷新多个操作,可以减少此开销。

虽然stdoutstderr在缓冲方面的行为可能不同,但这通常不是它们之间的决定因素,不应依赖。如果您绝对需要立即输出,请始终手动flush流。

假设

int main(void)
{
    printf("foon");
    sleep(10);
    printf("barn");
}

在控制台上执行时

$ ./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);
}

相关内容

  • 没有找到相关文章

最新更新