标准 IO 库的缓冲区

首先需要明确一点: 标准 IO 库提供缓冲区的目的是尽可能减少系统调用 read 和 write 函数的调用次数. 之后会给出例子直观的显示缓冲区的大小对程序性能的影响.

标准 IO 提供了 3 种类型的缓冲:

  1. 全缓冲: 其特点是需要填满缓冲区后才进行实际的 IO 操作(当然, 也可以使用 flush 对缓冲区进行冲洗), 一般对于磁盘上的文件实施的是全缓冲. 默认全缓冲的大小为 4096;
  2. 行缓冲: 当输入输出遇到换行符时, 才执行 IO 操作. 当流涉及一个终端时, 通常使用行缓冲. 行缓冲的长度是固定的, 稍微小一些, 默认是 1024;
  3. 不带缓冲: 标准 IO 库不对字符进行缓冲. 比如标准错误输出 stderr 通常是不带缓冲的, 这样即使没有换行符, 出错信息也能尽快显示. 此时缓冲的大小为 1.

测试缓冲大小对程序性能的影响

下面给出一个例子展示缓冲区的大小对程序性能的影响, 该程序实现对文件的读, 然后将内容显示到屏幕上. 根据上面介绍的内容, 使用标准 IO 库对磁盘上的文件进行处理时, 实施的全缓冲. 之后, 我们将缓冲类型设置为不带缓冲, 从而比较两种类型的缓冲对程序性能的影响.

/* test_buffer.c */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>#define oops(msg) {perror(msg); exit(1);}int main() {char buf[100];FILE *fp;if ((fp = fopen("file", "r")) == NULL)oops("fopen");/*setbuf(fp, NULL);*/struct timeval t_val, t_val_end, t_result;gettimeofday(&t_val, NULL);while (fgets(buf, 100, fp) != NULL)printf("%s", buf);gettimeofday(&t_val_end, NULL);timersub(&t_val_end, &t_val, &t_result);double consume = t_result.tv_sec + (1.0 * t_result.tv_usec)/1000000;printf("end.elapsed time= %fs \n", consume);
}

其中文件 file 有 20 行, 总共 238 个字符.

  • 当执行上述代码后(注意此时 setbuf(fp, NULL); 被注释了), 结果为:
end.elapsed time= 0.000092s
  • 当将 setbuf(fp, NULL); 的注释去掉, 此时 fp 对应的流是不带缓冲的, 代码的执行结果为:
end.elapsed time= 0.000265s

结果在我们的意料之中. 此时由于关闭缓冲后, 系统调用频繁, 所消耗的时间无疑会增多.

显示缓冲的类型以及大小

下面的例子展示了各个流的缓冲类型以及相应的大小:

/* buffer_info.c */
#include <stdio.h>
#include <stdlib.h>void pr_stdio(const char*, FILE*);
int is_unbuffered(FILE*);
int is_linebuffered(FILE*);
int buffer_size(FILE*);#define oops(msg) {perror(msg); exit(1);}int main() {FILE *fp;pr_stdio("stdin", stdin);pr_stdio("stdout", stdout);pr_stdio("stderr", stderr);if ((fp = fopen("/etc/passwd", "r")) == NULL)oops("fopen");if (getc(fp) == EOF)oops("getc error");pr_stdio("/etc/passwd", fp);exit(0);
}void pr_stdio(const char *name, FILE *fp) {printf("stream = %s,  ", name);if (is_unbuffered(fp))printf("unbuffered");else if (is_linebuffered(fp))printf("line buffered");elseprintf("fully buffered");printf (", buffer size = %d\n", buffer_size(fp));
}int is_unbuffered(FILE *fp) {return(fp->_flags & _IO_UNBUFFERED);
}int is_linebuffered(FILE *fp) {return(fp->_flags & _IO_LINE_BUF);
}int buffer_size(FILE *fp) {return(fp->_IO_buf_end - fp->_IO_buf_base);
}

程序运行的结果为:

stream = stdin,  line buffered, buffer size = 1024
stream = stdout,  line buffered, buffer size = 1024
stream = stderr,  unbuffered, buffer size = 1
stream = /etc/passwd,  fully buffered, buffer size = 4096

