Linux内核块设备I/O子系统

Linux IO调度程序是块设备I/O子系统的主要组件,它介于通用块层和块设备驱动程序之间,如下图所示。当Linux内核组件要读写数据时,并非一有请求便立即执行,而是将请求放入请求(输入)队列,并推迟执行。为什么如此设计?原因在于Linux需要应对的最核心的块设备是磁盘。磁盘的寻道时间严重制约磁盘性能,若想提高磁盘IO性能必须想尽办法减少磁盘寻道次数。

块设备I/O子系统最核心的任务也就是提高块设备的整体性能,为此Linux实现了四种IO调度算法,算法基本思想就是通过合并和排序IO请求队列中的请求大大降低所需的磁盘寻道时间,从而提供整体IO性能。

2.6内核实现了四种IO调度算法,分别为预期(Anticipatory)算法、最后期限(Deadline)算法、完全公平对列(CFQ)算法以及NOOP算法(No Operation)。用户可在内核引导时指定一种I/O调度算法,也可在运行时通过 sysfs 文件系统/sys/block/sda/queue/scheduler改变块设备的I/O调度算法(cat可查看当前使用IO调度算法)。默认的IO调度程序是"预测"IO调度程序。

“Noop”算法

最简单的 I/O调度算法。该算法仅适当合并用户请求,并不排序请求:新的请求通常被插在调度队列的开头或末尾,下一个要处理的请求总是队列中的第一个请求。这种算法是为不需要寻道的块设备设计的,如SSD。

“CFQ”算法

"CFQ(完全公平队列)”算法的主要目标是在触发I/O请求的所有进程中确保磁盘I/O带宽的公平分配。为了达到这个目标,算法使用许多个排序队列——缺省为64——它们存放了不同进程发出的请求。当算法处理一个请求时,内核调用一个散列函数将当前进程的线程组标识符(PID);然后,算法将一个新的请求插人该队列的末尾。因此,同一个进程发出的请求通常被插入相同的队列中。

算法本质上采用轮询方式扫描I/O输入队列,选择第一个非空队列,依次调度不同队列中特定个数(公平)的请求,然后将这些请求移动到调度队列的末尾。

“最后期限”算法

除了调度队列外,“最后期限”算法还使用了四个队列。其中的两个排序队列分别包含读请求和写请求,其中的请求是根据起始扇区号排序的。另外两个最后期限队列包含相同的读和写请求,但这是根据它们的“最后期限”排序的。引人这些队列是为了避免请求饿死,由于电梯策略(曾经的调度算法)优先处理与上一个所处理的请求最近的请求,因而就会对某个请求忽略很长一段时间,这时就会发生这种情况。请求的最后期限本质上就是一个超时定时器,当请求被传给电梯算法时开始计时。缺省情况下,读请求的超时时间是500ms,写请求的超时时间是5s——读请求优先于写请求,因为读请求通常阻塞发出请求的进程。最后期限保证了调度程序照顾等待很长一段时间的那个请求,即使它位于排序队列的末尾。

当算法要补充调度队列时,首先确定下一个请求的数据方向。如果同时要调度读和写两个请求,算法会选择“读”方向,除非该“写”方向已经被放弃很多次了(为了避免写请求饿死)。

接下来,算法检查与被选择方向相关的最后期限队列:如果队列中的第一个请求的最后期限已用完,那么算法将该请求移到调度队列的末尾。同时,它也会移动该过期的请求后面的一组来自排序队列的相同扇区号的请求。如果将要移动的请求在磁盘上物理相邻,那么这一批队列的长度会很长,否则就很短。

最后,如果没有请求超时,算法对来自于排序队列的最后一个请求连带之后的一组相同扇区的请求进行调度。当指针到达排序队列的末尾时,搜索又从头开始(“单方向算法”)。

“预期”算法

“预期”算法是Linux提供的最复杂的一种1/O调度算法。基本上,它是“最后期限”算法的一个演变,借用了“最后期限”算法的基本机制:两个最后期限队列和两个排序队列;I/O调度程序在读和写请求之间交互扫描排序队列,不过更倾向于读请求。扫描基本上是连续的,除非有某个请求超时。读请求的缺省超时时间是125ms,写请求的缺省超时时间是250ms。但是,该算法还遵循一些附加的启发式准则:

