Linux核心中的程序(一)

2021-06-16 10:02:00 字數 2296 閱讀 1163

多工系統可以分為:非搶占式和搶占式。linux提供搶占式多工模式。程序在被搶占之前能夠執行的時間叫程序的時間片,linux獨一無二的公平排程程式本身並沒有採用時間片來達到公平排程。

linux之前採用o(1)排程器,它對大伺服器的工作負載很理想,但是對響應時間敏感的程式卻有不足。在2.6.23核心版本中用完全公平排程演算法(cfs)代替了o(1)排程演算法。

程序可以被分為i/o消耗型和處理器消耗型。i/o消耗型指程序的大部分時間用來提交i/o請求或是等待i/o請求。處理器消耗型指程序把事件大多數用在執行**上。排程策略通常在兩個矛盾中尋找平衡:程序響應迅速和最大系統利用率。linux更傾向於優先排程i/o消耗型程序。

排程程式總是選擇時間片未用盡而且優先順序最高的程序執行。

linux採用兩種不同的優先順序範圍。第一種是nice值,越大的nice值意味著更低的優先順序。第二種是實時優先順序,其值可以配置,越高的實時優先順序數值意味著程序優先順序越高。任何實時程序的優先順序都高於普通程序。

cfs做法:允許每個程序執行一段時間,迴圈輪轉,選擇執行最少的程序作為下乙個執行程序,而不再採用分配給每乙個程序時間片的做法,cfs在所有可執行程序總數基礎上計算出乙個程序應該執行多久,而不是依靠nice值來計算時間片。cfs引入每個程序獲得的時間片底線(最小粒度)預設情況為1ms,絕對的nice值不再影響排程決策,任何程序所獲得的處理器時間由它自己和其他所有可執行程序nice值的相對差決定。

linux排程的實現:

時間記賬

排程器實體結構是struct sched_entity,它嵌入在程序描述符struct task_struct中。虛擬時間以ns為單位,存在vruntime變數中,它和定時器節拍不再相關,vruntime變數可以準確測定程序的執行時間,而且可以知道誰應該是下乙個被執行的程序。

程序選擇

當cfs需要選擇下乙個執行程序時,它會挑乙個具有最小vruntime的程序,這就是cfs排程演算法的核心:選擇具有最小的vruntime的任務。這裡採用紅黑樹實現的。

排程器入口

程序排程的主要入口點是schedule函式,該函式會以優先順序為序,從高到低,依次檢查每乙個排程器,並且從最高優先順序的排程器中,選擇最高優先順序的程序。

睡眠和喚醒

對於睡眠,核心的操作是:程序把自己標記為休眠狀態,從可執行紅黑樹中移出,放入等待佇列,然後呼叫schedule函式選擇和執行乙個其他程序。對於喚醒,正好相反,程序被設定為可執行狀態,然後再從等待佇列中移到可執行紅黑樹中。

休眠有兩種程序狀態:task_interruptible和task_uninterruptible。它們唯一的區別在於處在task_uninterruptible的程序會忽略訊號,處於task_interruptible狀態的程序如果接收到乙個訊號,會被提前喚醒並響應該訊號。兩種狀態的程序位於同乙個等待佇列上,等待某些事情,不能夠執行。

關於休眠還需要注意一點:存在虛假的喚醒,所以有時候需要乙個迴圈處理來保證程序被喚醒的條件真正大達成。

等待佇列的使用

static declare_wait_queue_head(button_waitq);  //定義等待佇列頭

wait_event_interruptible(button_waitq, ev_press);              //休眠

wake_up_interruptible(&button_waitq);                  //喚醒

搶占和上下文切換

上下文切換就是從乙個可執行程序切換到另乙個可執行程序。schedule函式主要完成兩個工作:其一,把虛擬記憶體從上乙個程序對映切換到新程序中。其二,從上乙個程序的處理器狀態切換到新程序的處理器狀態。

核心必須知道在什麼時候呼叫schedule函式,如何僅靠使用者程式**顯式地呼叫schedule,它們可能就會永遠的執行下去,所以核心中提供了乙個need_resched標誌來表明是否需要重新執行一次排程,該標誌對於核心來講是乙個資訊,它表示有其他程序應當被執行了,要盡快呼叫排程程式。

使用者搶占

核心即將返回使用者空間的時候,如果need_resched標誌被設定,會導致schedule函式被呼叫,此時就會發生使用者搶占。使用者搶占在如下情況時產生:其一,從系統呼叫返回使用者空間時。其二,從中斷處理程式返回使用者空間時。

核心搶占

在2.6版核心中,核心引入搶占能力,只要重新排程是安全的,即只要沒有持有鎖,核心就可以在任何時候搶占正在執行的任務。為了支援核心搶占,在每個程序的thread_info引入preempt_count計數器,當做一把鎖來使用。核心搶占在如下情況時產生:其一,中斷處理程式正在執行,且返回核心空間之前。其二,核心**再一次具有可搶占性的時候。其三,如果核心中的任務顯式地呼叫schedule函式。其四,如果核心中的任務阻塞(這樣會呼叫schedule函式)。

Linux核心中的list for each

在linux核心原始碼中,經常要對鍊錶進行操作,其中乙個很重要的巨集是list for each entry 意思大體如下 假設只有兩個結點,則第乙個member代表head,list for each entry的作用就是迴圈遍歷每乙個pos中的member子項。巨集list for each e...

Linux核心中的Namespace

linux核心中的namespace提供了乙個輕量級的基於系統呼叫層面的虛擬化解決方案。相比傳統的使用 vmware,qemu,xen,kvm,hurd的虛擬 圖1所示 基於namespace的輕量級虛擬具有易使用,易管理,無需硬體虛擬化支援,低 成本等優點。圖 1.namespace又稱conta...

linux核心中的 config

經過make menuconfig 生成 config 決定哪些驅動編譯到核心,哪些驅動編譯為模組 那為什麼呢?舉個例子分析一下 eg 在.config 中有 config dm9000 y grep config dm9000 r 1.c檔案中 arch arm mach s5pv210 mach...