一文搞懂 | Linux 内核的 4 大 IO 调度算法

点击蓝字

00033a0f9690e5fa3e40947fc468ca3a.png

关注我们

因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享

来源于网络,侵删

Linux 内核包含4个IO调度器:

  • Noop IO scheduler

  • Anticipatory IO scheduler

  • Deadline IO scheduler 

  • CFQ IO scheduler

anticipatory, 预期的;提早发生的;期待着的

通常磁盘的读写影响是由磁头到柱面移动造成了延迟,解决这种延迟内核主要采用两种策略:缓存和IO调度算法来进行弥补。

本文做一简单介绍。

调度算法概念

  1. 当向设备写入数据块或是从设备读出数据块时,请求都被安置在一个队列中等待完成。

  2. 每个块设备都有它自己的队列。

  3. I/O调度程序负责维护这些队列的顺序,以更有效地利用介质.I/O调度程序将无序的I/O操作变为有序的I/O操作。

  4. 内核必须首先确定队列中一共有多少个请求,然后才开始进行调度。

d106ee8f4762eed0bbf5a0ac79c3dbed.png

IO 调度器(IO Scheduler)

7d87a3f5925ad189829ead686de798f0.png

IO调度器(IO Scheduler)是操作系统用来决定块设备上IO操作提交顺序的方法。存在的目的有两个,一是提高IO吞吐量,二是降低IO响应时间。然而IO吞吐量和IO响应时间往往是矛盾的,为了尽量平衡这两者,IO调度器提供了多种调度算法来适应不同的IO请求场景。其中,对数据库这种随机读写的场景最有利的算法是DEANLINE。

IO调度器在内核栈中所处位置如下:

45462a338aa36cca8cc00f3b8412987d.png

849e7d06fdb81f054b0c7e24bba83a37.png

块设备最悲剧的地方就是磁盘转动,这个过程会很耗时间。

每个块设备或者块设备的分区,都对应有自身的请求队列(request_queue),而每个请求队列都可以选择一个I/O调度器来协调所递交的request。I/O调度器的基本目的是将请求按照它们对应在块设备上的扇区号进行排列,以减少磁头的移动,提高效率。每个设备的请求队列里的请求将按顺序被响应。实际上,除了这个队列,每个调度器自身都维护有不同数量的队列,用来对递交上来的request进行处理,而排在队列最前面的request将适时被移动到请求队列中等待响应。

22c00f62a435ed1387ad25c15de22577.png

IO scheduler 的作用主要是为了减少磁盘转动的需求。主要通过2种方式实现:

      1. 合并

      2. 排序

每个设备都会自己对应请求队列,所有的请求在被处理之前都会在请求队列上。在新来一个请求的时候如果发现这个请求和前面的某个请求请求的位置是相邻的,那么就可以合并为一个请求。如果不能找到合并的,就会按照磁盘的转动方向进行排序。通常IO scheduler 的作用就是为了在进行合并和排序的同时,也不会太影响单个请求的处理时间。

1、NOOP

2eb3065359a9346ef5467843564a37f6.png

FIFO

1. noop是什么? noop是一种输入输出调度算法。NOOP, No Operation. 什么都不做,请求来一个处理一个。这种方式实施起来简单,也更有效。问题就是disk seek 太多,对于传统磁盘,这是不能接受的。但对于SSD 磁盘就可以,因为SSD 磁盘不需要转动。

2. noop的别称 又称为电梯调度算法。

3. noop原理是怎样的?

将输入输出请求放到一个FIFO队列中,然后按次序执行队列中的输入输出请求:当来一个新请求时:

1. 如果能合并就合并;

2. 如果不能合并,就会尝试排序。如果队列上的请求都已经很老了,这个新的请求就不能插队,只能放到最后面。否则就插到合适的位置;

3. 如果既不能合并,又没有合适的位置插入,就放到请求队列的最后;

4. 适用场景

4.1 在不希望修改输入输出请求先后顺序的场景下;

4.2 在输入输出之下具有更加智能调度算法的设备,如NAS存储设备;

4.3 上层应用程序已经精心优化过的输入输出请求;

4.4 非旋转磁头式的磁盘设备,如SSD磁盘

2、CFQ(Completely Fair Queuing, 完全公平排队)

CFQ(Completely Fair Queuing)算法,顾名思义,绝对公平算法。它试图为竞争块设备使用权的所有进程分配一个请求队列和一个时间片,在调度器分配给进程的时间片内,进程可以将其读写请求发送给底层块设备,当进程的时间片消耗完,进程的请求队列将被挂起,等待调度。

每个进程的时间片和每个进程的队列长度取决于进程的IO优先级,每个进程都会有一个IO优先级,CFQ调度器将会将其作为考虑的因素之一,来确定该进程的请求队列何时可以获取块设备的使用权。

IO优先级从高到低可以分为三大类:

RT(real time)

BE(best try)

IDLE(idle)

