《Linux核心設計與實現》第四章讀書筆記

2022-08-17 17:09:24 字數 4175 閱讀 9920

1.多工系統分為兩類:非搶占式多工和搶占式

linux2.5核心版本採用o(1)排程程式的新排程程式,對大伺服器的工作負載很理想,但其缺少叫互動程序。

linux2.6核心版本初期採用rsdl,反轉樓梯最後期限排程演算法。最終採用cfs,完全排程公平演算法。

(1)程序分為i/o消耗型和處理器消耗型

(2)排程策略通常在兩個矛盾的目標中間尋找平衡:程序響應迅速(響應時間短)和最大系統利用率(高吞吐量)。

(3)unix系統更傾向於i/o消耗型程式,以提供更好的程式響應速度。

在某些系統中,優先順序高的程序使用的時間片也比較長。排程程式總是選擇時間片未用盡而且優先順序最高的程序執行。使用者和系統都可以通過設定程序的優先順序來影響系統的排程。

linux採用了兩種不同的優先順序範圍——nice值和實時優先順序值。

(1) nice值,範圍是-20到19,數值越大優先順序越低,預設值為0。linux中,nice值則代表時間片的比例。可以通過ps-el命令檢視系統中的程序列表,結果中標記ni的一列就是程序對應的nice值。

(2) 實時優先順序值,預設0到99,數值越大優先順序越高。任何實時程序的優先順序都高於普通的程序。

檢視程序列表以及對應的實時優先順序:ps-eo state,uid,pid,ppid,rtprio,time,comm.

表明程序被搶占前所能持續執行的時間。長時間片導致系統互動表現欠佳。

關於linux的cfs排程器:

(1)沒有直接分配時間片到程序,而是將處理器的使用比劃分給程序。nice值高、優先權低的程序被賦予低權重,喪失一小部分處理器使用比;nice值低、優先權高的程序被賦予高權重,搶得更多的處理器使用比。

(2)其搶占時機取決於新的可執行程式消耗了多少處理器使用比。如果消耗的使用比比當前程序小,立刻投入執行,搶占當前程序;否則推遲執行。

unix系統中,優先順序以nice值形式輸出給使用者空間。產生如下問題:

(1) 將nice值對應給時間片,就必須nice單位值對應到處理器的絕對時間,導致程序切換無法最優化進行。給定高nice值

(低優先順序)的程序往往是後台程序,且多是計算密集型;而普通優先順序的程序多是前台使用者任務,不合理。

(2) nice(通常使用相對nice值)系統呼叫實在原值上增加或者減少,不是在絕對值上操作。比如nice值減一的效果更多取決於其初始值。

(3) 如果執行nice值到時間片的對映,需要分配乙個絕對時間片(必須在核心的測試範圍內)。即時間片必須是定時器節拍的整數倍。

(4) 基於優先順序的排程器為了優化互動任務,喚醒相關程序,即使時間片已經用盡。有時會給某些特殊的睡眠/喚醒用例乙個玩弄排程器的後門,使得給定程序打破公平原則,獲得更多處理器時間,損害其他程序利益。

總結:實質問題是分配絕對的時間片引發的固定的切換頻率給公平性造成了很大變數。

cfs中,任何程序所獲得的處理器時間是由它自己和其他所有可執行程序nice值的相對差值決定。任何nice值對應的絕對時間是處理器的使用比。

所有的排程器對程序執行時間做記賬。

排程器實體結構

cfs使用排程器實體結構(名為se的成員變數,嵌入在程序描述符struct task_struct內)進行追蹤程式並記賬:

虛擬實時

注意:update_curr()是由系統定時器週期性呼叫的,無論程序出於何種狀態。

cfs排程演算法的核心:選擇具有最小vruntime的任務。

挑選下乙個任務

cfs程序選擇演算法——執行rbtree最左邊葉子節點所代表的程序。__pick_next_entity()函式實現,定義在kernel/sched_fair.c檔案中。

向樹中加入程序

從樹中刪除程序

刪除動作發生在程序堵塞或者終止時,實際工作由輔助函式__dequeue_entity()完成。

(1)程序排程的主要入口點是schedule()函式,定義在kernel/sched.c檔案中。

(2)schedule()會呼叫pick_next_task()——以優先順序為序,從高到低,依次檢查每乙個排程類,並從最高優先順序的排程類中選擇最高優先順序的程序:

注意:該函式的核心是for()迴圈;pick_next_task()實現會呼叫pick_next_entity()。

等待佇列

休眠通過等待佇列進行處理。

程序加入到乙個等待佇列:

(1)呼叫巨集define_wait()建立乙個等待佇列的項。

(2)呼叫 add_ wait_ queue()把自己加入到佇列中。

