【问题标题】:When can i expect "stdout" printed to console我什么时候可以期待“stdout”打印到控制台
【发布时间】:2013-07-15 15:30:16
【问题描述】:

我知道这是因为 stdout 的缓冲,但是我什么时候可以在下面的程序中期望 stdout 的输出。如果我运行,我总是得到“stderr”作为输出。如果我添加 '\n' 或 fflush(stdout) 那么只有我得到两个语句。如果我不添加 '\n' 或 fflush(stdout),我不会得到“stdout”作为输出。如果我不添加 '\n' 或 fflush(stdout),我什么时候才能得到所有缓冲的“stdout”作为输出。

#include <stdio.h>
#include <unistd.h>
int main()
{
      for(;;)
      {
              fprintf(stdout,"stdout");
              fprintf(stderr,"stderr");
              sleep(1);
      }
      return 0;
} 

【问题讨论】:

    标签: c linux


    【解决方案1】:

    确实,新行或刷新,因为默认情况下stdout 在引用终端设备时是行缓冲的。

    更准确地说:标准输入和标准输出是完全缓冲的,当且仅当它们不引用交互式设备时。标准错误永远不会完全缓冲。

    关于行缓冲,引用自APUE

    行缓冲有两个注意事项。首先,标准 I/O 库用于收集每一行的缓冲区大小是固定的,因此如果我们在写入换行符之前填充此缓冲区,则可能会发生 I/O。其次,每当通过标准 I/O 库从 (a) 无缓冲流或 (b) 行缓冲流(需要从内核请求数据)请求输入时,所有行缓冲输出流都会被刷新。 (b) 上的限定词的原因是请求的数据可能已经 在缓冲区中,不需要从内核读取数据。显然,来自无缓冲流的任何输入(项目 (a))都需要从内核获取数据。

    要将其更改为无缓冲,请使用setvbuf

    setvbuf(stdout, NULL, _IONBF, 0);
    

    【讨论】:

    • 我的问题是,如果我不添加 '\n' 或 fflush(stdout),那么所有缓冲的标准输出何时会打印到控制台
    • @Chinna 当标准输出文件 * 的内部缓冲区已满时。该缓冲区的大小取决于平台,但通常为 1024 或 4096 字节。
    【解决方案2】:

    发送到 stderr 的输出通常会立即打印。它是标准错误输出。当然,错误应该立即显示,因此任何存在的缓冲区都会立即刷新。

    另一方面,stdout 是缓冲的。打印出该缓冲区因语言而异,但通常至少需要以下两项之一:/n,或其他类型的换行符,或.flush();。如果您不提供这些选项,那么通常您必须等待缓冲区填满。这可能需要任何时间,因为它几乎完全取决于缓冲区的大小。

    按照惯例,处理流的方式是您将尽可能多的信息塞入其中,然后调用.flush()。如果缓冲区恰好在此期间填满,则数据将被发送到它要去的任何地方,并且缓冲区再次开始填满。

    不过,在这里,您正在填充一个接收文本的缓冲区。与二进制信息相比,文本并没有真正占用大量空间(这是一个非常主观的陈述,应该松散地解释),因此填充缓冲区可能需要相当长的时间。

    最好的做法是,在您“输入”完所有要打印的文本后,手动刷新流 (stdout)。

    【讨论】:

      【解决方案3】:

      fprintf 默认是行缓冲的。您可以通过调用 setvbuf 来改变行为。它允许您将其设置为“无缓冲”、“行缓冲”或“完全缓冲”。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-02-02
        • 2018-04-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-05
        • 2012-09-27
        • 1970-01-01
        相关资源
        最近更新 更多