一文图解|I/O 调度层

news2025/1/4 18:49:15

当我们使用 read() 和 write() 系统调用向内核提交读写文件操作时,内核并不会立刻向硬盘发送 I/O 请求,而是先将 I/O 请求交给 I/O 调度层进行排序和合并处理。经过 I/O 调度层加工处理后,才会将 I/O 请求发送给块设备驱动进行最终的 I/O 操作。

下图是块设备 I/O 栈的架构图:

在上图中,红色那一层便是 I/O 调度层。

I/O 调度层主要完成的工作如下:

  • 对新提交的 I/O 请求进行排序。
  • 如果新的 I/O 请求能与旧的 I/O 请求进行合并,那么将会把两个 I/O 请求合并成一个 I/O 请求。
  • 向块设备驱动层发送 I/O 请求。

 

什么是 I/O 调度层

现实中块设备的种类非常多,如磁盘、SSD(固态硬盘) 和 CD-ROM 等。由于不同种类的块设备其物理结构不同,所以优化 I/O 效率的算法也不一样。如:SSD 读写任意地址中的数据速度都一样,所以就没必要进行额外的优化,只需要将用户提交 I/O 操作直接发送给块设备驱动即可。

但有些块设备的物理结构比较特殊,如磁盘,其读写速度与磁头移动的距离(寻道)有关,所以磁头移动的距离越远,读写速度就越慢。

磁盘的物理结构如下图所示:

对于磁盘来说,顺序读写的速度是最快的。这是由于顺序读写时,磁头移动的距离最小。所以,避免随机读写是加速磁盘 I/O 效率最有效的办法。

假如有3个进程先后向磁盘写入数据,如下图所示:

如上图序号的顺序所示:首先进程 A 向扇区 A 写入数据,然后进程 B 向扇区 B 写入数据,最后进程 C 向扇区 C 写入数据。

如上图所示,扇区 A 到扇区 B 的距离要比扇区 A 到扇区 C 的距离远。如果按照 I/O 提交的顺序进行操作,那么步骤如下:

  • 当进程 A 的数据写入到扇区 A 后,将磁头移动到较远的扇区 B 处,并将进程 B 的数据写入到扇区 B。
  • 当进程 B 的数据写入到扇区 B 后,将磁头倒退回到扇区 C 处,并将进程 C 的数据写入到扇区 C 中。

聪明的读者可以发现,其实上面的过程可以进行优化。而优化的方案是:进行 I/O 操作时,按照磁盘的移动方向的顺序进行 I/O 操作,而不是按照提交的顺序进行 I/O 操作。

如上述例子中,将数据写入到扇区 A 后,应该接着写扇区 C,最后才写扇区 B。因为这样磁盘移动的距离最小,寻道所需的时间最小。

为了提高 I/O 操作的效率,Linux 内核需要对用户提交的 I/O 操作进行排序和合并,这个工作就是通过 I/O 调度层来完成。

 资料直通车:Linux内核源码技术学习路线+视频教程内核源码

学习直通车:Linux内核源码内存调优文件系统进程管理设备驱动/网络协议栈

I/O 调度层工作原理

通过前面的分析可知,I/O 调度层的主要工作是合并和排序用户提交的 I/O 操作,从而达到提升 I/O 效率的作用。

由于不同的场景或硬件所需的优化手段不一样,比如固态硬盘(SSD)就不需要对 I/O 请求进行排序。

Linux 内核为了适配不同的场景或硬件,定义了一套统一的接口。不同的 I/O 调度算法,只需要实现这套接口即可无缝接入到 I/O 调度层。如下图所示:

从上图可知,Linux 内核支持多种 I/O 调度算法,如:CFQ调度算法、Deadline调度算法 与 noop调度算法 等。我们可以根据不同的场景来选择适当的调度算法,从而提升 I/O 操作的效率。

I/O 调度层通过 elevator_ops 结构体来适配不同的 I/O 调度算法,这个结构体定义了一系列的接口。不同的 I/O 调度算法只需要实现这些接口,然后注册到 I/O 调度层后,即可被 I/O 调度层识别。

elevator_ops 结构体定义如下:

struct elevator_ops
{
    elevator_merge_fn *elevator_merge_fn;
    elevator_merged_fn *elevator_merged_fn;
    ...
    elevator_dispatch_fn *elevator_dispatch_fn;
    elevator_add_req_fn *elevator_add_req_fn;
    ...
};

elevator_ops 结构定义了很多接口,但 I/O 调度算法只需要按需实现其中部分重要的接口即可。

下面我们来介绍一下 elevator_ops 结构几个重要接口的作用:

  • elevator_merge_fn:用于判断新提交的 I/O 请求是否能够与 I/O 调度器中的请求进行合并。
  • elevator_merged_fn:用于对合并后的 I/O 请求进行重新排序。
  • elevator_dispatch_fn:用于将 I/O 调度器中的 I/O 请求分发给块设备驱动层。
  • elevator_add_req_fn:用于向 I/O 调度器添加新的 I/O 请求。

由于内核支持多种 I/O 调度算法,所以内核通过链表把所有的 I/O 调度算法连接起来。如果用户编写了新的 I/O 调度算法,可以使用 elv_register() 函数将其注册到内核中。

Deadline 调度算法

上面介绍了 I/O 调度层的原理,现在我们通过 Deadline调度算法 来分析它是怎么提升 I/O 操作的效率的。

1. 排序队列

Deadline 调度算法通过使用红黑树(一种平衡二叉树)来 I/O 请求进行排序,节点的键为 I/O 请求的开始扇区号,值为 I/O 请求实体。如下图所示:

当向设备驱动层分发 I/O 请求时,Deadline 调度器会按照排序后的顺序进行分发,这样做的好处是:可以减少磁头移动的距离。如下图所示:

虽然这样能够减少磁头移动的距离,但对 I/O 请求进行排序可能会导致某些 I/O 请求出现 饥饿 的情况,饥饿的意思是用户指发送的 I/O 请求长时间得不到执行。

试想一下以下场景:

磁盘正在扇区号 100 处执行 I/O 操作,这时用户提交一个新的 I/O 请求,此 I/O 请求的起始扇区号为 200,如下图所示:

如果用户没有提交新的 I/O 请的话,那么执行完扇区号 100 处的 I/O 请求后,便会移动到扇区号 200 处执行 I/O 请求。

此时如果用户连续在扇区号 110、120、130 处提交了新的 I/O 请求,由于 Deadline 调度器会以 I/O 请求的起始扇区号进行排序,所以 I/O 队列将会变成如下图所示情况:

执行 I/O 请求时会按照排序后的顺序进行操作,那么扇区号 200 处的 I/O 请求就很有可能出现饥饿的情况。

2. FIFO队列

为避免 I/O 请求出现饥饿的情况,Deadline 调度器还使用 FIFO(Frist In Frist Out)队列来管理 I/O 请求。

在新的 I/O 请求被提交到 Deadline 调度器时,Deadline 调度器会为 I/O 请求设置一个限期(Deadline),然后添加到 FIFO 队列中。如下图所示:

在向设备驱动层分发 I/O 请求时,Deadline 调度器首先会查看 FIFO 队列中的第一个 I/O 请求是否超时。如果超时了,那么将 FIFO 队列的第一个 I/O 请求分发给设备驱动层。否则,将会从排序队列中获取下一个 I/O 请求分发给设备驱动层。

Deadline 调度器通过设置 I/O 请求的限期和 FIFO 队列,来解决 I/O 请求出现饥饿的情况。

另外,Deadline 调度器为 读/写 操作分别各分配一个排序队列和 FIFO 队列,所以在 Deadline 调度器中维护了 4 个队列:读排序队列、写排序队列、读FIFO队列 和 写FIFO队列。

这是因为在 I/O 操作中,读操作比写操作需要的实时性更高,所以会优先处理读操作。如果将读写操作放在同一个队列进行管理,那么就不能优先处理读操作了。

 

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

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

相关文章

【强烈建议收藏:MySQL面试必问系列之慢SQL优化专题】

一.知识回顾 学习本篇文章之前呢,我们可以先看一下【强烈建议收藏:MySQL面试必问系列之SQL语句执行专题】,看完这篇文章再来学习本篇文章可谓是如虎添翼。好的,那我们也不讲太多的废话,直接开始。 二.如何做慢SQL查询优化呢&…

《uniapp基础知识》学习笔记Day38-(Period2)全局文件一些常用的配置

如果进行开发的话,首先要配置路由页面 page.json 页面路由 pages.json 文件用来对 uni-app 进行全局配置,决定页面文件的路径、窗口样式、原生的导航栏、底部的原生tabbar 等。 {"pages": [{"path": "pages/component/index…

Centos7搭建DHCP

1.简介DHCP服务器又叫动态主机协议,由服务器划分一段地址池,客户端地址池中获取IP地址及掩码等信息端口:UDP 67/68主配置文件:/etc/dhcp/dhcpd.conf租约时间文件:/etc/sysconfig/dhcpd2.简单搭建DHCP服务PS&#xff1a…

离线数据仓库项目--技术选择

文章目录(一)技术选型1)数据采集工具2)数据存储3)数据计算4)数据可视化(二)整体架构设计(三)服务器资源规划(一)技术选型 1&#xff…

MySQL索引事务

1.索引1.1概念索引是一种特殊的文件,包含着对数据表里所有记录的引用指针。可以对表中的一列或多列创建索引,并指定索引的类型,各类索引有各自的数据结果实现。(这里只用通俗的语言和图片进行介绍)1.2作用数据库中的表…

洗地机哪个牌子好?口碑最好的洗地机

选择洗地机,最关键的当然是清洁力度啦,这就要看洗地机的吸力如何了,一般情况下,吸力越大,越能够吸附顽固污渍,清洁力度就越好。然后杀菌功能也是必不可少的,毕竟是要清洁整个家的地面卫生&#…

Android 圆弧形 SeekBar

效果预览package com.gcssloop.widget;import android.annotation.SuppressLint;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Matrix;import android.graph…

ViT(Vision Transformer) TNT(Transformer in Transformer)

ViT(Vision Transformer) ViT的结构 ViT将输入图片分为多个patch(16x16),再将每个patch投影为固定长度的向量送入Transformer,后续encoder的操作和原始Transformer中完全相同。但是因为对图片分类,因此在输入序列中加…

论文复现-3

模型构建中的运算 数据集是CONLL03 这个数据集共有4种实体类型,所以,在做实体描述的embedding时,得到的语义表示的Tensor大小为 : 4*max_len, 具体指的是: type_input_ids: torch.LongTensor None, type_attention_m…

2023年中职组网络安全竞赛——web服务渗透测试解析

web服务渗透测试(100分) 题目如下: 解析如下: PS:任务环境可以私信博主,求个三连吧! 通过本地PC中的渗透测试平台KALI2020对靶机进行WEB渗透,找到页面内的文件上传漏洞并且尝试进行上传攻击,将文件上传成功后的页面回显字符串作为FLAG提交(如:点击超链接查看上传文…

Python自动化测试之requests库【发送json数据类型 】(六)

目录:导读 数据类型 application/json: application/x-www-form-urlencoded text/xml requests发送json 写在最后 我们都知道post请求中的body有4种数据类型,今天我们来写一篇关于requests请求json这种数据类型。 数据类型 我们都知道…

使用JSON.stringify的第三个参数,美化序列化后的值

事情是这样的,我在使用tiptap富文本编辑器,展示JSON代码,效果图肯定是这样的假设我有一个javascript对象如下const data {a: test }想要实现上面的效果,肯定需要使用JSON.stringifyconst editorData JSON.stringify(data)editor…

Linux中安装JDK8.跟学韩顺平

Linux中安装JDK8第16章Linux之JavaEE定制篇搭建JavaEE环境16.1 概述16.2安装JDK16.2.1安装步骤16.2.2测试是否安装成功第16章Linux之JavaEE定制篇搭建JavaEE环境 16.1 概述 如果需要在Linux下进行JavaEE的开发,我们需要安装如下软件 资料下载地址:百度…

【算法】BloomFilter概念和原理以及业务中的应用场景

思考:海量数据下去重,如果是非数值类型的话如何判断?1.什么是布隆过滤器 1970年由布隆提出的一种空间效率很高的概率型数据结构,它可以用于检索一个元素是否在一个集合中。 由只存0或1的位数组和多个hash算法, 进行判断数据 【一…

2023-03-03 mysql列存储-cpu占用100%-追踪思路

摘要: 最近在处理mysql列存储时, 发现在执行explain时, cpu占用达到了100%. 本文分析定位该问题的思路过程 现象: mysqld进程占用100%使用kill processlist终止会话, 无响应查看show processings; 发现一直在运行mysql> show processlist; +----+-----------------+-----…

图片服务器

文章目录一、项目简介二、功能及场景三、业务设计四、数据库设计准备图片表准备实体类五、API设计常用功能封装文件上传文件上传获取图片列表接口获取图片内容删除图片接口六、项目优化七、测试自动化测试测试用例一、项目简介 图片服务器:解决项目中插入图片的问题…

Java 运算符与类型转化

Java 运算符与类型转化 1 算术运算符 Java中的算术运算符主要有(加)、-(减)、*(乘)、/(除)、%(求余),它们都是二元运算符。 2 自增和自减运算…

Day906.grant语句 -MySQL实战

grant语句 Hi,我是阿昌,今天学习记录的是关于grant语句的内容。 在 MySQL 里面,grant 语句是用来给用户赋权的。 不知道有没有见过一些操作文档里面提到,grant 之后要马上跟着执行一个 flush privileges 命令,才能使…

搞懂它,带你学会高效配置交换机!

想了解更多IT学习资料,可关注公众号“IT运维大本营” 不同网段的用户想要进行三层通信,必须借助于路由表项,而VLANIF接口只能生成直连路由,实现不同网段间通过同一台设备互通,对于不同网段间跨设备…

【Linux】虚拟机设置ISO镜像、配置CentOS 7、设置快照

目录 一、设置ISO镜像 1.设置或编辑 2.配置光驱(DVD) 3.虚拟机快捷键设置 4.启动虚拟机 二、配置CentOS 7 三、设置快照 四、​​​​​​​虚拟网卡不显示怎么办? 💟 创作不易,不妨点赞💚评论❤️收…