linux調度器(七)——other cfs class api and functions

來源:互聯網
上載者:User

OTHER CFS CLASS API

set_curr_task_fair(rq):將cpu運行隊列裡的當前運行進程設定為cfs運行隊列裡當前啟動並執行進程(set_curr_task_fair),對於組調度則必須把它上級的se也設定為相應cfs_rq的當前運行進程。該介面主要用於修改某個進程的調度策略(__sched_setscheduler調度器類的運行隊列資訊也需要更新)或把一個進程從一個group遷移到另一個group的過程(__sched_move_task此時如果它是正在啟動並執行,則需讓它在新的group
cfs_rq中也處於執行狀態),注意:這裡並不需要resched_task當前進程

switched_to_fair(rq, p, running):把rq裡的進程p的調度策略切換到CFS。如果p是正在啟動並執行,那麼直接resched_task它;否則判斷p是否能夠搶佔當前啟動並執行進程。顯然該介面也用於調度策略改變時調用(check_class_changed)

prio_changed_fair(rq, p, oldprio, running):該函數在p的優先順序被改變時調用(在調度架構的__sched_setscheduler-à check_class_changed被調用)。如果p是正在啟動並執行進程,並且它的優先順序降低了,那麼直接resched_task它,否則調用check_preempt_curr檢查當前啟動並執行是否該被p搶佔(check_class_changed)

yield_task_fair(rq):該介面用於系統調用sched_yield中,這本身的邏輯非常簡單:把當前進程從buddies中刪除,並且更新它的執行時間update_curr,最後把它設定為skip_buddy(上面的pick_next_task我們說過如果是skip的話,在選擇的時候會被skip的),這裡及sched_yield系統調用並沒有把當前進程設定為TIF_NEED_RESCHED,這是因為在sched_yield裡直接調用了schedule,而不再需要在系統調用返回時去檢查

yield_to_task_fair(rq, p, preempt):該函數不僅讓當前進程讓出CPU,而且想讓p進程優先運行set_next_buddy,該介面用於yield_to函數中

CFS內部主要函數

__pick_first_entity(cfs_rq):獲得cfs_rq紅/黑樹狀結構隊列裡最左邊的節點

__pick_next_entity(se):獲得se所在紅/黑樹狀結構的se的後一個節點

entity_key(cfs_rq, se):se在cfs_rq的紅/黑樹狀結構中的key,se->vruntime - cfs_rq->min_vruntime,這裡使用這個差值為key(標準化後的),是因為vruntime本身為usigned long而且是一個遞增的值, vruntime溢出了,那麼就會導致順序混亂,所以key不能直接使用vruntime,而這個差值就是為了防止溢出

update_min_vruntime(cfs_rq):更新cfs_rq的min_vruntime,並且它保證每次將要更新的min_vruntime都大於等於當前的min_vruntime,即max(cfs_rq->min_vruntime,min(cfs_rq->curr->vruntime, cfs_rq->rb_leftmost->vruntime)),所以min_vruntime也是遞增的

calc_delta_mine(delta_exec,weight, lw):該函數用於計算物理delta_exec時間的相對時間,這個時間用delta_exec為基數 乘以 第二個參數與最後一個參數比重,即delta_exec * weight / lw.於是就有以下幾種情況:
delta_exec為一個se實質啟動並執行物理時間,第二個參數為NICE_0的權重,第三個參數為該se的本身權重:該Function Compute出來的值就是該se它運行了delta_exec物理時間對應的虛擬時間,如calc_delta_fair;
delta_exec為一個運行隊列的運行周期(物理時間),第二個參數為當前se的權重,第三個參數為運行隊列本身的權重:該Function Compute出來的值就是該se在當前運行隊列中即將(理想)啟動並執行物理時間,如sched_slice非組調度。

calc_delta_fair(delta,se):計算se執行的delta物理時間的相應的虛擬時間

__sched_period(nr_running):該函數用於計算當前運行隊列所有se運行一遍所需要的時間周期,這是一個實質物理時間,當運行隊列成員小於sched_nr_latency時,該時間為sysctl_sched_latency;否則等於sysctl_sched_min_granularity*運行隊列的成員個數(這個函數也是計算所謂的延遲調度周期,即核心保證在這麼長的時間內它的運行隊列的成員都會被執行至少一次,sysctl_sched_latency、sysctl_sched_min_granularity可以在/proc/sys/kernel/上進行設定)

