linux 程序排程1

2022-09-07 17:54:13 字數 3752 閱讀 8340

程序分為實時程序和普通程序,分別對應實時排程策略和普通排程策略

在 task_struct 中,有乙個成員變數,我們叫排程策略

unsigned int policy;
它有以下幾個定義:

#define sched_normal    0

#define sched_fifo 1

#define sched_rr 2

#define sched_batch 3

#define sched_idle 5

#define sched_deadline 6

配合排程策略的,還有我們剛才說的優先順序,也在 task_struct 中

int

prio, static_prio, normal_prio;

unsigned

int rt_priority;

實時程序,優先順序的範圍是 0~99;對於普通程序,優先順序的範圍是 100~139。數值越小,優先順序越高

實時程序的排程策略: sched_fifo、sched_rr、sched_deadline

普通程序的排程策略:sched_normal、sched_batch、sched_idle

**實現:

在 task_struct 裡面,還有這樣的成員變數:

const

struct sched_class *sched_class;

排程策略的執行邏輯,就封裝在這裡面

其所屬程序的優先順序順序為: stop_sched_class -> dl_sched_class -> rt_sched_class -> fair_sched_class -> idle_sched_class

普通程序使用的排程策略是 fair_sched_class,顧名思義,對於普通程序來講,公平是最重要的

cfs 全稱 completely fair scheduling,叫完全公平排程

原理:首先,你需要記錄下程序的執行時間。cpu 會提供乙個時鐘,過一段時間就觸發乙個時鐘中斷。就像咱們的表滴答一下,這個我們叫 tick。cfs 會為每乙個程序安排乙個虛擬執行時間 vruntime。如果乙個程序在執行,隨著時間的增長,也就是乙個個 tick 的到來,程序的 vruntime 將不斷增大。沒有得到執行的程序 vruntime 不變

顯然,那些 vruntime 少的,原來受到了不公平的對待,需要給它補上,所以會優先執行這樣的程序。

1/*2

* update the current task's runtime statistics.3*/

4static

void update_curr(struct cfs_rq *cfs_rq)520

2122

/*23

* delta /= w

24*/

25static inline u64 calc_delta_fair(u64 delta, struct sched_entity *se)

26

在這裡得到當前的時間,以及這次的時間片開始的時間,兩者相減就是這次執行的時間 delta_exec ,但是得到的這個時間其實是實際執行的時間,需要做一定的轉化才作為虛擬執行時間 vruntime。

轉化方法如下:

虛擬執行時間 vruntime += 實際執行時間 delta_exec * nice_0_load/ 權重

cfs 需要乙個資料結構來對 vruntime 進行排序,找出最小的那個,更新的時候也需要能夠快速地調整排序,要知道 vruntime 可是經常在變的,變了再插入這個資料結構,就需要重新排序

能夠平衡查詢和更新速度的是樹,在這裡使用的是紅黑樹。紅黑樹的的節點是應該包括 vruntime 的,稱為排程實體

對於普通程序的排程實體定義如下,這裡面包含了 vruntime 和權重 load_weight,以及對於執行時間的統計

struct

sched_entity ;

例項:

所有可執行的程序通過不斷地插入操作最終都儲存在以時間為順序的紅黑樹中,vruntime 最小的在樹的左側,vruntime 最多的在樹的右側。 cfs 排程策略會選擇紅黑樹最左邊的葉子節點作為下乙個將獲得 cpu 的任務。

每個 cpu 都有自己的 struct rq 結構,其用於描述在此 cpu 上所執行的所有程序,其包括乙個實時程序佇列 rt_rq 和乙個 cfs 執行佇列 cfs_rq,在排程時,排程器首先會先去實時程序佇列找是否有實時程序需要執行,如果沒有才會去 cfs 執行佇列找是否有進行需要執行。

struct

rq ;

對於普通程序公平佇列 cfs_rq,定義如下:

/*

cfs-related fields in a runqueue

*/struct

cfs_rq ;

這裡面 rb_root 指向的就是紅黑樹的根節點,這個紅黑樹在 cpu 看起來就是乙個佇列,不斷的取下乙個應該執行的程序。rb_leftmost 指向的是最左面的節點

排程類的定義如下

struct

sched_class

}}

排程的時候是從優先順序最高的排程類到優先順序低的排程類,依次執行。而對於每種排程類,有自己的實現

當有一天,某個 cpu 需要找下乙個任務執行的時候,會按照優先順序依次呼叫排程類,不同的排程類操作不同的佇列。當然 rt_sched_class 先被呼叫,它會在 rt_rq 上找下乙個任務,只有找不到的時候,才輪到 fair_sched_class 被呼叫,它會在 cfs_rq 上找下乙個任務。這樣保證了實時任務的優先順序永遠大於普通任務。

sched_class 定義的與排程有關的函式

我們重點看 fair_sched_class 對於 pick_next_task 的實現 pick_next_task_fair,獲取下乙個程序。

呼叫路徑如下:pick_next_task_fair->pick_next_entity->__pick_first_entity。

struct sched_entity *__pick_first_entity(struct cfs_rq *cfs_rq){  

struct rb_node *left = rb_first_cached(&cfs_rq->tasks_timeline);

if (!left)

return

null;

return rb_entry(left, struct sched_entity, run_node);

從這個函式的實現可以看出,就是從紅黑樹裡面取最左面的節點乙個 cpu 上有乙個佇列,cfs 的佇列是一棵紅黑樹,樹的每乙個節點都是乙個 sched_entity,每個 sched_entity 都屬於乙個 task_struct,task_struct 裡面有指標指向這個程序屬於哪個排程類。

在排程的時候,依次呼叫排程類的函式,從 cpu 的佇列中取出下乙個程序

參考:《趣談linux作業系統》排程(上)

程序排程 1

最近特別有感觸,各層面的設計似乎都可以從作業系統中找出相似的設計,作業系統幾乎是設計集大成者,所以重新又開始看作業系統相關的書籍。最近可能都是一些記錄性的文章,作業系統原理因為是教學課程,所以不會另做筆記。從重讀linux核心開始,記錄學習過程。本文均摘自 linux核心與實現 因為硬體資源總是有限...

Linux程序排程之 大O 1 排程演算法

而大o 1 排程演算法其實就是一種非常好的排程演算法,它能讓程序排程的更加合理,更加快速。我將該排程演算法總結為下面這張圖 對其中一些內容做出解釋 1.首先將相同優先順序的程序放在同一佇列裡,然後有多少個優先順序,就建立多少個優先順序佇列,這些佇列可以用佇列陣列來表示。2.如果某一優先順序佇列裡沒有...

linux程序排程

排程 從就緒的程序選出最適合的乙個來執行。知識點 1 排程策略 2 排程時機 3 排程步驟 排程策略 sched normal sched other 普通的分時程序 sched fifo 先入先出的實時程序 sched rr 時間片輪轉的實時程序 sched batch 批處理程序 sched i...