linux的CFQ調(diào)度器解析_第1頁(yè)
linux的CFQ調(diào)度器解析_第2頁(yè)
linux的CFQ調(diào)度器解析_第3頁(yè)
linux的CFQ調(diào)度器解析_第4頁(yè)
linux的CFQ調(diào)度器解析_第5頁(yè)
已閱讀5頁(yè),還剩4頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、cfq_queue 的屬性中,包括 workload priority: IDLE, BE, RT,包括 workload type: ASYNC, SYNC_NOIDLE, SYNC。同時(shí)cfq_queue雖然基于CFQ調(diào)度器,但其內(nèi)部的算法還是基于 dead-line 的cfq_group 包含了多個(gè)紅黑樹(shù) service tree,對(duì)應(yīng)不同 workload priority, workload type一些工具性質(zhì)的函數(shù):cfq_find_cfqg(struct cfq_data *cfqd, struct blkio_cgroup *blkcg):如果 blkcg 是全局的 blki

2、o_root_cgroup,則返回 cfq_data-root_group,否則首先調(diào)用 blkiocg_lookup_group 在全局 的blkio_cgroup的hash列表中查找_key為cfq_data指針的blkio_cgroup結(jié)構(gòu)。通過(guò) blkio_cgroup查找cfq_group的方法很簡(jiǎn)單,通過(guò)一個(gè)container_of宏就可以。說(shuō)的通俗一點(diǎn), 就是我們已經(jīng)通過(guò)進(jìn)程找到了對(duì)應(yīng)的blkio_cgroup,可能是一個(gè)根cgroup也可能是某個(gè)子 cgroup,但這個(gè)cgroup的設(shè)置未必會(huì)有相應(yīng)的device,e.g.只設(shè)置了 blkio.weight而沒(méi)有設(shè)置 blkio

3、.dev_weight,這時(shí)cfq_data就派上用場(chǎng)了。假設(shè)這種場(chǎng)景:一個(gè)cgroup中的不同進(jìn)程讀 寫不同的block device,甚至一個(gè)進(jìn)程讀寫不同的device,但proportional weight只是針對(duì)單個(gè) 塊設(shè)備來(lái)的,【這里應(yīng)該理解為什么blkio_cgroup會(huì)有多個(gè)blkio_group的哈希項(xiàng)了吧】,因此 需要通過(guò)cfq_data這個(gè)key來(lái)找到那個(gè)blkio_group結(jié)構(gòu)(順便填入cfq_group-blkg.dev,通 過(guò) cfq_data-queue-backing_dev_info 得來(lái))cfq_get_cfqg(struct cfq_data *cfqd

4、):首先通過(guò) current 指向的當(dāng)前的 task_struct,查找其所 屬的blkio_cgroup,如果當(dāng)前task_struct還沒(méi)有加入cgroup,則返回全局的blkio_root_cgroup, 其對(duì)應(yīng)的 cfq_group 結(jié)構(gòu)是cfq_data-root_group。再調(diào)用 cfq_find_cfqg,由于傳入了 cfq_data, 因此可以找到cfq_data對(duì)應(yīng)的cfq_cgroup結(jié)構(gòu)。如果沒(méi)有找到則調(diào)cfq_alloc_cfqg初始化一個(gè) cfq_group 結(jié)構(gòu),再通過(guò) current 找到 blkio_cgroup,最后調(diào)用 cfq_init_add_cfqg_

5、lists 把 cfq_data, cfq_group, blkio_cgroup三個(gè)結(jié)構(gòu)關(guān)聯(lián)起來(lái)。cfq_get_queue(struct cfq_data *cfqd, bool is_sync, struct io_context *ioc, gfp_t gfp_mask):通過(guò)ioc得到cfq_data所關(guān)聯(lián)的塊設(shè)備上進(jìn)程的cfq_queue,其關(guān)鍵函數(shù)為 cfq_find_alloc_queue,該函數(shù)首先調(diào)用cfq_get_cfqg,通過(guò)current指向的當(dāng)前CPU上在跑的 進(jìn)程來(lái)找到cfqd所在塊設(shè)備上的cfq_group ;其次調(diào)用cfq_cic_lookup來(lái)得到塊設(shè)備對(duì)應(yīng)