有些情况下,算法可能在排序队列当前位置之后选择一个请求,从而强制磁头从后搜索。这种情况通常发生在这个请求之后的搜索距离小于在排序队列当前位置之后对该请求搜索距离的一半时。

算法统计系统中每个进程触发的I/O操作的种类。当刚刚调度了由某个进程p发出的一个读请求之后,算法马上检查排序队列中的下一个请求是否来自同一个进程p。如果是,立即调度下一个请求。否则,查看关于该进程p的统计信息:如果确定进程p可能很快发出另一个读请求,那么就延迟一小段时间(缺省大约为7ms)。因此,算法预测进程p发出的读请求与刚被调度的请求在磁盘上可能是“近邻”。

linux的回写机制

不管如何优化块设备调度算法,也不可能解决磁盘IO和CPU速度严重不匹配的问题,为此Linux引入了页高速缓存。页高速缓存最开始是为内存管理而设计的,在2.6内核中,各种基于页的数据管理都纳入页高速缓存。因此块设备的IO缓冲区也属于页高速缓存。这些和使用者无关,是内核开发者需要关心的。对于开发者,需要知道的是:所有文件的IO操作都是“读写缓存”。对于读操作,只有当数据不在缓存时才需要IO操作。对于写操作,一定需要IO操作,但内核把数据写到高速缓存后write系统调用立马返回,内核采用特定的写进程统一回写dirty的缓存页。即内核对读写是分别对待的:“同步读,异步写”!

Linux的写回由特定进程按照特定算法来进行回写。在2.6.32之前的内核,pdflush后台回写例程负责完成这个工作。啥时回写呢? 下面两种情况下,脏页会被写会到磁盘:

1.在空闲内存低于一个特定的阈值时,内核必须将脏页写回磁盘,以便释放内存。
2.当脏页在内存中驻留超过一定的阈值时,内核必须将超时的脏页写会磁盘,以确保脏页不会无限期地驻留在内存中。

回写开始后,pdflush会持续写数据,直到满足以下两个条件:

1.已经有指定的最小数目的页被写回到磁盘。
2.空闲内存页已经回升,超过了阈值dirty_background_ration。

系统管理员可以在/proc/sys/vm中设置回写相关的参数,也可以通过sysctl系统调用来设置它们。下表给出了可以设置的量:

回写机制看上去很完美,在实际工作中却未必。一个问题是:pdflush线程数据是可变的(2-8),但面对的是所有块设备的数据,当某个块设备很慢,必然阻塞其他块设备的回写。为此2.6.32引入新的pdflush线程模型,每个块设备拥有独立的pdflush线程,设备之间的回写不再互相干扰。

回写缺陷

看上去如此完美的回写机制,实际中有2个缺陷:1) 回写不及时引发丢数据(sync|fsync);2) 回写期间读IO性能极差,尤其是大数据量时。

Linux:2.6.16 
内存:32G
测试过程:限速情况下持续追加写入磁盘,速度20-10MB/s, 
实测曲线:

结论:pdflush回写期间极其消耗磁盘IO,严重影响读性能。

相关文章

linux kernel development 3rd(Linux内核设计与实现)

块设备I/O调度程序

linux内核分析笔记----页高速缓存和页回写

