缓冲I/O和非缓冲I/O

文件读写主要牵涉到了如下五个操作:打开、关闭、读、写、定位。在Linux系统中,提供了两套API,

  • 一套是C标准API:fopen、fclose、fread、fwrite、fseek,
  • 另一套则是POSIX定义的系统API:open、close、read、write、seek。

其中POSIX定义的API是系统API,而C标准API是基于系统API的封装,并且提供了额外的缓冲的功能。因此也可以把它们叫做缓冲I/O函数和非缓冲I/O函数。

除了前面介绍的这几个缓冲IO函数外,C标准库里面还提供了一系列封装的IO函数:如puts、putchar、printf等。

为什么要有增加缓冲区这个功能呢?主要是因为IO操作时,操作系统要从用户态转换为内核态的,而这个转换过程相对来说比较慢,因此可以通过缓冲的形式减少转换到内核态的次数。

那么,缓冲IO函数又是如何工作的呢?

  • 当用fopen打开文件时,除了分配文件句柄外,还额外申请了一个缓冲区。
  • 读文件时,会首先读到缓冲区中,然后返回用户需要的部分,多余的部分仍然放在缓冲区,下次再读的时候可以直接从缓冲区中返回。
  • 写文件时,会先写到缓冲区中,等缓冲区满后再统一写到文件中。

那么,我们该如何选择哪一组I/O函数呢?

  • 非缓冲I/O函数每次读写都要进内核,调一个系统调用比调一个用户空间的函数要慢很多,所以在用户空间开辟I/O缓冲区还是必要的。
  • 用缓冲I/O库函数要时刻注意I/O缓冲区和实际文件有可能不一致,在必要时需调用fflush()。

I/O函数也用于读写设备,比如终端或网络设备。此时通常需要更快的响应,一般不使用缓冲I/O函数。

PS:严格来讲,就算是POSIX的I/O函数,仍然是有内核I/O缓冲的,所以write也不一定是直接写到文件的,也可能写到内核I/O缓冲区中,至于究竟写到了文件中还是内核缓冲区中对于进程来说是没有太大差别的,我们不用太关注这一点。

阻塞I/O和非阻塞I/O

文件读写通常有阻塞和非阻塞两种方式,其中阻塞方式是我们比较常见的一种方式,此时函数会阻塞至操作完成。例如,对于如下一个等待用户输入字符串,并在屏幕上输出的例子:

#include <unistd.h>
#include <stdlib.h>int main(void)
{char buf[10];int n = read(STDIN_FILENO, buf, 10);write(STDOUT_FILENO, buf, n);return 0;
}

执行该函数时,read函数会一直阻塞到在屏幕上输入数据并回车(此时STDIN有数据可用)为止。
阻塞IO有一个很大的问题是:无法实现并发。当同时进行多个IO操作的时候,前面的文件数据不可用的时候(往往是Socket之类的IPC操作),后面的IO操作无法执行。
非阻塞IO则可以很好的解决这个问题,要使用非阻塞IO操作,需要在open的时候制定O_NONBLOCK标志。这样,如果设备暂时没有数据可读就返回-1,调用者应该试着再读一次(again)。这种行为方式称为轮询(Poll),调用者只是查询一下,而不是阻塞在这里死等,这样可以同时监视多个设备:

#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>int main(void)
{char buf[10];int fd, n;fd = open("/dev/tty", O_RDONLY|O_NONBLOCK);while (1){n = read(fd, buf, 10);if (n >= 0)break;sleep(1);}write(STDOUT_FILENO, buf, n);close(fd);return 0;
}

PS:为了示例函数简单,我这里没有考虑异常情况(如open失败)的处理,而这些是在实际项目中是必不可少的。

非阻塞I/O有一个缺点,如果所有设备都一直没有数据到达,调用者则需要反复查询,这样会一直占着cpu不放。因此,在使用非阻塞I/O时,通常不会在一个while循环中一直不停地查询(这称为Tight Loop),而是每延迟等待一会儿来查询一下,以免做太多无用功,在延迟等待的时候可以调度其它进程执行。

但是,这样又引入了一个新的问题,可能导致数据读取的不够及时,就拿我前面的例子来说,我在每次循环的时候Sleep了一秒。如果刚开始Sleep的时候数据可用,但此时却无法立即响应,需要到Sleep结束后钟才能输出结果。

要解圆满解决这个问题,则需要用到select函数,它可以阻塞地同时监视多个设备,还可以设定阻塞等待的超时时间,由于select多见于socket编程场景,这里不大好举例,后续如果会介绍socket编程的时候再详细介绍它,要了解它的工作原理可以看一下这篇文章select,多路同步I/O模型。

来自为知笔记(Wiz)

转载于:https://www.cnblogs.com/linzhenjie/p/5485628.html