sched_slice(cfs_rq,se):對於非組調度它計算的就是當前se在運行隊列裡所能分配的物理執行時間,首先計算出該隊列的調度周期(__sched_period),然後按照該se在隊列中所佔的比重計算出它自己的理想執行時間__sched_period*(se->load/se->cfs_rq->load);對於組調度,它則算出該se對應的group
root理想的物理執行時間。為什麼要算到root?——假設我們有兩個group並且它們的shares差一倍,但是它們下面的task load是一樣的1024,那麼它們的執行時間顯然跟它們所屬的group有關。即它的se的上級group se是這樣計算的:parent_slice=child_slice*(parent_load/parent_cfs_rq->load)。註:如果se不在運行列隊(從另一個cpu遷移過來),那麼計算隊列的load時還應該加上該啟動並執行se的load。

__update_curr(cfs_rq,curr, delta_exec):更新cfs_rq當前的運行se的累計物理執行時間sum_exec_runtime,vruntime(這裡用到calc_delta_fair計算實質物理時間對應的虛擬時間)以及cfs_rq->min_vruntime(update_min_vruntime)

sched_vslice(cfs_rq,se):計算該se理想情況下啟動並執行物理時間相對應的虛擬時間

update_curr(cfs_rq):該函數調用__update_curr更新vruntime,及更新一些統計資訊

wakeup_gran:用於計算被搶佔進程的最小執行時間(物理時間sysctl_sched_wakeup_granularity 1ms)的虛擬時間(calc_delta_fair)

wakeup_preempt_entity:該函數用於判斷一個新的se是否應該搶佔當前的curr,如果當前的虛擬執行時間小於等於(優先不搶佔)新的vruntime,顯然當前執行的時間更少,所以不應該被搶佔(返回-1);否則,假設新的se可以搶佔curr,那麼它最少需要運行wakeup_gran虛擬時間(sysctl_sched_wakeup_granularity保證最少已耗用時間防止頻繁切換),如果這個時間比當前多啟動並執行時間小的話,那麼說明被搶佔後新的se運行後的vruntime還會比當前的vruntime還小,這樣新的se可以搶佔當前curr(返回1);0好像也表示不應該搶佔

place_entity(cfs_rq,se, initial):確定se被wakeup(initial=0)或者剛被fork的時新(initial=1)的合適vruntime,對於wakeup則進行適當的補償(補償因子sysctl_sched_latency,如果睡眠時間太短se->vruntime依然很大(比vruntime大),那麼進程虛擬時間不變,而得不到獎勵);對於剛被fork的進程,則把它的vruntime賦值為cfs_rq->min_vruntime,另外因為進程剛被建立,它的運行應當被放在運行周期之後,所以加上運行周期對應虛擬時間(sched_vslice)

set_next_entity(cfs_rq,se):將se置為當前cfs_rq上正在啟動並執行進程,如果它是在運行隊列裡,則先出隊,否則直接cfs_rq->curr = se

set_last_buddy(se):設定優先調度的last buddy

set_next_buddy(se):設定優先調度的next buddy,它的優先順序比last buddy高

set_skip_buddy(se):設定不應該被調度的buddy,也就是它的優先順序最最低

update_cfs_shares(cfs_rq):更新該cfs_rq自身所屬的se weight.load值(se = tg->se[cpu_of(rq_of(cfs_rq))]),新的shares值計算公式為:(tg->shares*cfs_rq->load.weight)/(tg->load_weight-cfs_rq->load_contribution+cfs_rq->load.weight),注意最後在更新時reweight_entity(cfs_rq_of(se),
se, shares),這時傳給reweight_entity就是這個se所屬的cfs_rq(上級的my_q),而不是它自己本身了,因為如果這個se已經在它的上級cfs_rq裡,那麼應該先減去它舊的shares值,然後再更新該se的shares值,然後再用新的se shares值加到這個上級cfs_rq裡

account_entity_enqueue(cfs_rq,se):入隊列時相應更新,包括cfs_rq的load,nr_running;另外如果該se是root的話,則增加cfs_rq對應的rq的load,如果該se是task的話,則增加cfs_rq的task weight

account_entity_dequeue(cfs_rq,se):做account_entity_enqueue的相反操作

reweight_entity(cfs_rq,se, weight):重新計算se的load及相應的cfs_rq的load(如該se在cfs_rq裡),即先把該se account_entity_dequeue,再更新se的load update_load_set,最後再重新計算cfs_rq的load account_entity_enqueue

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.