6、的 cfq_io_context,從而得到對(duì)應(yīng)的cfq_queue (根據(jù)其是否同步請(qǐng)求);最后如果這時(shí)cfq_queue 為空,則調(diào)用kmem_cache_alloc_node重新分配一個(gè)cfq_queue,并將其初始化完畢cfq_init_add_cfqg_lists(struct cfq_data *cfqd, struct cfq group *cfqg, struct blkio_cgroup *blkcg):把 cfqg-blkg 這個(gè) block_group 加到 blkcg 的哈希表中,這里哈希鍵 值是cfq_data的指針值。同時(shí)cfqd這個(gè)cfq_data結(jié)構(gòu)也保存了一個(gè)哈

7、希表,表頭是 cfq_data-cfqg_list,該函數(shù)會(huì)把cfq_group也同時(shí)加到這個(gè)哈希表里【這里可以看到, blkio_cgroup會(huì)保存一個(gè)blkio_group的哈希表,每個(gè)cfq_data對(duì)應(yīng)一個(gè)blkio_group】。同時(shí) 每個(gè)cfq_data也會(huì)保存一個(gè)哈希表,記錄這個(gè)cfq_data對(duì)應(yīng)的塊設(shè)備下的所有cfq_groupcfq_get_io_context(structcfq_data *cfqd, gfp_tgfp_mask):/*Setup general io context and cfq io context. There can be several cf

8、qio contexts per general io context, if this process is doing io to morethan one device managed by cfq.*/上面這段解釋了為什么一個(gè)io_context里會(huì)有多個(gè)cfq_io_context,因?yàn)橐粋€(gè)進(jìn)程可能同時(shí)讀寫 多個(gè)設(shè)備,這時(shí)需要通過(guò)cfq_data來(lái)確定塊設(shè)備,從而得到基于這個(gè)塊設(shè)備IO的cfq_io_context該函數(shù)首先調(diào)用cfq_cic_lookup查找是否已有cfq_io_context,如果有了就退出,否則調(diào)用 cfq_alloc_io_context 倉(cāng)ll建一個(gè) cfq

9、_io_context,把這個(gè) cfq_io_context 力口入U(xiǎn) io_context 的 radix_tree 里(key 值為 cfq_data 指針),如果有必要?jiǎng)t調(diào)用 cfq_ioc_set_ioprio, cfq_ioc_set_cgroup 來(lái)設(shè)置 io priority 和 cgroupcfq_ioc_set_cgroup(struct io_context *ioc):對(duì)于 ioc 的哈希表 ioc-cic_list 中的每一個(gè) hash node (實(shí)際上是 cfq_io_context),調(diào)用 changed_cgroup。其中 changed_cgroup 的作用是

10、 把cfq_io_context的cfq_queue類型的同步隊(duì)列設(shè)置為NULL,代碼中的解釋如下/*Drop reference to sync queue. A new sync queue will beassigned in new group upon arrival of a fresh request. */cfq_ioc_set_ioprio(struct io_context *ioc):和 cfq_ioc_set_cgroup 類似,跳過(guò)了cfq_cic_lookup(struct cfq_data *cfqd, struct io_context *ioc) : io_c

11、ontext 保存 了 一個(gè) radix_tree,其樹(shù)根為 io_context-radix_root。據(jù)我猜測(cè),io_context 為什么要包含一個(gè) cfq_io_context的radix tree呢?可能是因?yàn)檫M(jìn)程會(huì)同時(shí)讀寫多個(gè)塊設(shè)備,因此根據(jù)cfq_data的 成員cic_index,里面是cfq_data對(duì)應(yīng)的塊設(shè)備在radix tree里的索引。最后返回io_context中 相應(yīng)塊設(shè)備對(duì)應(yīng)的cfq_io_contextcfq_cic_link(struct cfq_data *cfqd, struct io_context *ioc, struct cfq_io_contex

12、t *cic, gfp_tgfp_mask):具體的代碼注釋講的很清楚了,跳過(guò)/*Add cic into ioc, using cfqd as the search key. This enables us to lookupthe process specific cfq io context when entered from the block layer.Also adds the cic to a per-cfqd list, used when this queue is removed. */cic_to_cfqd(struct cfq_io_context *cic) : c

