最近由于一些控制IO带宽的需求,开始研究CFQ以及对应的IO cgroup,今天baidu了一下,竟然发现没有多少中文的介绍,所以准备写一个系列,介绍一下这个调度器,粗粗想了一下,大概可以灌四篇水,包括CFQ的基本介绍,CFQ各个配置参数的含义和调优,CFQ的基本架构以及CFQ+cgroup。各位看官要是觉得还有什么值得写的,请留言给我或者直接新浪微博 @淘伯瑜。闲话少说,言归正传。
CFQ是Completely Fair Queuing的缩写,顾名思义,他存在的主要目的就是为了保证公平性, 并为此做了大量的工作。为了说明他的公平性,让我们先来简单看看另外目前kernel另外两个IO调度器,noop和deadline。那么怎么看自己目前硬盘的调度器呢?sysfs里面就有:
cat /sys/block/sda/queue/scheduler 目前这个是设备相关的,不同的盘可以选择不同的IO调度器。
noop
这个调度器基本上什么也不做,没有自己的请求队列,不做排队,基本上是上层发什么请求就直接扔给驱动的队列(其实他也可以做简单的尾部合并,不过这个合并实际上是通用的block层代码实现,可能也不应该算在他的头上)。代码么,也只有100行左右,非常简单。对于一些非常快速的设备,如fusion IO的pci-e卡,noop的性能还是相当不错的。
deadline
这个调度器功能上有以下特点,有自己的请求队列,可以做前端合并,读写分离,并用红黑树来管理请求,红黑树的key是请求的读写位置,另外他还设置了fifo队列来管理请求的超时,这样对于一般的请求通过排序来照顾到顺序IO,并通过fifo来保证请求的响应时间。400多行的代码做到如此的简单高效,非常赞。另外一般的SSD读写混合时候效率很差,deadline使用的batch方式,读写请求的发送在某种程度上是分离的。从我们的测试来看,一般的SSD(如Intel的x25-m系列)使用deadline效果还是非常棒的。
CFQ
CFQ相对于上面两个那可真是巨无霸了,目前的block/cfq-iosched.c就有4000多行,这个还不包括blk-cgroup的1700行代码,这许多代码加起来的特性那就相当丰富了。下面咱们简单来理理。
CFQ把进程当成了基本的调度单位,也就是说各个请求现在都是属于进程的,CFQ调度的是进程,当选择了某个进程的时候,他的请求才能够被发送到设备,否则只能在自己的队列里面待着(说进程可能不太准确,这个实际上是一个task_struct里面有一个,所以可能说内核线程更准确一些,各位看官有印象就好了,下面我就不区分了)。
优先级:进程被分成不同的类别,而且又有不同的优先级,具体的分类有点复杂,建议有兴趣的看看man ionice(不知道Jens Axboe同学当时为啥要分的如此细)。
时间片:时间片是CFQ分给每个进程的基本单位,当CFQ选择了一个进程开始服务的时候,一般情况下他会给这个进程足够长的时间(slice_sync)发送请求,当该进程暂时没有请求的时候,会等待一段时间(slice_idle),这样如果他又发送新的顺序请求,就避免了不必要的磁盘seek(其实这个对SSD恰恰是有一定的副作用的,在后面的博文中会详细分析),然后再选择另外一个进程服务。当然如果有优先级高的进程,可以中断当前的进程,选择那个进程开始服务。
带宽控制:可能这里的带宽的定义比较含糊,其实准确的来说,目前CFQ是通过时间片来控制的,所以通过给各个进程分配不同的时间片,CFQ期待能够尽量保持各个进程的带宽比例,并假设IOPS或者带宽能够和时间片线性相关。
暂时就想到这么多了,各位如果还有啥好的,欢迎补充呀!
下一篇将介绍CFQ的各个参数的含义,各位感兴趣的可以先看看,主要的参数在这里:
taoma@tma-laptop1:~/kernel/linux-2.6$ ls /sys/block/sda/queue/iosched/
back_seek_max fifo_expire_async group_idle quantum slice_async_rq slice_sync
back_seek_penalty fifo_expire_sync low_latency slice_async slice_idle
原文转自:http://blogread.cn/it/article/5828