其中RT和BE又可以再划分为8个子优先级。可以通过ionice 去查看和修改。优先级越高,被处理得越早,用于这个进程的时间片也越多,一次处理的请求数也会越多。

实际上,我们已经知道CFQ调度器的公平是针对于进程而言的,而只有同步请求(read或syn write)才是针对进程而存在的,他们会放入进程自身的请求队列,而所有同优先级的异步请求,无论来自于哪个进程,都会被放入公共的队列,异步请求的队列总共有8(RT)+8(BE)+1(IDLE)=17个。

从Linux 2.6.18起,CFQ作为默认的IO调度算法。对于通用的服务器来说,CFQ是较好的选择。具体使用哪种调度算法还是要根据具体的业务场景去做足benchmark来选择,不能仅靠别人的文字来决定。

3、DEADLINE

DEADLINE在CFQ的基础上,解决了IO请求饿死的极端情况。

除了CFQ本身具有的IO排序队列之外,DEADLINE额外分别为读IO和写IO提供了FIFO队列。

adf48f3d1548273ae08b7bec22459f86.png

读FIFO队列的最大等待时间为500ms,写FIFO队列的最大等待时间为5s(当然这些参数都是可以手动设置的)。

FIFO队列内的IO请求优先级要比CFQ队列中的高,而读FIFO队列的优先级又比写FIFO队列的优先级高。优先级可以表示如下:

FIFO(Read) > FIFO(Write) > CFQ

deadline 算法保证对于既定的 IO 请求以最小的延迟时间,从这一点理解,对于 DSS 应用应该会是很适合的。

deadline 实际上是对Elevator 的一种改进: 

1. 避免有些请求太长时间不能被处理。

2. 区分对待读操作和写操作。

deadline IO 维护3个队列。第一个队列和Elevator 一样, 尽量按照物理位置排序。第二个队列和第三个队列都是按照时间排序,不同的是一个是读操作一个是写操作。

deadline IO 之所以区分读和写是因为设计者认为如果应用程序发了一个读请求,一般就会阻塞到那里,一直等到的结果返回。而写请求则不是通常是应用请求写到内存即可,由后台进程再写回磁盘。应用程序一般不等写完成就继续往下走。所以读请求应该比写请求有更高的优先级。

在这种设计下,每个新增请求都会先放到第一个队列,算法和Elevator的方式一样,同时也会增加到读或者写队列的尾端。这样首先处理一些第一队列的请求,同时检测第二/三队列前几个请求是否等了太长时间,如果已经超过一个阀值,就会去处理一下。这个阀值对于读请求时 5ms, 对于写请求时5s。

个人认为对于记录数据库变更日志的分区,例如oracle 的online log, mysql 的binlog 等等,最好不要使用这种分区。因为这类写请求通常是调用fsync 的。如果写完不成,也会很影响应用性能的。

4、ANTICIPATORY

CFQ和DEADLINE考虑的焦点在于满足零散IO请求上。对于连续的IO请求,比如顺序读,并没有做优化。

为了满足随机IO和顺序IO混合的场景,Linux还支持ANTICIPATORY调度算法。ANTICIPATORY的在DEADLINE的基础上,为每个读IO都设置了6ms的等待时间窗口。如果在这6ms内OS收到了相邻位置的读IO请求,就可以立即满足。

小结

IO调度器算法的选择,既取决于硬件特征,也取决于应用场景。

在传统的SAS盘上,CFQ、DEADLINE、ANTICIPATORY都是不错的选择;对于专属的数据库服务器,DEADLINE的吞吐量和响应时间都表现良好。

然而在新兴的固态硬盘比如SSD、Fusion IO上,最简单的NOOP反而可能是最好的算法,因为其他三个算法的优化是基于缩短寻道时间的,而固态硬盘没有所谓的寻道时间且IO响应时间非常短。

3d0ab7724f1e7dd811c1adf6ad9d5300.jpeg

如果你年满18周岁以上,又觉得学【C语言】太难?想尝试其他编程语言,那么我推荐你学Python,现有价值499元Python零基础课程限时免费领取,限10个名额!
▲扫描二维码-免费领取

戳“阅读原文”我们一起进步

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/337107.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

众神进入瓦尔哈拉_一时冲动:“通往瓦尔哈拉之路的冒险”

众神进入瓦尔哈拉通过所有有关Java 9和Project Jigsaw的讨论,我们不应忽视Java的另一重大变化。 希望在第10版或第11版中, Valhalla项目能够实现并介绍价值类型和专业化。 那么,这是什么一回事,项目进展如何,面临什么…

当电子工程师十余年,感慨万千!

点击蓝字关注我们因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络,侵删当电子工程师也一些年头了,不算有出息,环顾四周,也没有看见几个有出息的。回顾工程师生涯,感慨万…

面试大全 | C语言高级部分总结,2.6万字长文

