1. 程式人生 > 其它 >Linux中的排程引數之公平排程中的輪轉週期與時間片

Linux中的排程引數之公平排程中的輪轉週期與時間片

基於Linux-5.4

當前的Linux中有公平排程、實時(rt)排程、deadline排程等等排程演算法;其中公平排程是目前最主要的排程演算法之一。

公平排程,顧名思義就是要保證公平性,要照顧到所有任務都能夠有機會得到CPU排程資源。Linux中有幾個引數和"公平性"息息相關。

sysctl_sched_min_granularity:公平排程中一個輪轉週期內每個任務可執行的最小時間粒度(最小時間片),這樣可避免任務執行時間太短導致優先順序低的任務受到不公平待遇以及避免任務切換太過頻繁的情況。 期預設值為750000ULL,單位nanoseconds;
sysctl_sched_latency:預設的輪轉週期。公平排程中處於就緒狀態的所有任務執行一輪所需要的時間稱為輪轉週期;當CPU上就緒任務的數量nr_running滿足nr_running < (sysctl_sched_latency/sysctl_sched_min_granularity),輪轉週期等於預設輪轉週期sysctl_sched_latency,否則輪轉週期等於(nr_running * sysctl_sched_min_granularity)。注意輪轉週期並不是均分給任務的,而是根據各個任務(準確說是排程實體se)的權重來分配的。該引數的值在linux-5.4中為預設值為6000000ULL,單位nanoseconds。


sched_nr_latency:預設輪轉週期內可確保所有任務都能夠得到排程的任務數量,即(sysctl_sched_latency/sysctl_sched_min_granularity)。這個引數不是sysctl介面。
這三個引數用在主要由sched_slice(struct cfs_rq *cfs_rq, struct sched_entity *se)函式用於計算se的時間片。虛擬碼如下:

【1】根據sysctl_sched_min_granularity、cfs_rq->nr_running以及se在排程組的權重來計算任務(排程實體se)的時間片

static u64 sched_slice(struct
cfs_rq *cfs_rq, struct sched_entity *se) { //根據sysctl_sched_min_granularity和cfs_rq->nr_running來決定se的輪轉週期slice, //要麼是sysctl_sched_latency,要麼是nr_running * sysctl_sched_min_granularity u64 slice = __sched_period(cfs_rq->nr_running + !se->on_rq); for_each_sched_entity(se) {
//計算se在整個層級樹中的slice的加權平均值 } return slice; }

【2】在一個排程時鐘中斷中如果當前cpu上的就緒任務大於1,則check_preempt_tick()函式會被呼叫來計算當前任務的時間片是否到期,以及決定是否要讓其他任務搶佔當前任務。虛擬碼如下:

static void check_preempt_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr)
{
        ideal_runtime = sched_slice(cfs_rq, curr);            //計算curr在一個輪轉週期的時間片
        delta_exec = curr->sum_exec_runtime - curr->prev_sum_exec_runtime;    //計算curr已執行的時間
        if (delta_exec > ideal_runtime) {                    //如果curr的時間片已經用完,則觸發搶佔
                resched_curr(rq_of(cfs_rq));
          ....
                return;
        }

    //如果curr執行時間不足最小粒度,則不允許搶佔
        if (delta_exec < sysctl_sched_min_granularity)
                return;
    //如果curr比下一個任務的的虛擬時間多出一個時間片則觸發搶佔
        se = __pick_first_entity(cfs_rq);
        delta = curr->vruntime - se->vruntime;

        if (delta < 0)
                return;

        if (delta > ideal_runtime)
                resched_curr(rq_of(cfs_rq));
}

總結一下:三個引數共同作用起來確保任務在就緒狀態的情況下至少執行一個屬於自己的時間片,而不會因為優先順序、權重原因被頻繁搶佔。