11

今天我了解到 stdout 在设置为终端时是行缓冲的,在不同情况下是缓冲的。因此,在正常情况下,如果我使用 printf() 而不使用终止 '\n',则只有在缓冲区已满时才会在屏幕上打印。如何获得这个缓冲区的大小,这个有多大?

4

4 回答 4

11

实际大小由各个实现定义;该标准没有规定最小尺寸(无论如何,基于我能够找到的内容)。不知道如何确定缓冲区的大小。

编辑

章节和诗句

7.19.3 文件

...
3 当流未缓冲时,字符应尽快从源或目标出现。否则,字符可能会作为一个块累积并传输到主机环境或从主机环境传输。当一个流被完全缓冲时,当缓冲区被填满时,字符将作为一个块传输到主机环境或从主机环境传输。当流被行缓冲时, 字符旨在在遇到换行符时作为块传输到主机环境或从主机环境传输。此外,当缓冲区被填满时,当在非缓冲流上请求输入时,或者当在需要从主机环境传输字符的行缓冲流上请求输入时,字符打算作为块传输到主机环境. 对这些特性的支持是由实现定义的,并且可能通过setbufsetvbuf函数受到影响。

重点补充。

“实现定义”不是“我不知道”的委婉说法,它只是一种声明,语言标准明确地将其留给实现定义行为。

话虽如此,有一种非编程方式可以找出答案;请查阅编译器的文档。“实现定义”还意味着实现必须记录行为:

3.4.1

1实现定义的行为
未指定的行为,其中每个实现都记录了如何做出选择

2 示例 实现定义的行为的一个例子是当有符号整数右移时高位的传播。
于 2012-06-05T20:29:36.337 回答
2

使用默认管道大小 64K 创建管道时的 Linux。在 /proc/sys/fs/pipe-max-size 中存在最大管道大小。对于默认值 1048576 是典型值。

对于 glibc 的默认文件缓冲区;65536 字节似乎是合理的。但是,由 glibc 源代码树中的 grep 确定: libio/libio.h:#define _IO_BUFSIZ _G_BUFSIZ sysdeps/generic/_G_config.h:#define _G_BUFSIZ 8192 sysdeps/unix/sysv/linux/_G_config.h:#define _G_BUFSIZ 8192

原来的问题可能会或可能不会被回答。对于一分钟的努力,最好的猜测是 8 KB。

对于单纯的行缓冲,8K 就足够了。但是,与 64K 相比,对于超过行缓冲的输出;8K 效率不高。因为对于默认管道大小,使用 64K,如果不希望有更大的管道大小,并且如果没有明确设置更大的管道大小,则建议 stdio 缓冲区使用 64K。

如果需要性能,那么微薄的 8K 缓冲区是不够的。通过 fcntl(pipefd,F_SETPIPE_SZ,1048576) 可以增加管道的大小。通过 setvbuf (stdout,buffer,_IOFBF,1048576) 可以替换 stdio 提供的文件缓冲区。如果不使用管道,则管道尺寸无关紧要。但是,如果在两个进程之间传输数据,那么通过增加管道大小可能会提高性能。否则,最小的缓冲区或最小的管道会产生瓶颈。

如果还通过 stdio 读取更大的缓冲区,则可能需要更少的读取函数调用。“可能”这个词暗示了一个重要的考虑因素。正如由单个读取函数调用提供的单个写入函数调用所提供的那样,可以读取尽可能多的数据。通过读取函数调用,可以预期返回的字节数少于请求的字节数。通过额外的读取函数调用,可以获得额外的字节。

用于写数据线;通过 stdio overkill 提供。但是,通过 stdio 行缓冲输出是可能的。在某些情况下,行缓冲输出是必不可少的。如果写入 proc 虚拟文件系统提供的文件或写入 sys 虚拟文件系统提供的文件,则应在单个写入缓冲区中包含换行字节。如果使用第二次写入,则可能会出现意想不到的结果。

如果读写和 stdio 混合使用,则存在警告。在调用 write 函数之前,需要调用 fflush 函数。因为 stderr 没有被缓冲;对于 stderr,不需要 fflush 函数调用。通过读取可能会提供少于预期的字节数。通过 stdio,之前的字节可能已经被缓冲了。

不混合 unistd 和 stdio I/O 是个好建议,但经常被忽略。混合缓冲输入是不合理的。混合无缓冲输入是可能的。混合缓冲输出是合理的。

通过 stdio 缓冲 IO 提供了便利。没有 stdio 缓冲 IO 是可能的。但是,对于代码,需要额外的字节。当利用足够大的缓冲区时;与 stdio 提供的输出功能相比;写函数调用不一定慢。

但是,当不涉及管道时,可以通过函数 mmap 提供高级 IO。在 mmap 的管道上,不会返回错误。但是,在地址空间中不提供数据。在 lseek 的管道上提供了一个错误。

最后由 man 3 setvbuf 提供了一个很好的例子。如果在堆栈上分配缓冲区,则在返回之前不能省略 fclose 函数调用。

实际的问题是“在 C 中,标准输出缓冲区的大小是多少?” 到 8192 可能会回答这么多。

遇到这种询问的人可能会对缓冲区输入/输出效率产生好奇。通过一些调查,目标是隐含的。通过对简洁答复的偏好,管道大小的重要性和缓冲区大小的重要性和 mmap 没有被解释。这个回复说明了。

于 2016-03-21T19:12:15.727 回答
0

这里有一些关于类似问题的非常有趣的答案。

在 linux 系统上,您可以查看不同函数的缓冲区大小,包括ulimit. 还有头文件limits.hpipe.h应该包含那种信息。

于 2012-06-05T20:29:28.640 回答
-2

您可以将其设置为无缓冲,或者只是刷新它。

当 C 运行时通常为您和一些示例刷新它时,这似乎有一些不错的信息。看看这个

于 2012-06-05T20:06:35.843 回答