13、fq_io_context 的 key 就是對(duì)應(yīng)的 cfq_datacfq_set_request(struct request_queue *q, struct request *rq, gfp_t gfp_mask):這里可以 看到,有 struct cfq_data *cfqd = q-elevator-elevator_data 說(shuō)明 cfq_data 是基于塊設(shè)備的。 該函數(shù)作用是為一個(gè)request來(lái)分配相應(yīng)的cfq_io_context, cfq_queue并存到request-elevator_private 中。cfq_scaled_cfqq_slice(struct cfq

14、_data *cfqd, struct cfq_queue *cfqq):通過(guò)一系列公式, 計(jì)算出一個(gè)cfq_queue所占用的time_slice。首先計(jì)算cfq_cgroup中的平均cfq_queue個(gè)數(shù), 以及每個(gè)cfq_queue的time slice,相乘得到expect_latency為這個(gè)cgroup希望得到的time slice; 同時(shí)調(diào)用cfq_group_slice按照權(quán)重比例計(jì)算出cgroup的time slice;如果這個(gè)time slice小于 expect_latency,則調(diào)整之前根據(jù)cfq_queue的優(yōu)先級(jí)計(jì)算出的slice,否則返回之前調(diào)用 cfq_prio

15、_to_slice 得到的 time slicecfq_prio_slice cfq_prio_to_slice cfq_scale_slice :這三個(gè)函數(shù)都是計(jì)算隊(duì)列的服務(wù)時(shí)間slice time 的cfq group slice : cfq_data-grp_service_tree 為一個(gè) cfq_rb_root 為一個(gè)紅黑樹(shù)樹(shù)根,其成員 total_weight為這個(gè)塊設(shè)備上所有cgroup的權(quán)重值,而cfq_group-weight為該cgroup的權(quán)重 值,因此該函數(shù)返回基于cfq_target_latency,300ms,各個(gè)cgroup所占用的slice時(shí)間,基于 weigh

16、t的比例。cfq_set_prio_slice :設(shè)置 cfq_queue 中對(duì)應(yīng)的 slice_start, slice_end, allocated_slicecfq_choose_req(struct cfq_data *cfqd, struct request *rq1, struct request *rq2, sector_t last):看代碼中的解釋/*Lifted from AS - choose which of rq1 and rq2 that is best served now.We choose the request that is closest to the

17、head right now. Distancebehind the head is penalized and only allowed to a certain extent.*/基本上可以認(rèn)為,同步請(qǐng)求優(yōu)先異步請(qǐng)求,其次根據(jù)請(qǐng)求的位置,按照和AS類似的算法決定優(yōu) 先處理哪個(gè)請(qǐng)求_cfq_group_service_tree_add(structcfq_rb_root *st, structcfq_group *cfqg):向 service tree插入一個(gè)cfq_group,其中紅黑樹(shù)的key被編程為static inline s64cfqg_key(struct cfq_rb_roo

18、t *st, struct cfq_group *cfqg)return cfqg-vdisktime - st-min_vdisktime;這邊vdisktime和min_vdisktime是干什么用的,目前我也不清楚cfq_link_cfqq_cfqg(struct cfq_queue *cfqq, struct cfq_group *cfqg):這個(gè)函數(shù)本身沒(méi)啥 可說(shuō)的,但是驗(yàn)證了在CFQ調(diào)度器中,所有的異步請(qǐng)求都屬于cfq_data-root_group這個(gè)cgroup, 因此不受指定cgroup的任何限制#1248 - #1267這段代碼,是不需要cgroup調(diào)度支持的cfq調(diào)度器代