(3)呼叫 prepareto wait()方法將程序的狀態變更為task_ interruptible 或task_ uninterruptible。

(4)如果狀態被設定為task_interruptible,則訊號喚醒程序。

(5)當程序被喚醒的時候,它會再次檢查條件是否為真。

(6)當條件滿足後,程序將自己設定為 task_ running 並呼叫 finish_ wait()方法把自己移 出等待佇列。

喚醒喚醒操作由函式wake_up()進行

由context_switch()函式(定義在kernel/sched.c中)負責處理。每當乙個新的程序被選出來準備執行的時候,schedule()就會呼叫該函式,完成兩項基本工作:

呼叫switch_mm(),負責把虛擬記憶體從上乙個程序對映切換到新的程序中;

呼叫switch_to(),負責從上乙個程序的處理器狀態切換到新程序的處理器狀態。以程序為物件進行管理和儲存。

核心提供need_ resched標誌表明是否需要重新執行一次排程。該標誌對核心是乙個資訊,標識其他程序應當被執行了,要盡快排程程式。

發生時機:

(1)只要沒有鎖,核心就可以程序搶占;鎖是非搶占區域的標誌。

(2)為了支援搶占,每個程序的thread_info都加入了preempt_count計數器(初值為0,每當使用鎖的時候就加1,釋放鎖的時候數值減1),當數值為0的時候,核心就可以搶占。

(3)如果核心中程序被阻塞或顯示呼叫了schedule(),核心搶占也會顯示發生。

總結——核心搶占發生在:

linux 提供兩種實時排程策略sched_fifo和sched_rr。

這兩種演算法實現的都是靜態優先順序。linux實時排程演算法是軟實時工作方式——核心排程程序,盡量使程序在它的限定時間到來前執行,但核心不能保證能夠總能滿足。

實時優先順序範圍是0到max_rt_prio減1。預設情況下,max_rt_prio為100,nice值從-20到19直接對應的是100到139的實時優先順序範圍。

linux排程程式提供強制的處理器繫結機制。也就是說,雖然它盡力通過一種軟的(或者說自然的)親和性試圖使程序盡量在同乙個處理器上執行,但它也允許使用者強制指定「這個程序無論如何都必須在這些處理器上執行」。這種強制的親和性儲存在程序的乙個位掩碼標誌中。該掩碼標誌的每一位對應乙個系統可用的處理器,預設情況下,所有的位都被設定。

核心提供的強制處理器繫結的方法很簡單:

linux通過sched_yield()系統呼叫,提供了一種讓程序顯式地將處理器時間讓給其他等待執行程序的機制,它是通過將程序從活動佇列中(因為程序正在執行,所以它肯定位於此佇列當中)移到過期佇列中實現的。

核心**為了方便,可以直接呼叫sched_yield(),先要確定給定程序確實處於可執行狀態,然後再呼叫sched_yield(),使用者空間的應用程式直接使用sched_yield()系統呼叫就可以 。

程序排程程式是核心重要的組成部分,因為執行著的程序首先在使用計算機(至少在我們大多數人看來)。從unix漸漸完善到linux的cfs排程程式,逐步盡量滿足各方面的需求,本章也主要的介紹了程序排程所遵循的基本原理、具體實現、排程演算法以及目前linux核心所使用的介面。通過這章的學習,對以前的知識比如第五章系統呼叫有了更加深刻的理解。

Linux核心設計與實現 第四章

多工多工系統可以劃分為搶占式多工和非搶占式多工。程序在被搶占之前能夠執行的時間叫時間片。linux採用的就是搶占式多工 io消耗型程序 頻繁處於可執行狀態但是只執行很短的時間。處理器消耗型 時間大多用在執行 上,系統盡量降低其排程頻率而延長執行時間。程序排程要在兩個排程之間尋求平衡 響應時間短和最大...

《Linux核心設計與實現》讀書筆記 第四章

排程程式負責決定將哪個程序投入執行,何時執行以及執行多長時間,程序排程程式可看做在可執行態程序之間分配有限的處理器時間資源的核心子系統。多工作業系統就是能同時併發地互動執行多個程序的作業系統。多工系統可以劃分為兩類 像所有unix的變體和許多其他現代作業系統一樣,linux提供了搶占式的多工模式。程...

第四章 Linux核心模組

注 內容大多摘自 linux裝置驅動開發詳解 第2版 1.特點 2.模組程式結構 1 模組載入函式 一般需要 2 模組解除安裝函式 一般需要 3 模組許可證宣告 必須 4 模組引數 可選 5 模組匯出符號 可選 6 模組作者等資訊宣告 可選 3.模組的載入,解除安裝,檢視 4.printk函式 核心...