当前位置:嗨网首页>书籍在线阅读

25-控制缓冲

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

3.13 控制缓冲

标准I/O实现了三种类型的用户缓冲,并为开发者提供了接口,可以控制缓冲区类型和大小。以下不同类型的用户缓冲提供不同功能,并适用于不同的场景:

无缓冲(Unbuffered)

不执行用户缓冲。数据直接提交给内核。因为这种无缓冲模式不支持用户缓冲(而用户缓冲一般会带来很多好处),通常很少使用,只有一个例外:标准错误默认是采用无缓冲模式。

行缓冲(Line-buffered)

缓冲是以行为单位执行。每遇到换行符,缓冲区就会被提交到内核。行缓冲对把流输出到屏幕时很有用,因为输出到屏幕的消息也是通过换行符分隔的。因此,行缓冲是终端的默认缓冲模式,比如标准输出。

块缓冲(Block-buffered)

缓冲以块为单位执行,每个块是固定的字节数。本章一开始讨论的缓冲模式即块缓冲,它很适用于处理文件。默认情况下,和文件相关的所有流都是块缓冲模式。标准I/O称块缓冲为“完全缓冲(full buffering)”。

大部分情况下,默认的缓冲模式即对于特定场景是最高效的。但是,标准I/O还提供了一个接口,可以修改使用的缓冲模式:

121.png setbuf()函数把指定stream的缓冲模式设置成mode模式,mode值必须是以下之一:

_IONBF 无缓冲。

_IOLBF 行缓冲。

_IOFBF 块缓冲。

_ IONBF无缓冲模式下,会忽略参数buf和size;对于其他模式,buf可以指向一个size字节大小的缓冲空间,标准I/O会用它来执行对给定流的缓冲。如果buf为空,glibc会自动分配指定size的缓冲区。

setvbuf()函数必须在打开流后,并在执行任何操作之前被调用。成功时,返回0;出错时,返回非0值。

在关闭流时,其使用的缓冲区必须存在。一个常见的错误是把缓冲区定义成某个作用域中的一个局部变量,在关闭流之前就退出这个作用域了。特别需要注意的是,不要在main()函数中定义一个局部缓冲区,且没有显式关闭流。比如以下代码存在bug:

122.png 这类错误可以通过两种方式来解决:一是在离开作用域之前显式关闭流,二是把buf设置成全局变量。

总体而言,开发者不需要关心如何在流上使用缓冲。对于标准出错,终端是采用行缓冲模式;对于文件,采用块缓冲模式。默认的块缓冲区大小是BUFSIZ,在<stdio.h>中定义,而且通常情况下该大小设置是最优的(一个较大值,是标准块大小的整数倍)。