19、碼,可以看出簡(jiǎn)單很多, cfq_get_cfqg 只是簡(jiǎn)單返回 cfq_data-root_groupcfq_service_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq, bool add_front): 該函數(shù)目的是把cfq_queue加入到cfq_group對(duì)應(yīng)的service_tree的紅黑樹(shù)中。首先根據(jù)io class, io priority來(lái)找到cfq_group對(duì)應(yīng)的service_tree,類型為cfq_rb_root,其中插入的key是計(jì)算 出來(lái)的一個(gè)起始時(shí)間,應(yīng)該cfq_group是按照這個(gè)起始時(shí)間來(lái)依次處理

20、掛在上面的所有 cfq_queue 的請(qǐng)求。 最后調(diào)用 cfq_group_notify_queue_add 來(lái)通矢日 cfq_datacfq_prio_tree_lookup, cfq_prio_tree_add :這兩個(gè)函數(shù)都是把 cfq_queue 加到 cfq_data 里 的priority tree的紅黑樹(shù)中,cfq_data共有8個(gè)priority tree,對(duì)應(yīng)不同的優(yōu)先級(jí),而紅黑樹(shù)中的 排序基于cfq_queue中第一個(gè)請(qǐng)求的sector positioncfq_resort_rr_list,cfq_add_cfqq_rr,cfq_del_cfqq_rr:前者把 cfq_qu

21、eue 加到 cfq_data 中的 cgroup 對(duì)應(yīng)的 service_tree 數(shù)組,以及 cfq_data 的 priority tree的紅黑樹(shù)中。后者除了調(diào)用 cfq_resort_rr_list 以夕卜,還遞增了 cfq_data-busy_queues, cfq_data-busy_sync_queues最后把 cfq_queue 移除出 service tree,和 priority tree,并調(diào)用 cfq_group_notify_queue_del 通知 cfq_datacfq_del_rq_rb,cfq_add_rq_rb :這兩個(gè)函數(shù)操作cfq_queue里面的re

22、quest請(qǐng)求,把請(qǐng)求從 cfq_queue中添加或者刪除cfq_add_rq_rb首先調(diào)用elv_rb_add把請(qǐng)求插到cfq_queue-sort_list這個(gè)紅黑樹(shù)中,基于請(qǐng)求 的起始sector,再調(diào)用cfq_dispatch_insert真正把請(qǐng)求下發(fā)到底層驅(qū)動(dòng)上,下面再調(diào)用 cfq_add_cfqq_rr把隊(duì)列掛到cfq_data代表的塊設(shè)備上,下面重新選擇cfq_queue-next_rq,如 果和之前的cfq_queue-next_rq不同,需要改動(dòng)cfq_queue對(duì)應(yīng)的優(yōu)先級(jí)并調(diào)整到隊(duì)列所在的 cfq_data 下的 priority tree 中cfq_del_rq_rb

23、 調(diào)用 elv_rb_del 把請(qǐng)求從 cfq_queue-sort_list 中刪除,如果此時(shí) cfq_queue-sort_list為空了,而該隊(duì)列又在cfq_data的priority tree中,則從紅黑樹(shù)里刪除掉cfq_remove_request(struct request *rq):調(diào)用 cfq_del_rq_rb 從 cfq_queue 中刪除 rqcfq_find_rq_fmerge(struct cfq_data *cfqd, struct bio *bio):通過(guò)當(dāng)前 current 的 task_struct 來(lái)找到io_context,從而調(diào)用cfq_cic_loo

24、kup來(lái)找到cfq_io_context,然后根據(jù)bio是否同步找 到對(duì)應(yīng)的cfq_queue;下面找到bio之后的第一個(gè)sector,然后在cfq_queue-sort_list中基于 這個(gè)sector查找是否有對(duì)應(yīng)的bio可以被mergecfq_merge :檢查是否可以merge,如何可以修改對(duì)應(yīng)的request,把bio給merge進(jìn)requestcfq_merged_request:調(diào)用 cfq_reposition_rq_rb,把相應(yīng)的 request 更新為已經(jīng) merge 了 bio 的 request_cfq_set_active_queue :似乎是初始化 cfq_queu

