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

2022-09-04 11:15:09 字數 3256 閱讀 1486

排程程式負責決定將哪個程序投入執行,何時執行以及執行多長時間,程序排程程式可看做在可執行態程序之間分配有限的處理器時間資源的核心子系統。

多工作業系統就是能同時併發地互動執行多個程序的作業系統。

多工系統可以劃分為兩類:

像所有unix的變體和許多其他現代作業系統一樣,linux提供了搶占式的多工模式。

程序的時間片:程序在被搶占之前能夠執行的時間是預先設定好的。

排程策略通常要在兩個矛盾的目標中間尋找平衡:程序響應迅速(響應時間短)和最大系統利用率(高吞吐量),為了滿足上述需求,排程程式通常採用一套非常複雜的演算法來決定最值得執行的程序投入執行,但是它往往並不保證低優先順序程序會被公平對待,unⅸ系統的排程程式更傾向於i/o消耗型程式,以提供更好的程式響應速度,linux為了保證互動式應用和桌面系統的效能,所以對程序的響應做了優化(縮短響應想間)更傾向於優先排程i/o消耗型程序,雖然如此,但在下面你會看到,排程程式也並未忽略處理器消耗型的程序。

時間片e是乙個數值,它表明程序在被搶占前所能持續執行的時間。排程策略必須規定乙個預設的時間片,但這並不是件簡單的事,時間片過長會導致系統對互動的響應表現欠佳,讓人覺得系統無法併發執行應用程式:時間片太短會明顯增大程序切換帶來的處理器耗因為肯定會有相當一部分系統時間用在程序切換上,而這些程序能夠用來執行的時間片卻很短,此外,i/o消耗型和處理器消耗型的程序之間的矛盾在這裡也再次顯露出來:i/o消耗型不需要長的時間片,而處理器消耗型的程序則希望越長越好(比如這樣可以讓它們的快取記憶體命中率更高)

linux排程器是以模組方式提供的,這樣做的目的是允許不同型別的程序可以有針對性地選擇排程演算法。這種模組化結構被稱為排程器類。

它允許多種不同的可動態新增的排程演算法並存,排程屬於自己範疇的程序。

每個排程器都有乙個優先順序,基礎的排程器**定義在sched_fair.c檔案中,它會按照優先順序順序遍歷排程類,擁有乙個可執行程序的最高優先順序的排程器類勝出,去選擇下面要執行的那乙個程式。完全公平排程(cs)是乙個針對普通程序的排程類,在linux中稱為sched_normal。

問題中的絕大多數都可以通過對傳統unix排程器進行改造解決,雖然這種改造修改不小,但也並非是結構性調整,比如,將nice值呈幾何增加而非算數增加的方式解決第二個問題:採用乙個新的度量機制將從nice值到時間片的對映與定時器節拍分離開來以此解決第三個問題。但是這些解決方案都迴避了實質問題——即分配絕對的時間片引發的固定的切換頻率,給公平性造成了很大變數,cfs採用的方法是對時間片分配方式進行根本性的重新設計(就程序排程器而言)完全摒棄時間片而是分配給程序乙個處理器使用比重,通過這種方式,cfs的確保了程序排程中能有恆定的公平性,而將切換頻率置於不斷變動中。

cfs的出發點基於乙個簡單的理念:程序排程的效果應如同系統具備―個備乙個理想中的完美多工同時,我們可以排程給它們無限小的時間週期,所以在任何可測量週期內,我們給予乙個程序中每個程序同樣多的執行時間。舉例來說,假如我們有兩個執行程序,在標準unⅸ排程模型中,我們先執行其中乙個5ms,然後再執行另乙個,5ms。但它們任何乙個執行時都將占有100%的處理器。而在理想情況下,完美的多工處理器模型應該是這樣的:我們能在5ms內同時執行兩個程序,它們各自使用處理器一半的能力。

所有的排程器都必須對程序執行時間做記賬。多數unix系統,分配乙個時間片給每乙個程序。那麼當每次系統時鐘節拍發生時,時間片都會被減少乙個節拍週期。

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