点击蓝字关注我们因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络,侵删一、内存大话题1.0、内存就是程序的立足之地,体现内存重要性。1.1、内存理解:内存物理看是有很多个 Bank(就是…

程序如何运行,编译、链接、装入?

点击蓝字关注我们因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络,侵删一、地址概念和程序如何运行在多道程序环境下,要使程序运行,必须先为之创建进程。而创建进程的第一件事,便是…

NSA:建议从 C/C++ 切换到内存安全语言

点击蓝字关注我们因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络,侵删美国国家安全局(NSA)发布了一份指南,旨在帮助软件开发商和运营商预防和缓解软件内存安全问题。其鼓励组织将编…

探索cqrs和事件源_编写基于事件的CQRS读取模型

探索cqrs和事件源关于事件源和CQRS的讨论似乎通常集中在CQRS上下文中的整体系统架构或领域驱动设计的各种形式。 但是,尽管也有一些有趣的考虑,但读取模型经常被忽略。 在本文中,我们将介绍通过使用事件流来填充视图模型的示例实现。 总览 …

C# 11正式发布

点击蓝字关注我们因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络,侵删C# 11 现已发布。公告称,“随着每个版本的发布,社区的参与度越来越高,贡献了从建议、见解和错误报告到整个功…

分享一个通用的嵌入式驱动层

点击蓝字关注我们因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络,侵删C 语言面向对象编程的最佳实践一、前言以STM32为例,打开网络上下载的例程或者是购买开发板自带的例程,都会发现应用层中会…

cks32和stm32_cks子,间谍,局部Mo子和短管

cks32和stm32本文是我们名为“ 用Mockito测试 ”的学院课程的一部分。 在本课程中,您将深入了解Mockito的魔力。 您将了解有关“模拟”,“间谍”和“部分模拟”的信息,以及它们相应的存根行为。 您还将看到使用测试双打和对象匹配器进行验证…

CSON+CJSON,解析json数据更优雅?

点击蓝字关注我们因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络,侵删前言json是目前最为流行的文本数据传输格式,特别是在网络通信上广泛应用,随着物联网的兴起,在嵌入式设备上&a…

让C语言源码可知自身函数的实际地址与大小

点击蓝字关注我们因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络,侵删事情的起因大概是这样……在很久很久以前,我最早用的是MASM(Win32ASM)写程序,从平台兼容性、开发…

java设计模式迭代器模式_迭代器设计模式示例

java设计模式迭代器模式本文是我们名为“ Java设计模式 ”的学院课程的一部分。 在本课程中,您将深入研究大量的设计模式,并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因,并了解何时以及如何应用模式中的每一个。 在这里查…

平衡二叉树 C语言代码实现

点击蓝字关注我们因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络,侵删1.什么是平衡二叉树平衡二叉树,我们也称【二叉平衡搜索树/AVL】,树中任何节点的两个子树的高度最大差别为1,巴拉巴拉。。…

UDP/TCP 包的大小限制知多少

点击蓝字关注我们因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络,侵删一、MTU 简述 - 分包后数据包最大长度1、定义Maximum Transmission Unit(最大可传输单元) 的缩写,它的单位是…

java ee的小程序_扩展Java EE应用程序的基础

java ee的小程序老实说,“可扩展性”是一个详尽的主题,并且通常没有被很好地理解。 通常,它被认为与高可用性相同。 我已经看到新手程序员和“经验丰富”的建筑师都建议将“ 群集 ”作为可伸缩性和HA的解决方案。 它实际上没有任何问题&#…

28 张图,一次性说清楚 TCP,速度

点击蓝字关注我们因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络,侵删做IT相关的工作,肯定都离不开网络,网络中最重要的协议是TCP。无论是实际工作还是笔试面试,你看哪里能少得了T…

晨风机器人怎么买奴隶_潮牌复刻和正品该怎么抉择???带你了解了解

今天带你们聊一聊潮牌复刻和正品,简单介绍一下我自己,在复刻圈子五年,我的原则从始至终就是质量放在第一位,之所以能走这么久也是这个原因。回归正题,接着往下看。无论是正品还是复刻,其实还要根据自己的能…

C语言字符串函数strcat | strcpy | strlen | strcmp的用法及原型

点击蓝字关注我们因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络&#xff0c;侵删strcat(str1,str2) 意为将字符串str2连接到字符串str1之后strcat用法如下#include <stdio.h> #include <string.h>int main () {cha…

C语言字符数组与字符串的使用详解

点击蓝字关注我们因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络&#xff0c;侵删正文1、字符数组的定义与初始化字符数组的初始化&#xff0c;最容易理解的方式就是逐个字符赋给数组中各元素。char str[10]{ I, ,a,m, ,‘h,a,p…

5 个牛逼的算法设计,你知道几个?

点击蓝字关注我们因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络&#xff0c;侵删1、分治法概念&#xff1a;将一个难以直接解决的大问题&#xff0c;分割成一些规模较小的相同问题&#xff0c;以便各个击破&#xff0c;分而治之…