25、e,并將其設(shè)置為 active_queue_cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq, bool timed_out):/* current cfqq expired its slice (or was too idle), select new one*/#1744 - #1751 ( 3.0.23 cfq-iosched.c)這里的 cfq_queue-slice_resid 似乎是還沒(méi)有 用完的 slice_time nr_sync計(jì)算出cfq_group同步隊(duì)列的個(gè)數(shù) cfq_gr

26、oup_servedcharge表示已經(jīng)用掉的配額,在不同模式下意義不同,如果是iops模式,用cfq_queue-slice_dispatch,也就是dispatch的請(qǐng)求個(gè)數(shù)作為不同的cfq_queue的配額,如果 是異步請(qǐng)求則用cfq_queue-allocated_slice,也就是分配給該隊(duì)列的時(shí)間作為配額;否則是同步非iops模式則等同于used_sl (通過(guò)cfq_cfqq_slice_usage計(jì)算得出)#975 - #978 cfq_group-vdisktime 似乎是改 cgroup 至今所有用掉的 slice 總和如果當(dāng)前的 cfq_group 的 expire 時(shí)間(

27、cfq_data-workload_expires)在 jiffies 之前,那啥也不 用做了,不然保存相應(yīng)的 cfq_group 的 saved_workload_slice,saved_workload,saved_serving_prio最后調(diào)用 cfq_resort_rr_list,把 cfq_queue 插至cfq_group,cfq_data 對(duì)應(yīng)的 service tree, prio tree 的紅黑樹(shù)中所以代碼看下來(lái),我猜測(cè)所有的cfq_queue開(kāi)始時(shí)都在cfq_data和其對(duì)應(yīng)的cfq_group的service tree,priority tree中,當(dāng)輪到這個(gè)cfq_

28、queue被處理時(shí),從這些紅黑樹(shù)中被摘下來(lái),等到其slice expired之后,更新一系列參數(shù)后被放回原來(lái)的紅黑樹(shù)里;再進(jìn)一步說(shuō),如果cfq_queue里已經(jīng) 沒(méi)有請(qǐng)求了,則會(huì)把他們從紅黑樹(shù)里移除掉,這應(yīng)該就是CFQ大致的工作原理cfq_dist_from_last,cfq_rq_close :前者計(jì)算出request的sector和cfq_data的last_position對(duì)應(yīng)的sector之間相隔的sector數(shù),后者拿這個(gè)值和CFQ_CLOSE_THR比較,如果在這個(gè)范圍內(nèi)就認(rèn)為兩個(gè)request是相近的請(qǐng)求(言下之意不會(huì)對(duì)磁頭轉(zhuǎn)動(dòng)造成太多的overhead)cfqq_close(s

29、truct cfq_data *cfqd, struct cfq_queue *cur_cfqq)/*First, if we find a request starting at the end of the lastrequest, choose it.*/首先調(diào)用 cfq_prio_tree_lookup 查找同一個(gè) priority tree 下的 cfq_queue 中,有沒(méi)有起始 sector 正好在cfq_data-last_position上的,如果有則返回這個(gè)離當(dāng)前磁頭位置最近的cfq_queue/*If the exact sector wasnt found, the p

30、arent of the NULL leafwill contain the closest sector.*/如果cfq_prio_tree_lookup沒(méi)有找到,則返回的parent參數(shù)包含了 sector差別最小的那個(gè) cfq_queue,如果這個(gè) cfq_queue-next_rq 滿足了 cfq_rq_close 的要求,則返回這個(gè) cfq_queue如果不滿足的,開(kāi)始遍歷這個(gè)紅黑樹(shù)(只遍歷一次),再次判斷這個(gè)cfq_queue是否滿足cfq_rq_close,如果不滿足就返回NULLcfq_choose_wl, choose_service_tree :選擇最優(yōu)的 workload

