1. 数据缓冲区
C 程序员经常使用动态分配的缓冲区(通过调用 malloc() / free() 函数)在函数之间传递数据
2. 为什么需要缓冲
首先在若干字符作为一个块传输比逐个发送字符耗费的时间少。其次如果你输入有误。就可以使用您的键盘更改功能来修正错误。并且最终按下回车,就可以发送正确的输入
3. 缓冲区的分类
缓冲分为两类,完全缓冲和行缓冲
1.对于完全缓冲来说,缓冲区满时,缓冲区会被清空。此时缓冲区中的内容也会发往目的地。这种类型的缓冲通常出现在文件输入中。第一次执行I/O操作时,ANSI标准的文件管理函数通过调用malloc函数获得需要使用的缓冲区,默认大小为8192
//come from /usr/include/stdio.h
#ifndef BUFSIZ
# define BUFSIZ _IO_BUFSIZ //BUFSIZ 全局宏定义
#endif
//come from /usr/include/libio.h
#define _IO_BUFSIZ _G_BUFSIZ
//come from /usr/include/_g_config.h
#define _G_BUFSIZ 8192 //真实大小
2.对于行缓冲来说,遇到一个换行字符时,缓冲区中的内容就会被清空。因为标准I/O库每行的缓冲区长度是固定的,所以只要填满了缓冲区,即使还没有遇到换行符,也会执行I/O系统调用操作,默认行缓冲区的大小为1024
4. 缓冲区机制
对文件的访问可以分为带缓冲区的操作和非缓冲区的文件操作
- 带缓冲区文件操作:高级标准文件I/O操作,将会在用户空间中自动为正在使用的文件开辟内存缓冲区
- 非缓冲区文件操作:低级文件I/O操作,读写文件时,不会开辟对文件操作的缓冲区,直接通过系统调用对磁盘进行操作(读、写等),当然用于可以在自己的程序中为每个文件设定缓冲区
两种文件操作的解释和比较:
- ANSI标准C库函数 是建立在底层的系统调用之上,ANSI标准C库中的文件处理函数为了减少使用系统调用的次数,提高效率,采用缓冲机制,这样,可以在磁盘文件进行操作时,可以一次从文件中读出大量的数据到缓冲区中,以后对这部分的访问就不需要再使用系统调用了,即需要少量的CPU状态切换,提高了效率
- 非缓冲的文件操作访问方式,每次对文件进行一次读写操作时,都需要使用读写系统调用来处理此操作,即需要执行一次系统调用,执行一次系统调用将涉及到CPU状态的切换,即从用户空间切换到内核空间,实现进程上下文的切换,这将损耗一定的CPU时间,频繁的磁盘访问对程序的执行效率造成很大的影响
fopen打开普通文件,用open打开设备文件
5. 无缓冲区
无缓冲区是指标准I/O库不对字符进行缓存,直接调用系统调用。标准出错流stderr通常是不带缓冲区的,这使得出错信息能够尽快地显示出来。
注:①标准输入和标准输出设备:当且仅当不涉及交互作用设备时,标准输入流和标准输出流才是全缓冲的。②标准错误输出设备:标准出错绝不会是全缓冲方式的
6. 更改缓冲区类型
void setbuf(FILE *steam, char *buf);
说明:setbuf函数具有打开和关闭缓冲机制。为了带缓冲进行I/O,参数buf必须指向一个长度为BUFSIZ(定义在stdio.h头文件中)的缓冲区。通常在此之后该流就是全缓冲的,但是如果该流与一个终端设备相关,那么某些系统也可以将其设置为行缓冲。为了关闭缓冲,可以将buf参数设置为NULL
char outbuf[50];
int main(void)
{
/* 将outbuf与stdout输出流相连接 */
setbuf(stdout,outbuf);
/* 向stdout中放入一些字符串 */
puts("hello furong.");
//fflush(stdout);
/* 以下是outbuf中的内容 */
puts(outbuf);
/*刷新流*/
fflush(stdout);
return 0;
}
fflush(stdin)刷新标准输入缓冲区,把输入缓冲区里的东西丢弃[非标准]
fflush(stdout)刷新标准输出缓冲区,把输出缓冲区里的东西打印到标准输出设备上
printf(” “);后面加fflush(stdout);可提高打印效率
int setvbuf(FILE *stream, char *buf, int type, unsigned size);
type : 缓冲区的类型:
_IOFBF(满缓冲):当缓冲区为空时,从流读入数据。或者当缓冲区满时,向流写入数 据
_IOLBF(行缓冲):每次从流中读入一行数据或向流中写入一行数据
_IONBF(无缓冲):直接从流中读入数据或直接向流中写入数据,而没有缓冲区
size : 缓冲区内字节的数量
如果出现指定该流是带缓冲区的,而buf 是NULL,则标准I/O 库将自动为该流分配适当长度的缓冲,适当长度指的即是由文件属性数据结构(struct stat)的成员st_blksize 所指定的值,如果系统不能为该流决定此值(例如若此流涉及一个设备或一个管道),则分配长度BUFSIZ 的缓冲区
setvbuf(fp,NULL,_IONBF,0);
setvbuf(fp,buf,_IOLBF,sizeof(buf));
setvbuf(fp,buf,_IOFBF,sizeof(buf));
注意:This function should be called once the file associated with the stream has already been opened but before any input or output operation has taken place.
意思是这个函数应该在打开流后,立即调用,在任何对该流做输入输出前
7. 缓冲
操作系统以缓冲方式实现设备的输入和输出操作,主要是缓解处理机与设备之间速度不匹配的矛盾