Linux高级编程--05.文件读写相关推荐

  1. linux web高级编程,寒假学习 第16.17天 (linux 高级编程)

    寒假学习 第16.17天 (linux 高级编程) 笔记 总结 一.进程的基本控制(进程的同步) 1.进程的常见控制函数 pause   sleep/usleep atexit   on_exit i ...

  2. 嵌入式系统开发学习步骤(Linux高级编程学习顺序)

    2019独角兽企业重金招聘Python工程师标准>>> 嵌入式系统开发学习步骤(Linux高级编程学习顺序) 1.Linux 基础 安装Linux操作系统 Linux文件系统 Lin ...

  3. linux系统编程之文件与I/O(六):fcntl 函数与文件锁

    2013-05-14 11:26 8290人阅读 评论(2) 收藏 举报  分类: linux系统编程(19)  版权声明:本文为博主原创文章,未经博主允许不得转载. 一.fcntl函数 功能:操纵文 ...

  4. Linux环境编程05

    目录 Linux环境编程05 一.信号相关基本概念 二.信号捕获 三.进程休眠信号 四.信号集和信号阻塞 五.附带数据信息的信号处理(较难) 六.定时器 Linux环境编程05 声明:本学习笔记为个人 ...

  5. Linux系统编程之文件IO

    Linux系统编程之文件IO 文件IO第一天 一.标准IO基本概念 1.1c语言函数 (c库函数) 调用实现某一个功能,(API) 1.2系统调用:内核中的程序接口,应用程序和硬件设备之间的中间层 1 ...

  6. 【Linux系统编程】文件描述符的复制dup()和dup2()

    00. 目录 文章目录 00. 目录 01. 文件描述符复制概述 02. 常用函数 2.1 dup函数 2.2 dup2函数 03. 案例实战 3.1 dup示例 3.2 dup2示例 04. 附录 ...

  7. Linux Linux开发 Linux高级编程 Linux文档

    今天上传了一本课本.是我们班的同学共同书写完成.还是很不错的.希望大家多多支持啊. 下载地址:http://download.csdn.net/detail/ta893115871/4368933 1 ...

  8. linux原子过程,linux系统编程:IO读写过程的原子性操作实验

    所谓原子性操作指的是:内核保证某系统调用中的所有步骤(操作)作为独立操作而一次性加以执行,其间不会被其他进程或线程所中断. 举个通俗点的例子:你和女朋友OOXX的时候,突然来了个电话,势必会打断你们高 ...

  9. C语言嵌入式Linux高级编程

    C语言本质上是编程语言的"通用语言",在今天仍具有极大的影响力.那么,C语言到底学到什么程度,才能够进行嵌入式内核.驱动的开发? 本课程为系列课程中的一个小节,入门介绍篇,介绍嵌入 ...

最新文章

  1. 使用Nmap获取目标服务器开放的服务以及操作系统信息
  2. 360浏览器极速模式_【小技巧】解除浏览器主页以及,锁定主页~
  3. UA MATH563 概率论的数学基础 中心极限定理14 Kolmogorov maximal inequality
  4. 开源 python_8款Python GUI开源框架,谁才是你的最爱?
  5. SQL:如何用一个sql统计出全校男生个数、女生个数以及总人数
  6. php session有什么用,session有什么作用?
  7. OCR——PaddleOCR之文字识别的学习笔记
  8. 框架-vue-cli
  9. (转)2017中国互联网证券年度报告
  10. 计算机VB圆的面积周长,使用VB设计一个简单的小程序计算圆的面积
  11. MySQL 管理表记录
  12. Docker入门学习
  13. 如何将计算机c盘分区,无损调节电脑C盘分区,让C盘空间不再尴尬(超实用)
  14. 世界精神卫生日:不断变化的世界的应用程序
  15. SharpDevelop源码分析之插件
  16. CSS的class常用命名规则
  17. python入门指南
  18. 【ChatGPT】ChatGPT使用指南——句词分类
  19. 用JAVA编写MD5大写32位加密
  20. 第三方软件测试z5x电池,5000mAh的vivo Z5x能用多久?三大续航测试摧残,表现出乎意料...

热门文章

  1. [文摘20080919]小软件将网页变为3D世界
  2. 擴展PictureBox的一個組件
  3. 患者是否应该主动关注医疗知识
  4. 医生为什么总是说生理性玻璃体混浊不用治
  5. GenericUDTF使用流程记载(转载+自己整理)
  6. spark集群启动正常,但是提交任务后只有一个节点(slave/worker)参与集群计算
  7. django的admin管理后台到底是否靠谱呢
  8. best single model of RSNA
  9. 西京学院计算机科学与技术专业怎么样,西京学院有哪些专业及什么专业好
  10. ASP.NET 之 MVC框架及搭建