31、 class, 和選擇最優(yōu)的 service treechoose_service_tree 選擇的優(yōu)先級(jí)是 RT BE IDLE,這個(gè)決定了 cfq_data-serving_prio, 然后調(diào)用 cfq_choose_wl 來(lái)決定 cfq_data-serving_type,/*the workload slice is computed as a fraction of target latencyproportional to the number of queues in that workload, overall the queues in the same priority c

32、lass*/group_slice調(diào)用cfq_group_slice,根據(jù)group的權(quán)重計(jì)算出來(lái),而slice則是這個(gè)workload里 的queues占所有busy_queues_avg的比例而計(jì)算得出的對(duì)于同步請(qǐng)求而言,slice在經(jīng)過(guò)一系列的比對(duì)之后,會(huì)把cfq_data-workload_expires = jiffies + slice,即當(dāng)前服務(wù)的cfq_queue的配額時(shí)間被放到cfq_data指定的成員中;而對(duì)于異步請(qǐng)求而 言,由于異步的優(yōu)先級(jí)比同步要低,會(huì)再經(jīng)過(guò)一些處理,具體的請(qǐng)參考代碼/*Async queues are currently system wide. Ju

33、st takingproportion of queues with-in same group will lead to higherasync ratio system wide as generally root group is goingto have higher weight. A more accurate thing would be tocalculate system wide asnc/sync ratio.*/static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd):/*Select a queu

34、e for service. If we have a current active queue,check whether to continue servicing it, or retrieve and set a new one.*/這里可以參考之前關(guān)于cfq_slice_expired函數(shù)的解析,可以看到cfq_data每個(gè)時(shí)刻只服務(wù)一個(gè) cfq_queue,就是 cfq_data-active_queuecfq_may_dispatch(struct cfq_data *cfqd, struct cfq_queue *cfqq):判斷是否可以向底層驅(qū) 動(dòng)分發(fā)請(qǐng)求#2463如果cfq

35、_queue允許idle 一段時(shí)間,同時(shí)塊設(shè)備還有異步請(qǐng)求on-the-fly,暫時(shí)不分發(fā)#2469如果要分發(fā)的這個(gè)cfq_queue是一個(gè)異步隊(duì)列,同時(shí)塊設(shè)備上還有同步請(qǐng)求on-the-fly, 暫時(shí)不分發(fā)#2472先給max_dispatch設(shè)定個(gè)初始值,默認(rèn)是cfq_quantum/2 = 4 #2473 對(duì)于 idle 級(jí)別的 cfq_queue,max_dispatch 設(shè)為 1 先看#2542,如果當(dāng)前cfq_queue-dispatched,即已經(jīng)分發(fā)的請(qǐng)求數(shù)目沒(méi)有超過(guò)max_dispatch, 如果是同步隊(duì)列則允許分發(fā),異步隊(duì)列的話,需要修改下max_dispatch的值并重新

36、和 cfq_queue-dispatched比較,具體原因請(qǐng)看代碼注釋/*Async queues must wait a bit before being allowed dispatch.We also ramp up the dispatch depth gradually for async IO,based on the last sync IO we serviced */再回到#2479,如果此時(shí)cfq_queue-dispatched已經(jīng)超過(guò)了 max_dispatch,如果這是個(gè)同步 cfq_queue,同時(shí)此時(shí)塊設(shè)備上只有這個(gè)cfq_queue有請(qǐng)求,那么不限制該隊(duì)列的分發(fā)

37、請(qǐng)求數(shù), 如下面注釋/*If there is only one sync queuewe can ignore async queue here and give the syncqueue no dispatch limit. The reason is a sync queue canpreempt async queue, limiting the sync queue doesnt makesense. This is useful for aiostress test.*/否則如果只有一個(gè) cfq_queue,放大一倍 max_dispatch 的值,到 cfq_data-cfq_