休眠(被阻塞)的程序處於乙個特殊的不可執行狀態,這點非常重要,如果沒有這種特殊狀態的話,排程程式就可能選出乙個本不願意被執行的程序,更糟糕的是,休眠就必須以輪詢的方式實現了,程序休眠有多種原因,但肯定都是為了等待一些事件,事件可能是一段時間從檔案讀更多資料,或者是某個硬體事件,乙個程序還有可能在嘗試獲取乙個已被占用的核心訊號量時被迫進入休眠,休眠的乙個常見原因就是檔案i/o——如程序對個檔案執行了read()操作,而這需要從磁碟裡讀取,還有,程序在獲取鍵盤輸入的時候也需要等待,無論哪種情況,核心的操作都相同:程序把自己標記成休跳態,從可執照課樹黑樹中移出,放入等待佇列,然後呼叫schedule()選擇和執行―個其他程序,喚醒的過程剛好相反:程序被設定為可執行狀態,然後再從等待佇列中移到可晰紅黑樹中。

在核心返回使用者空間的時候,它知道自己是安全的,因為既然它可以繼續去執行當前程序,那麼它當然可以再去選擇乙個新的程序去執行。所以,核心無論是在中斷處理程式還是在系統呼叫後返回,都會檢查need_resched標誌,如果它被設定了,那麼,核心會選擇乙個其他(更合適的程序投入執行。從中斷處理程式或系統呼叫返回的返回路徑都是跟體系結構相關的,在entry.s(此檔案不僅包含核心入口部分的程式,核心退出部分的相關**也在其中)檔案中通過組合語言來實現。簡而言之,使用者搶占在以下情況時產生:

與其他大部分的unⅸ變體和其他大部分的作業系統不同,linux完整地支援核心搶占,在不支援核心搶占的核心中,核心**可以一直執行,到它完成為止,也就是說,排程程式沒有辦法在乙個核心級的任務正在執行的時候重新排程——核心中的各任務是以協作方式排程的不具備搶占性。核心**一直要執行到完成(返回使用者空間)或明顯的阻塞為止,在2.6版的核心中,核心引入了搶占能力;現在,只要重新排程是安全的,核心就可以在任何時間搶占正在執行的任務。

linux的實時排程演算法提供了―種軟實時工作方式,軟實時的含義是,核心排程程序,盡力使程序在它的限定時間到來前執行,但核心不保證總能滿足這些程序的要求。相反,硬實時系統保證在一定條件下,可以滿足任何排程的要求。linux對於實時任務的排程不做任何保證。雖然不能保證硬實時工作方式,但linux的實時排程演算法的效能還是很不錯的。2.6版的核心可以滿足嚴格的時間要求。

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

linux通過sched_yield()系統呼叫,提供了一種讓程序顯式地將處理器時間讓給其他等待執行程序的機制,它是通過將程序從活動佇列中(因為程序正在執行,所以它肯定位於此佇列當中)移到過期佇列中實現的,由此產生的效果不僅搶占了該程序並將其放入優先順序佇列的最後面,還將其放入過期佇列中—這樣能確保在一段時間內它都不會再被執行了,由於實時程序不會過期,所以屬於例外,它們只被移動到其優先順序佇列的最後面(不會放到過期佇列中)在linux以的早期版本中,程序只會被放置到優先順序佇列的末尾,放棄的時間往往不會太長,現在,應用程式甚至核心**在呼叫sched_yield()前,應該仔細考慮是否真的希望放棄處理器時間。核心**為了方便,可以直接呼叫sched_yield(),先要確定給定程序確實處於可執行狀態,然後再呼叫sched_yield(),使用者空間的應用程式直接使用sched_yield()系統呼叫就可以 。

Linux核心設計與實現讀書筆記 1

我現在要做的科研專案涉及到核心程式設計的知識,所以在學校的圖書館借了一本 linux核心設計與實現 英文名 linux kernel development 打算通過這本書來了解一下linux核心各部分的原理。我選擇這本書的原因很簡單 薄。全書只有二百多頁,但內容還是很全面的。翻譯質量還可以,譯者還...

linux核心設計與實現讀書筆記 記憶體管理

一 頁 記憶體管理的基本單位 頁。核心中用struct page表示物理頁,位於,屬性包括flag頁狀態 count頁的引用計數,virtual頁虛擬位址。目的在於描述物理記憶體本身而非其中的資料。1 獲得頁 核心 alloc pages gft t gft mask,order 連續分配2n個連續...

《Linux核心設計與實現》讀書筆記 程序排程

程序排程程式負責決定將哪個程序投入執行,何時執行以及執行多長時間。在執行態程序之間分配有限的處理器時間資源。多工系統分為搶占式和非搶占式。linux使用搶占式。大部分現代系統都是搶占式 io消耗型 處理器消耗型程序 把大多時間用於執行 的程序。程序優先順序 nice值 20 19,值越大優先順序越低...