标准 IO 库的缓冲区相关推荐

  1. C++ Primer 第八章 标准IO库

    学习本章内容之前有必要对缓冲区的概念做一个基本了解,我引用了网上一片文章<C++编程对缓冲区的理解>,内容如下: 什么是缓冲区    缓冲区又称为缓存,它是内存空间的一部分.也就是说,在内 ...

  2. 标准IO库--unix环境高级编程读书笔记

    标准IO库是C语言提供的一个库,不光存在于linux中,在windows中也是有的.标准IO库和文件IO的不同是,标准IO库是对文件IO(即系统调用)的封装,并且在用户层添加了一些缓冲区. 文件IO的 ...

  3. C++ Primer 第八章 标准IO库(转载)

    学习本章内容之前有必要对缓冲区的概念做一个基本了解,我引用了网上一片文章<C++编程对缓冲区的理解>,内容如下: 什么是缓冲区    缓冲区又称为缓存,它是内存空间的一部分.也就是说,在内 ...

  4. 《UNIX环境高级编程》笔记 第五章-标准IO库

    1. 流和FILE对象 在第三章的系统调用都是围绕文件描述符fd的.但是标准I/O库函数操作则是围绕流进行的.当使用标准I/O库打开或创建一个文件时,使用一个流与一个文件关联. 当打开一个流时,标准I ...

  5. Linux操作系统-标准IO库(2)

    Linux操作系统-标准IO库(2)(2015-8-4) 分类:Linux操作系统   打开一个流后,可采用三种不同类型的非格式化I/O对其进行读,写操作. 1. 每次读取一个字符的I/O 2. 每次 ...

  6. 【Linux】标准IO库

    Linux系统的文件IO都是针对文件描述符的,而标准IO(ISO C)的操作则是围绕流进行的,一个最明显的区别是标准IO比Linux文件IO多了缓冲机制.为了使用流,需要用到文件指针即指向FILE结构 ...

  7. 在标准IO库中,rewind函数作用?

    在标准IO库中,rewind函数作用? 将文件内部的位置指针重新指向一个流(数据流/文件)的开头 一个完整的信号生命周期包含4个重要的事件,这4个重要事件分别是? 信号诞生:信号在进程中注册完毕:信号 ...

  8. Linux操作与管理文件(多次打开同一文件,文件共享,fcntl函数,标准IO库)

    1.linux系统如何管理文件 硬盘中的静态文件和inode: (1)硬盘分为两大区域:一个是硬盘内容管理表项,另一个是真正存储内容的区域.先去读取硬盘内容管理表,找到要访问的存储内容的区域,再用得到 ...

  9. Linux后台开发系列之「13.标准 IO 库」

    StdIO.png 版权声明:本文为 cdeveloper 原创文章,可以随意转载,但必须在明确位置注明出处! 标准 IO 库 上一篇文章我们学习了 5 个底层的 IO 函数,这次我们来学习标准的 I ...

最新文章

  1. ASP.NET MVC+Bootstrap个人博客之打造清新分页Helper(三)
  2. python 3读取文件-python3的txt文件读写
  3. Codeforces Round #741 (Div. 2) D2. Two Hundred Twenty One (hard version) 前缀和 + 分段模型
  4. iOS5 UI 设计新手段 Storyboard
  5. Hbase读写数据的原理解析
  6. 深入探讨SDN拓扑发现机制:新的攻击及实践对策【SDN拓扑】(下)
  7. 关于ListView中Detail模式下的一些基本操作
  8. image.merge图像有什么变化_经常用到压缩软件的你,知道什么是无损压缩和有损压缩吗?...
  9. 类的应用python平均分_【数据科学系统学习】Python # 数据分析基本操作[四] 数据规整化和数据聚合与分组运算...
  10. 无法添加外键约束的原因(cannot add foreign key constraint)
  11. fastDFS原理及环境搭建
  12. abaqus2020安装教程
  13. [精品]CAD批量处理工具
  14. 染色基础知识(四)——怎么染?
  15. Christmas Lights Kata练习
  16. 项目中引入阿里巴巴图标——iconfont图标的使用-svg格式
  17. SSM校园外卖订餐系统
  18. 内核tcp协议栈SACK的处理
  19. ZZULIOJ:1071: 分解质因子
  20. 丰田增设电池生产线,加快丰田电动化进程

热门文章

  1. 微信开发者工具下载安装
  2. curl post 发送json
  3. 【UE4 第一人称射击游戏】11-武器跟随鼠标移动并添加开火音效
  4. ftp 链接时用户身份证验证失败
  5. 北华航天工业学院计算机科学与技术,北华航天工业学院计算机科学与工程系介绍...
  6. 三个白帽 - pwnme_k0
  7. 关于字体适配的那些事
  8. 中标麒麟mips64le架构安装minio
  9. 2019年最受欢迎的手机App
  10. 优惠券系统:用户查询并领取优惠券