38、quantum = 8不管怎樣,最后還是要比較一次cfq_queue-dispatched和max_dispatch的值,來(lái)決定是否給 底層驅(qū)動(dòng)分發(fā)下一個(gè)請(qǐng)求cfq_exit_io_context:當(dāng)一個(gè) task 結(jié)束之后,需要對(duì) io_context 關(guān)聯(lián)的所有 cfq_io_context, 調(diào)用 cfq_exit_single_io_contextcfq_exit_single_io_context,_cfq_exit_single_io_context:對(duì) cfq_io_context 的異步,同步隊(duì)列,分別調(diào)用cfq_exit_cfqqchanged_cgroup(struct i

39、o_context *ioc, struct cfq_io_context *cic):首先無(wú)視掉cic對(duì)應(yīng)的異步隊(duì)列,由此也可以看出其實(shí)CFQ里,異步請(qǐng)求是不分cgroup的,下 面直接把cfq_io_context里的同步隊(duì)列設(shè)置為NULL,代碼中的注釋告訴了為什么要這么做/*Drop reference to sync queue. A new sync queue will beassigned in new group upon arrival of a fresh request.*/cfq getqueue(struct cfq_data *cfqd, bool is_sync,

40、 struct io_context *ioc, gfp_tgfp_mask):如果是is_sync表示異步,調(diào)用cfq_async_queue_prio返回塊設(shè)備對(duì)應(yīng)的異步隊(duì) 列;否則調(diào)用cfq_find_alloc_queue來(lái)創(chuàng)建一個(gè)新隊(duì)列cfq getio context(struct cfq_data *cfqd, gfp_t gfp_mask):/*Setup general io context and cfq io context. There can be several cfqio contexts per general io context, if this proce

41、ss is doing io to morethan one device managed by cfq.*/首先調(diào)用get_io_context,獲取current指向的task_struct對(duì)應(yīng)的io_context,如果沒(méi)有則創(chuàng)建 一個(gè)io_context;下面調(diào)用cfq_cic_lookup獲取cfq_io_context,如果為空則調(diào)用 cfq_alloc_io_context 倉(cāng)ll建一個(gè) cfq_io_context,并調(diào)用 cfq_cic_link 把 cfq_io_context 和 io_context 關(guān)聯(lián)起來(lái); 最后調(diào)用 cfq_ioc_set_ioprio, cfq_

42、ioc_set_cgroup,實(shí)際上是對(duì)每個(gè) cfq_io_context,調(diào)用 changed_ioprio,changed_cgroup,這些函數(shù)是設(shè)置個(gè) ioprio_changed, cgroup_changed之類的標(biāo)簽cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq, struct cfq_io_context *cic):首先,如果是異步隊(duì)列或者隊(duì)列級(jí)別為IDLE,不考慮idle (slice_idle, group_idle之類的磁頭停 留時(shí)間)如果 cfq_queue-next_rq-cm

43、d_flags 包含了 REQ_NOIDLE,不考慮 idle;如果 slice_idle 為 0, 也不考慮idle;如果io_context-nr_tasks為0,也不考慮idle最后根據(jù)前后是否 idle,調(diào)用 cfq_mark_cfqq_idle_window/cfq_clear_cfqq_idle_windowcfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq, struct request *rq):判斷new_cfqq是否可以搶占/*Check if new_cfqq should preemp

44、t the currently active queue. Return 0 forno or if we arent sure, a 1 will cause a preempt.*/#3317如果new_cfqq是idle class的,其最低優(yōu)先級(jí)無(wú)法搶占#3320如果cfqq,也就是cfq_data-active_queue是idle class的,必定可以被搶占#3326不允許非RT搶占RT的cfq_queue#3333當(dāng)前cfqq不是同步隊(duì)列,那么同步請(qǐng)求所在隊(duì)列可以搶占#3336如果兩個(gè)隊(duì)列不屬于同一個(gè)cgroup,不可搶占#3339如果當(dāng)前cfqq時(shí)間片已經(jīng)用完,可以搶占#3353如果請(qǐng)求是基于元數(shù)據(jù)的,可以搶占#3359 RT請(qǐng)求可以搶占非RT的請(qǐng)求cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq):/* * cfqq preempts the active queue. if we allowed preempt with no slice left,* let it have half of its nominal

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論