Linux系统IO中write原型为  ssize_t write(int  filedes, const void * buff, size_t nbytes) ;

当调用write写数据的时候,调用完成后write直接返回,但是磁盘是个慢速设备,操作系统会将数据保存在内核中的缓冲区中,并负责异步地将数据写至磁盘。当然如果此时系统宕机了则会丢失数据。write是系统调用,每次调用都会陷入内核,所以选取一个合适的块长度buffsize,并尽量减少它的调用可以优化效率。在ANSI C的标准IO中我们调用printf/fprintf/fputs等会以流的方式进行处理,我们只需要写入流中,而不用像write一样选择一个buffsize,因为标准IO库帮我们处理了很多细节,例如缓冲区分配,以优化长度执行IO等。这样的话就会减少wirte/read系统调用的数量,提高效率。但是与此同时会引入另外一个问题:数据拷贝,例如当使用函数fgets和fputs时,通常需要经过两次缓冲区:一次是标准IO缓冲区,还有一次是调用read和write的内核缓冲区。但是总的来说使用标准IO相对于系统IO来说接口简单,且效率相当。

标准IO提供了三种类型的缓冲区:全缓存,行缓存和不带缓存,全缓存只有在缓冲区满时才会主动flush,通常用在对一个磁盘文件IO。行缓存在缓冲区中遇到换行符就会flush,还有一种情况是需要从标准输入输出得到输入数据时也会flush缓冲区,行缓存一般用在交互的终端中。不带缓存则相当于直接 write系统调用输出,标准出错流stderr通常是不带缓存的,这就使得出错信息可以尽快显示出来。除了默认的flush条件外,显式调用fflush函数和程序正常终止时也会flush缓冲区。我们可以使用setbuf/setvbuf来更改默认的缓冲区长度,参见APUE 5.4节。

在使用标准IO的程序中,当我们将一个标准输出重新定向到一个文件时,会将行缓存变为全缓存,在某些情况下可能会导致一些非预期错误,比如调用printf(“*****\n”)时,当以交互方式运行该程序时,会正常输出。但是当将标准输出重新定向到一个文件时,缓冲区区变为全缓存,printf就不会正常输出,该行数据仍在缓冲区中。如果此时再fork一个子进程,数据空间被复制到子进程中时,该缓冲区数据也被复制到子进程中。接着在子进程中如果输出则会刷新之前在缓冲区的内容,产生一些非预期的输出。

在网络编程中,应该直接使用系统IO,标准IO为提升性能而引入缓冲机制增加了网络应用程序的复杂性。并且,某种意义上说标准IO流是全双工的,能同时执行输入和输出,然而对流的限制和对套接字的限制,有时候会互相冲突。(参见CSAPP P611)

某些高级的网络库中(比如说muduo库)在使用系统IO的基础上会创建自己的缓冲区,帮助用户屏蔽系统IO的某些不便,例如调用write发送大量数据的时候,发送缓冲区满时需要应用层等待,read接收数据的时候粘包和数据接受的缓慢。当增加应用层缓冲区后,由网络库处理这些实现细节,简化用户操作。

Linux还提供了零拷贝技术来减少内存拷贝,进而提升效率,我们知道利用read/write从磁盘发送数据到网卡会经过四次拷贝操作:当应用程序需要访问某块数据的时候,操作系统内核会先检查这块数据是不是因为前一次对相同文件的访问而已经被存放在操作系统内核地址空间的缓冲区内,如果在内核缓冲区中找不到这块数据,Linux 操作系统内核会先将这块数据从磁盘读出来放到操作系统内核的缓冲区里。如果这个数据读取操作是由 DMA 完成的,那么在 DMA 进行数据读取的这一过程中,CPU 只需要进行缓冲区管理,以及创建和处理 DMA ,除此之外,CPU 不需要再做更多的事情,DMA 执行完数据读取操作之后,会通知操作系统做进一步的处理。Linux 操作系统会根据 read系统调用指定的应用程序地址空间的地址,把这块数据存放到请求这块数据的应用程序的地址空间中去,待用户对数据完成操作后,操作系统需要将数据再一次从用户应用程序地址空间的缓冲区拷贝到与网络堆栈相关的内核缓冲区中去,这个过程也是需要占用 CPU 的。数据拷贝操作结束以后,数据会被打包,然后发送到网络接口卡上去。从上面的描述可以看出,在这种传统的数据传输过程中,数据至少发生了四次拷贝操作,即便是使用了 DMA 来进行与硬件的通讯,CPU 仍然需要访问数据两次。

(ps:记得之前看过一个面试题说是printf输出过程经过几次缓冲区,现在大家明白了吧!)

使用零拷贝技术可以避免数据在系统内核地址空间的缓冲区和用户应用程序地址空间的缓冲区进行拷贝。有时候,应用程序在数据传输的过程中不需要对数据进行访问,传输的数据可以不用复制到用户应用区,直接通过内核发送到网卡就可以,这样可以提高性能,而此时就需要零拷贝技术。linux下可以用mmap,sendfile,splice实现零拷贝。

转载于:https://blog.51cto.com/12953214/1940500

后台开发之IO缓冲区管理相关推荐

  1. 文件异步io java,漫画图解java开发之IO阻塞、非阻塞、同步、异步

    周末在家加班,正在疯狂的撸代码,女朋友很开心的跑过来,手里拿着他刚刚画好的一副漫画. 同步.异步.阻塞.非阻塞都是和IO(输入输出)有关的概念.最简单的文件读取就是IO操作.而在文件读取这件事儿上,可 ...

  2. (015)java后台开发之web项目中如何添加jar包和删除jar包

    创建一个java web项目后,创建一个index.jsp运行起来后,就发布到服务器上!最简单的java web工程就算完成了!但是往往我们的工程比较复杂,经常会用一些第三方的库(jar)来帮助我们方 ...

  3. (012) java后台开发之Apache与Tomcat有什么关系和区别

    转载:http://blog.csdn.net/longzs/article/details/10959945 经常在用apache和tomcat等这些服务器,可是总感觉还是不清楚他们之间有什么关系, ...

  4. (022)java后台开发之HttpServletRequest

    本文转载自:Servlet运行原理及404.500.405异常原因和解决方法总结 一.Servlet运行原理 比如,在浏览器地址栏输入http://ip:port/web01/hello,整个通信流程 ...

  5. (021)java后台开发之HttpServletRequest

    文章转自:https://www.cnblogs.com/xdp-gacl/p/3798347.html servlet-api 的servlet.http.HttpServlet 的学习.大神的文章 ...

  6. (020)java后台开发之JAVA集合中的List接口

    转载:http://blog.csdn.net/self_realian/article/details/51881977 原文写的很好.请看原文. JAVA中的集合类: JAVA中的集合类,是一种工 ...

  7. (016)java后台开发之Eclipse安装反编译插件

    在java(015)中gson-2.2.4.jar 源码的查看基于Attach Source code 链接到源码库gson-2.2.4-source.jar 实现的.而我导入的servlet-api ...

  8. (014)java后台开发之用tomcat发布自己的javaWeb项目

    本地模拟tomcat发布javaWeb项目需要: 1.Mac本地安装tomcat. 2.Mac安装Eclipse-JavaEE. 3.tomcat 在Mac的安装. (http://blog.csdn ...

  9. (013)java后台开发之Mac系统安装和配置tomcat步骤详解

    一:下载 打开Apache Tomcat官网,选择需要的版本下载: 二:存放到本地 文件夹重名民为ApacheTomcat,放到/Users/计算机名/Library/目录下 三:启动Tomcat 打 ...

最新文章

  1. Tomcat 6.0.32 +Spring dbcp datasource关闭Tomcat出现严重异常
  2. Server-U的批量用户创建
  3. How to POST JSON data with Curl from Terminal/Commandline to Test Spring REST?
  4. 【Windows 10 应用开发】使用快捷访问键
  5. pyQt4 for mac OS 10.8
  6. [vue] prop验证的type类型有哪几种?
  7. 【转】WPF调用图片路径,或资源图片
  8. 使用jRebel在IntelliJ IDEA 中进行 Java 热部署
  9. Java执行系统命令策略
  10. 为什么微信推荐这么快?SimSvr在微信推荐系统中的应用实践
  11. win7在计算机中虚拟光驱怎么删除,win7系统删除虚拟光驱的操作方法
  12. hdu 1261 字串数
  13. 服务器指定网卡进行备份数据避免影响业务口
  14. 如何修改PDF文档,怎么编辑PDF背景
  15. 全网最全360无死角编写软件测试用例模板【建议收藏】
  16. 基于企业微信和钉钉的工资条发送工具 - 工资条帮
  17. 麦吉尔大学统计与计算机科学,麦吉尔大学统计学和计算机科学本科.pdf
  18. 固态硬盘是什么接口_固态硬盘接口有哪些,他们之间都有什么区别,该如何选择...
  19. 完善保密加密机制(Perfectly-secret Encryption)——无条件安全加密算法
  20. Zabbix - 微信报警

热门文章

  1. 3D人体姿态估计--Coarse-to-Fine Volumetric Prediction for Single-Image 3D Human Pose
  2. 使用overlap-add方法计算两个信号的卷积示例(在频域计算卷积)
  3. 【Harvest源码分析】GetF0CandidateContour函数
  4. 【Harvest源码分析】GetFourZeroCrossingIntervals函数
  5. Debian/Ubuntu/Raspbian 时间同步
  6. Ansible的安装及部署
  7. java面试题2016_2016最新java面试题 详细版
  8. mfc 访问局域网mysql_数据库操作:MFC连接与MYSQL
  9. Nginx 真实的 IP
  10. java 商城 jfinal,Jfinal开发农副产品电子商城系统,完整前后台系统