linux的IO调度算法和回写机制相关推荐

  1. linux块设备的IO调度算法和回写机制

    ************************************************************************************** 參考: <Linux ...

  2. Linux页高速缓存缓存回写机制,基于2.6版本内核

    注:2.6内核版本使用下列方式,旧版本内核可以参考 内核版本3.2页回写机制可参考: https://blog.csdn.net/SweeNeil/article/details/84993387 之 ...

  3. linux内核页高速缓存,《Linux内核设计与实现》读书笔记(十六)- 页高速缓存和页回写(示例代码)...

    主要内容: 缓存简介 页高速缓存 页回写 1. 缓存简介 在编程中,缓存是很常见也很有效的一种提高程序性能的机制. linux内核也不例外,为了提高I/O性能,也引入了缓存机制,即将一部分磁盘上的数据 ...

  4. 《Linux内核设计与实现》读书笔记(十六)- 页高速缓存和页回写

    主要内容: 缓存简介 页高速缓存 页回写 1. 缓存简介 在编程中,缓存是很常见也很有效的一种提高程序性能的机制. linux内核也不例外,为了提高I/O性能,也引入了缓存机制,即将一部分磁盘上的数据 ...

  5. Linux内核设计与实现---页高速缓存和页回写

    页高速缓存和页回写 1 页高速缓存 2 基树 3 缓冲区高速缓存 4 pdflush后台例程 膝上型电脑模式 bdflush和kupdated 避免拥塞的方法:使用多线程 页高速缓存(cache)是L ...

  6. 漫谈linux文件io,Linux文件IO与通用块层的请求合并

    本文参考https://mp.weixin.qq.com/s/Imt4BW-zoHPpcOpcKZs_AQ, 公众号"Linux阅码场" 请求合并就是将进程内或者进程间产生的在物理 ...

  7. 页高速缓存和页回写(一)

    一.缓存写入 进程写磁盘时,缓存有三种策略 不缓存:高速缓存不去缓存任何写操作,当写入时直接跳过缓存,写到磁盘,同时使缓存中数据失效. 写透:自动更新内存缓存,同时更新磁盘文件,有利于保持缓存一致性. ...

  8. Linux内核延迟写机制学习

    Linux内核延迟写机制 Linux内核延迟写的特点,是指在Linux通过write的场景下写入数据之后,会将数据直接标记为dirty,然后通过延迟读写的方式最后将数据回写到磁盘上.在本文的Linux ...

  9. linux 标准IO缓冲机制探究

    一.什么是缓存I/O(Buffered I/O) 缓存I/O又被称作标准I/O,大多数文件系统默认I/O操作都是缓存I/O.在Linux的缓存I/O机制中,操作系统会将I/O的数据缓存在文件系统的页缓 ...

  10. Linux内核设计与实现(十)| 页高速缓存和页回写

    文章目录 页高速缓存和页回写 1.缓存手段 1.1 写缓存 1.2 缓存回收 2.Linux页高速缓存 2.1 address_space对象 2.2 address_space操作 2.3 基树 2 ...

最新文章

  1. Tomcat在Linux上的安装与配置
  2. BZOJ 1087: [SCOI2005]互不侵犯King
  3. 【CyberSecurityLearning 76】DC系列之DC-7渗透测试(Drupal)
  4. SpringMVC学习--springmvc原理
  5. 11-提升R语言程序性能gc()
  6. Node.js和io.js将合并到Node基金会下
  7. ssm-学子商城-项目第十三天最后一天完成项目
  8. Shell脚本学习指南读书笔记(一)
  9. 关于无盘工作站的初步了解(RPL/PXE)
  10. 测试质量保障体系的建立
  11. doris的tablet副本修复相关情况总结
  12. 智慧城市建设方案建议书——如何打造智慧城市
  13. 剖析top命令显示的VIRT RES SHR值
  14. PB函数大全【转自 http://blog.csdn.net/xiaoxian8023 】
  15. spring boot中小学餐饮配送系统 毕业设计源码645661
  16. 让我在这枯燥的实验室机房里,告诉你们什么是嵌入式软件开发
  17. 【matlab】 动态绘制三维心形图
  18. FPGA入门经历的阶段
  19. macOS根目录上无法写入文件和创建目录的问题
  20. 阿里云小蜜优势与应用场景

热门文章

  1. MySQL查询时当offset较大时查询效率低
  2. 一天没出个版本,让别人试试哪里有问题
  3. WIN10电脑如何显示控制面板
  4. WIN10右键菜单没有新建项了,怎么办?
  5. Function语意学之Member的各种调用方式
  6. 服务器磁盘会影响应用么,想了解服务器磁盘的IO吞吐量,用sqlio 工具会不会对当前服务器有影响...
  7. django.forms生成HTML,python – 在django中为表单自动生成表单字段
  8. linux命令行关机 密码,[ Linux 基本命令 001 ] 登陆,登出,重启,关机
  9. 说话人识别python_基于各种分类算法的说话人识别(年龄段识别)
  10. windows下mongodb安装与使用