最近由於一些控制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