设为首页 加入收藏

TOP

11.5.1 缓冲
2013-10-07 00:44:20 来源: 作者: 【 】 浏览:64
Tags:11.5.1 缓冲

11.5.1  缓冲

对于glibc,fread的实现过于复杂,因此我们这里选择MSVC的fread实现。但在阅读fread的代码之前,首先要介绍一下缓冲(Buffer)的概念。

缓冲最为常见于IO系统中,设想一下,当希望向屏幕输出数据的时候,由于程序逻辑的关系,可能要多次调用printf函数,并且每次写入的数据只有几个字符,如果每次写数据都要进行一次系统调用,让内核向屏幕写数据,就明显过于低效了,因为系统调用的开销是很大的,它要进行上下文切换、内核参数检查、复制等,如果频繁进行系统调用,将会严重影响程序和系统的性能。

一个显而易见的可行方案是将对控制台连续的多次写入放在一个数组里,等到数组被填满之后再一次性完成系统调用写入,实际上这就是缓冲最基本的想法。当读文件的时候,缓冲同样存在。我们可以在CRT中为文件建立一个缓冲,当要读取数据的时候,首先看看这个文件的缓冲里有没有数据,如果有数据就直接从缓冲中取。如果缓冲是空的,那么CRT就通过操作系统一次性读取文件一块较大的内容填充缓冲。这样,如果每次读取文件都是一些尺寸很小的数据,那么这些读取操作大多都直接从缓冲中获得,可以避免大量的实际文件访问。

除了读文件有缓冲以外,写文件也存在着同样的情况,而且写文件比读文件要更加复杂,因为当我们通过fwrite向文件写入一段数据时,此时这些数据不一定被真正地写入到文件中,而是有可能还存在于文件的写缓冲里面,那么此时如果系统崩溃或进程意外退出时,有可能导致数据丢失,于是CRT还提供了一系列与缓冲相关的操作用于弥补缓冲所带来的问题。C语言标准库提供与缓冲相关的几个基本函数,如表11-4所示。

表11-4

int fflush(< xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

FILE *stream)

flush指定文件的缓冲,若参数为NULL,则flush所有文件的缓冲

int setvbuf(

FILE *stream,

char *buf,

int mode,

size_t size )

设置指定文件的缓冲。缓冲类型(mode参数)有3种:

缓冲模式

常量(mode)

备注

无缓冲模式

_IONBF

该文件不使用任何缓冲

行缓冲模式

_IOLBF

仅对文本模式打开的文件有效,所谓行,即是指每收到一个换行符(\n\r\n),就将缓冲flush

全缓冲模式

_IOFBF

仅当缓冲满时才进行flush

 

void setbuf(

FILE *stream,

char *buf)

设置文件的缓冲,等价于

(void) setvbuf(stream, buf, _IOFBF, BUFSIZ).

所谓flush一个缓冲,是指对写缓冲而言,将缓冲内的数据全部写入实际的文件,并将缓冲清空,这样可以保证文件处于最新的状态。之所以需要flush,是因为写缓冲使得文件处于一种不同步的状态,逻辑上一些数据已经写入了文件,但实际上这些数据仍然在缓冲中,如果此时程序意外地退出(发生异常或断电等),那么缓冲里的数据将没有机会写入文件。flush可以在一定程度上避免这样的情况发生。

在这个表中我们还能看到C语言支持两种缓冲,即行缓冲(Line Buffer)和全缓冲(Full Buffer)。全缓冲是经典的缓冲形式,除了用户手动调用fflush外,仅当缓冲满的时候,缓冲才会被自动flush掉。而行缓冲则比较特殊,这种缓冲仅用于文本文件,在输入输出遇到一个换行符时,缓冲就会被自动flush,因此叫行缓冲。

【责任编辑:云霞 TEL:(010)68476606】

回书目   上一节   下一节

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇1.5 fread实现 下一篇3.1.5 使用虚拟串口

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: