Linux块设备中的IO路径和调度策略

发布者:上海IT外包来源:http://www.lanmon.net点击数:1170

当文件系统通过submit_bio提交IO时,请求进入通用块层。通用块层对IO执行一些预处理操作。目的是确保可以更合理地将请求发送到底层磁盘设备,并保证最佳性能。这里更重要的是IO调度模块。每个人都可能听说过CFQ,除了DeadLine和Noop,它们都是磁盘调度算法。其中,CFQ调度算法是最常用的。
如果忽略堆栈结构和块设备的各种映射,简化的结构大约有3层,如图1所示。这里的3层不是所有软件,而是硬件。不用说,一般的阻塞层,这里主要完成IO合并和调度操作。下面是驱动程序层,驱动程序层是硬件驱动程序,用于将IO请求转换为硬件寄存器上的操作(注意:不同的块设备有不同,不可避免的iSCSI设备不会有寄存器操作)。对于不同的物理设备,驱动程序层的程序是不同的。例如,对于SAS直连磁盘,驱动程序层程序是SAS驱动程序,如果FC-HBA卡连接到FC-SAN,则驱动程序层是FC驱动程序(例如,Qlogic驱动程序)。
Linux块设备中的IO路径和调度策略
图1块设备分层
底层是设备层,设备层通常是硬件设备。这里有多种硬件,如SAS卡,SATA卡,FC-HBA卡或iSCSI-HBA卡。但有时它可能不是硬件设备。例如,对于iSCSI,该层可以是由软件模拟的设备层,并且其请求通过网卡发送到目标设备。
主要数据结构和流程
大多数程序由两部分组成:数据结构和算法。数据结构相当于程序的骨架,算法是程序的肋骨和肉体。数据结构通过算法链接以形成完整的整体。人类认知规律从具体到抽象,从简单到复杂,所以我们从数据结构入手。通过了解数据的数据结构,我们可以更容易地理解块设备IO的整个逻辑。块设备IO中最关键的数据结构是request_queue,它是请求队列。数据结构的简化图如图2所示。数据结构本身非常复杂。我们在这里简化了它,只留下了一些关键成员。该图的颜色部分是两个功能指针,分别用于接收请求和处理请求。
Linux块设备中的IO路径和调度策略
图2请求队列数据结构
为了便于理解,让我们举一个例子。以NBD块设备为例,当块设备初始化时,make_request_fn初始化为blk_queue_bio,request_fn初始化为do_nbd_request。对于SCSI块设备,request_fn初始化为scsi_request_fn。
通过了解上述数据结构和关键成员初始化的结果,我们可以分析块设备整个过程的细节。块设备请求的条目是submit_bio,在简单检查后调用。
Linux块设备中的IO路径和调度策略
从上面的代码可以看出,IO处理的入口函数实际上是函数指针make_request_fn,我们知道指针实际上是函数blk_queue_bio。因此,块设备的请求将由blk_queue_bio函数处理。
磁盘调度策略
Linux内核为设计磁盘调度策略提供了极大的灵活性。磁盘的调度策略由插件注册在内核中,即用户可以自由选择磁盘的调度策略。
调度算法的思想实际上非常简单,主要是通过IO的排序,合并和批处理来优化磁盘搜索和请求的处理时间。这里值得解释的当前调度算法实际上更适用于机械磁盘,因为机械磁头定位占总IO处理时间的很大一部分。当然,对于SSD磁盘,调度算法也有一些帮助,需要特别注意IO的特性。
Linux块设备中的IO路径和调度策略
图3调度策略结构
磁盘调度策略的结构定义如图3所示。每个变量的含义也比较清楚,此处不再赘述。本文主要研究elev_ops类型的变量ops,它是调度策略的具体功能实现。任何调度算法都必须实现其中一些功能。
调度策略的实现是通过这些回调函数完成的。为了理解调度策略的功能集是什么,我编译了一个表。让我们来看看每个函数的作用。对于调度策略,并非所有这些功能都必须实现。只有下表中带*的是必须实现的功能。Linux块设备中的IO路径和调度策略
简而言之,上述回调函数的功能是确定是否可以合并,合并和请求请求。上述回调函数更多,使用场景更复杂,特别是使用散布在调度程序中的许多进程。因此,我们很难一次性介绍所有场景。为了更直观地理解上述回调函数的作用,我们以Deadline调度策略为例进行简要介绍。
图4显示了Deadline初始化的回调函数。从图中可以看出,这里没有初始化所有回调函数,并且只初始化了16个回调函数中的9个。
Linux块设备中的IO路径和调度策略
图4截止日期回调函数
我们专门分析了函数的调用场景。我们引入了elevator_merge_fn函数来查询可以与bio合并的请求。如图5所示,整个调用堆栈,条目是blk_queue_bio,这个函数我们之前介绍过,它是调度程序的入口点。此函数调用elv_merge以查找是否有任何可以合并并返回的请求。由elv_merge函数调用的官方Deadline调度程序提供的回调函数。判断完成后,函数根据实际情况返回请求(或未找到,不返回)和可合并方向(例如,前向合并,后向合并等),后续流程将执行特定的合并操作。
图5函数调用堆栈
由于IO调度涉及许多过程,因此仅限于本文,今天将在此处介绍。稍后,我们将更深入地介绍有关IO调度的更多信息。
IT外包
>
400-635-8089
立即
咨询
电话咨询
服务热线
400-635-8089
微信咨询
微信咨询
微信咨询
公众号
公众号
公众号
返回顶部