現代作業系統(linux、windows)基本都能處理多項任務(多工系統),因而,此多工的管理和排程是核心的基本功能,第二章就圍繞此主體展開。相關主題如下:
linux支援實時程序和非實時程序(普通程序)。一般的程序都是普通程序,而實時程序強調希望得到系統的快速響應與處理,因而有較高的優先順序。應用程式可以通過nice系統呼叫修改程式的優先順序
。
#include int nice(int inc);
程序的生命週期大體可分為:執行、等待、睡眠等階段
,在核心中使用程序狀態表示:
r (task_running):可執行狀態&執行狀態(在run_queue佇列裡的狀態);
s (task_interruptible):可中斷的睡眠狀態,可處理signal;
d (task_uninterruptible):不可中斷的睡眠狀態,可處理signal,有延遲,不能有外部訊號喚醒,只能由核心親自喚醒;
t (task_stopped or task_traced):暫停狀態或跟蹤狀態,不可處理signal,因為根本沒有時間片執行**;
z (task_dead - exit_zombie):退出狀態,程序成為殭屍程序。不可被kill, 即不響應任務訊號, 無法用sigkill殺死.
以上狀態在核心中用各種巨集定義(sched.h)
,在除錯嵌入式程式時非常有用。如檢視系統mysqld守護程序的狀態
其外,文章介紹了linux的搶占式多工
處理:程序的兩種狀態選項:使用者態、核心態。核心態具有無限的權利,使用者態受到各種限制。使用者態切換到核心態的兩種方法:系統呼叫、中斷。系統呼叫是應用程式有意的,中斷是自動觸發的。
核心搶占:緊急情況下切換到另乙個程序,甚至當前是處於核心態執行系統呼叫(中斷不能被搶占)。
這裡要重點提下,現階段熱門的docker等虛擬性技術大多基於linux的命名空間(還一種技術是control group),其為應用程式提供源生態的核心虛擬化支援。
目前,核心支援6中命名空間:
uts:unix timesharing system;
ipc:程序間通訊;
mnt:檔案系統裝載;
pid:程序id管理;
user:使用者管理
net:網路命名空間。
命名空間為層級關係,父空間能檢視所有子空間的內容,反過來不行。
核心有一套完整的pid管理與分配方案,加入了pid 命名空間後,又存在全域性pid和區域性pid之分
,此部分相當複雜,建議深入閱讀分析,此處從簡。
使用者態程式可以使用fork、clone、vfork等系統呼叫產生新的程序/執行緒,然後使用exec函式族進行程序替換(elf檔案,替換原有程序的各個段)。
程序的排程啟用有兩種方式:週期性排程器
和主排程器
。其中,週期性排程器由系統時鐘中斷觸發,定期掃瞄排程佇列上是否有需要執行的程式;主排程器則採用schedule函式主動放棄當前程序的執行,使cpu選擇新的程序執行。
在排程順序上,所有可執行的程序按照時間在乙個紅黑樹中排序
,最左側的節點等待時間最長,最先被得到排程。紅黑樹是核心的一種標準資料結構,讀者可以在rbtree.c中檢視。
此外,核心採用模組化的設計分離排程器與排程類,排程器只負責選擇下乙個待執行的程序,而真正的程序管理功能由排程器類實現
。核心支援兩種排程器類(4.14原始碼中有5個排程器類):完全公平排程類、實時排程類。不同的排程類又有不同的排程策略,如下:
排程類 描述
對應排程策略
stop_sched_class
優先順序最高的執行緒,會中斷所有其他執行緒,且不會被其他任務打斷作用
1.發生在cpu_stop_cpu_callback 進行cpu之間任務migration
2.hotplug_cpu的情況下關閉任務
……dl_sched_class
採用edf最早截至時間優先演算法排程實時程序
……rt_sched_class
採用提供 roound-robin演算法或者fifo演算法排程實時程序,具體排程策略由程序的task_struct->policy指定
sched__rr:迴圈程序
sched_fifo:先進先出
fair_sched_clas
採用cfs演算法排程普通的非實時程序
sched_batch
sched_normal
idle_sched_class
……排程器類由sched_class表示,通過指標相互串聯。如:
const struct sched_class fair_sched_class =
isched = sched_getscheduler(0);
memset(&stsched, 0, sizeof(stsched));
sched_getparam(0, &stsched);
printf("after : %d, %d \n", isched, stsched.__sched_priority);
return error_success;
}程式首先通過sched_getscheduler獲取自身的排程策略;
之後,構建sched_param結構,通過sched_setscheduler修改自身的排程策略為fifo(實時程序),且優先順序為12;
最後,再次呼叫sched_getscheduler檢視自身的調查策略。
程序排程是os的基礎之基礎,本文只是通過書本講訴簡要的描述了排程的框架,可謂冰山一角。讀者若感興趣,可以閱讀核心相關原始碼。很多博主對此類主題也有深刻的解析,可以參閱,如:
linux程序排程器的設計--linux程序的管理與排程(十七)
感謝---完。
深入Linux核心架構筆記 程序管理與排程
概述 程序相關的基本概念 硬體實時程序有嚴格的時間限制,必須在可保證的時間範圍內得到處理,否則會有很嚴重的後果,請注意,這並不意味著所要求的時間範圍特別短,linux主流版本不支援硬實時處理 軟實時程序是硬實時程序的一種弱化形式,儘管仍然需要快速得到結果,但是稍微晚一點關係也不是很大,比如對cd機的...
深入Linux核心架構筆記 程序管理與排程2
程序表示 state 執行程序的狀態 task running 表示程序可以執行 task interruptiable 程序因為等待某種事件或者資源而睡眠,可以通過訊號喚醒 task uninterruptible 程序因為等待某種事件或者資源而睡眠,不能由訊號喚醒 task stopped 程序...
深入理解Linux核心 程序
1 程序的靜態特性 程序 程式執行時的乙個例項 程序描述符 task struct 程序的基本資訊 thread info 指向記憶體區描述符的指標 mm struct 程序相關的tty tty struct 當前目錄 fs struct 指向 檔案描述符的指標 files struct 所接收的訊...