I/O请求进入Linux块设备层过程中主要包括几个过程:
- Plug/Unplug 队列
- Elevator 系统队列
- 设备队列
其中:
- Plug/Unplug队列主要目的是为了提高IO吞吐量。通过plug(续流)/unplug(泄流)的方式使得IO能够在plug队列中进行提前合并。更为具体内容可参考:点击打开链接
- Elevator可视为一个容器,其中提供了多种调度策略,例如NOOP, Deadline,CFQ等。
- 当请求进入设备队列后,其将准备被发送至底层驱动,由驱动层将请求转换为command并下发至设备。
这三个过程的函数入口流程如下:
-------------------------块设备层入口------------------------------
generic_make_request() :
>>>>>> q->make_request_fn()/blk_queue_bio()
>>>>>> list_add_tail(&req->queuelist, &plug->list)
-------------------------Plug/Unplug队列入口------------------------------
blk_flush_plug_list()
>>>>>> __elv_add_request()
-------------------------Elevator系统入口-----------------------------------
__elv_add_request()
>>>>>> q->elevator->type->ops.elevator_add_req_fn(q, rq)/注册为cfq_insert_request(cfq-iosched.c)
-------------------------设备队列入口----------------------------------------
q->elevator->type->ops.elevator_dispatch_fn/注册为cfq_dispatch_requests (cfq-iosched.c)
>>>>>> cfq_dispatch_request
>>>>>> cfq_dispatch_insert
>>>>>> elv_dispatch_sort
--------------------------------------------------------------------------------
Elevator系统中的CFQ调度策略:
在请求进入CFQ调度策略对应的队列中之前,在elevator中会先判断当前请求能否进行合并,若不能合并则加入至CFQ调度队列中。通过elevator入口函数,可以确定加入CFQ队列的位置。为了分析请求在CFQ中的流程,我们首先先提供CFQ整体结构,如下图:

- CFQ调度策略实现的主要目的包括两方面,一方面是为了实现IO带宽进行公平性控制,另一方面是为了实现对IO的QoS控制。因此,在CFQ调度策略中引入了Cgoup的概念,对应的在CFQ实现过程中表现为cfq_group。每个cfq_group对象都是针对一个底层设备对象。它们通过红黑树的方式进行组织。
- 在每个cfq_group对象中,每个线程将会被匹配到某一个cfq_queue队列,在每个cfq_queue队列中,通过时间片管理的方式实现线程中I/O请求的调度控制。不同的线程或者说不同的I/O请求根据它们的IOPRIO_CLASS可分为三种类型的cfq_queue,分别为Real Time,Best Effort,Idle,三种类型的优先级依次下降。
- 另外,在每个cfq_queue队列中,请求存在两种组织方式,分别为红黑树和FIFO方式。其中FIFO方式是根据请求的时间顺序进行排序,其作用是为了避免请求超时处理。
Linux I/O调度解析
本文详细介绍了Linux块设备层的I/O请求处理流程,包括Plug/Unplug队列、Elevator系统队列及设备队列的过程。重点分析了CFQ调度策略如何实现公平性和QoS控制。
388

被折叠的 条评论
为什么被折叠?



