3.進程調(diào)度

進程調(diào)度

調(diào)度程序復(fù)雜決定哪個進程投入運行,合適運行以及運行時長。調(diào)度程序可看做在可運行態(tài)進程之間分配有限的處理器時間資源內(nèi)核子系統(tǒng)。只有通過調(diào)度程序的合理調(diào)度,系統(tǒng)資源才能最大程度地發(fā)揮作用,多進程才會有并發(fā)執(zhí)行的效果。

1.多任務(wù)

多任務(wù)就是操作系統(tǒng)能同時并發(fā)地交互執(zhí)行多個進程。實際上是使多個任務(wù)處于阻塞睡眠狀態(tài),這些任務(wù)位于內(nèi)存,但是并不處于可運行狀態(tài),知道某一時間發(fā)生。Linux系統(tǒng)中往往有多個程序在內(nèi)存,但是僅有一個處于可運行狀態(tài)。

多任務(wù)系統(tǒng)劃分為兩類:搶占式非搶占式。Linux采用搶占式多任務(wù)模式,進程在被搶占之前能夠運行一定時間,這個時間稱為時間片(timeslice)。從全局角度來看,合理調(diào)整時間片可以優(yōu)化系統(tǒng)資源的使用效率。

2.調(diào)度策略

調(diào)度策略決定進程何時運行以及處理器使用時間,因此調(diào)度器的策略往往決定系統(tǒng)的整體印象。

I/O消耗型和處理器消耗型進程

進程分為I/O消耗型處理器消耗型,以及混合型。I/O消耗型大部分時間用于等待或提交I/O請求,因此這種類型特點就是頻繁需要處于運行態(tài),但是運行時間很短,例如用戶圖形界面;處理器消耗型,很少需要I/O,主要是占用大量CPU時間,用于計算,例如Matlab;混合型,例如字處理器,通常等待鍵盤輸入,同時大量占用CPU進行拼寫檢查和宏計算。

針對不同類型的進程需要不同的調(diào)度策略,考慮進程的主要需求是響應(yīng)迅速還是高吞吐量

進程優(yōu)先級

Linux采用兩種不同的優(yōu)先級范圍:nice值和實時優(yōu)先級nice值越小表明優(yōu)先級越高,實時優(yōu)先級正好相反(值越大優(yōu)先級越高),同時實時性進程的優(yōu)先級高于非實時性進程

時間片

前面說了時間片是進程被搶占前所能持續(xù)運行的時間,在Linux中,時間片不是一個定值,而是根據(jù)nice值分配處理器的使用比例,所以時間片跟系統(tǒng)負載相關(guān)。nice值越大的進程,時間片就越小。

對于Linux中使用的CFS調(diào)度器,其搶占時機取決于新的可運行程序消耗了多少處理器使用比。若消耗的使用比比當(dāng)前進程小,則搶占處理器立刻投入運行。否則,推遲其運行。

3.Linux調(diào)度的實現(xiàn)

Linux的CFS調(diào)度算法實現(xiàn)主要有4個組成部分:

  • 時間記賬
  • 進程旋轉(zhuǎn)
  • 調(diào)度器入口
  • 睡眠和喚醒

時間記賬

所有調(diào)度器必須對運行時間記賬,每次系統(tǒng)時鐘節(jié)拍發(fā)生時,分配給進程的時間片減少一個節(jié)拍,當(dāng)節(jié)拍為0時,則會被另一個時間片尚未減到0的進程搶占。Linux中使用一個調(diào)度器實體結(jié)構(gòu)——sched_entity來記錄,該實體嵌入在進程描述符task_struct內(nèi)。同時CFS采用虛擬實時vruntime來度量進程的運行時間,實現(xiàn)記賬功能。

進程選擇

CFS在選擇下一個運行進程時,會挑選一個vruntime最小的進程。CFS使用紅黑樹(請翻閱數(shù)據(jù)結(jié)構(gòu),或者直接看做一種高效的數(shù)據(jù)結(jié)構(gòu),查找和刪除效率很高,O(log(n))的復(fù)雜度)來存儲可運行進程隊列,因此每次從紅黑樹中選擇最左邊的節(jié)點。

調(diào)度器入口

進程調(diào)度的主要入口是函數(shù)schedule(),它是內(nèi)核其他部分用于調(diào)用進程調(diào)度器的入口:選擇哪個進程可以運行,何時將其投入運行。通常schedule()都需要和一個具體的調(diào)度類相關(guān)聯(lián),也就是說,它會找到一個最高優(yōu)先級的調(diào)度類——后者需要有自己的可運行隊列,然后詢問后者誰是下一個該運行的進程。

睡眠和喚醒

休眠(被阻塞)的進程處于特殊的不可執(zhí)行狀態(tài),往往是等待某事件或者I/O資源。內(nèi)核對其操作:進程標(biāo)記自己為休眠狀態(tài),從可執(zhí)行紅黑樹中移除,放入等待隊列,然后調(diào)用schedule()選擇和執(zhí)行其他一個進程。

喚醒過程剛好相反:進程被設(shè)置為可執(zhí)行狀態(tài),然后從等待隊列中移到可執(zhí)行紅黑樹中。

4.搶占和上下文切換

上下文切換,就是從一個可執(zhí)行進程切換到另一個可執(zhí)行進程,由context_switch()函數(shù)負責(zé)處理。每當(dāng)一個新進程準(zhǔn)備投入運行的時候,schedule()都會調(diào)用該函數(shù),其主要完成兩個工作:

  • 調(diào)用switch_mm(),負責(zé)把虛擬內(nèi)存從上一個進程映射切換到新進程中
  • 調(diào)用switch_to(),負責(zé)從上一個進程的處理器狀態(tài)切換到新進程的處理器狀態(tài)。包括保存、恢復(fù)棧信息和寄存器信息,還有其他與體系結(jié)構(gòu)相關(guān)的狀態(tài)信息,都必須以每個進程為對象進行管理和保存。

內(nèi)核還必須知道何時調(diào)用schedule(),內(nèi)核提供了一個need_resched標(biāo)志來表明是否需要重新執(zhí)行一次調(diào)度。在某個進程被搶占,優(yōu)先級高的程序進入執(zhí)行狀態(tài),返回用戶空間以及中斷返回時,內(nèi)核會檢查need_resched標(biāo)志。每個進程都有need_resched標(biāo)志,這是因為訪問進程描述符內(nèi)數(shù)值快于全局變量

用戶搶占

用戶搶占發(fā)生在:從系統(tǒng)調(diào)用返回用戶空間時從中斷處理程序返回用戶空間時

內(nèi)核搶占

Linux支持內(nèi)核搶占,在重新調(diào)度是安全的時候(沒有持有鎖,鎖是非搶占區(qū)域的標(biāo)志),內(nèi)核就可以在任何時間搶占正在執(zhí)行的任務(wù)。內(nèi)核搶占發(fā)生在:

  • 中斷處理程序正在執(zhí)行,且返回內(nèi)核空間之前
  • 內(nèi)核代碼再一次具有可搶占性的時候
  • 內(nèi)核中任務(wù)顯示調(diào)用schedule()
  • 內(nèi)核中任務(wù)阻塞

5.實時調(diào)度策略

Linux提供兩種實時調(diào)度策略:FIFO(先入先出)RR(輪詢)兩種方式。FIFO是指先到來的任務(wù)占用處理器,直到其主動放棄,再讓第二個到來的任務(wù)占用處理器。RRFIFO類似,但是任務(wù)耗盡其時間片后,必須由下一個任務(wù)占用處理器。

小結(jié)

本節(jié)內(nèi)容,其實對于本人而言可能更為簡單一些(因為研究生期間接觸了一些無線通信的調(diào)度算法),因此省略了一些細節(jié),我自己也是喜歡先了解大概流程,再回頭細讀的方式學(xué)習(xí),不然容易被細節(jié)阻礙思路。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 又來到了一個老生常談的問題,應(yīng)用層軟件開發(fā)的程序員要不要了解和深入學(xué)習(xí)操作系統(tǒng)呢? 今天就這個問題開始,來談?wù)劜?..
    tangsl閱讀 4,172評論 0 23
  • 引言 當(dāng)計算機系統(tǒng)處于就緒狀態(tài)的用戶進程數(shù)多于CPU數(shù)時,就會產(chǎn)生多個進程或線程同時競爭CPU的結(jié)果。假設(shè)現(xiàn)在只有...
    程序猿胖子閱讀 7,797評論 1 3
  • 我們在人際交往里,經(jīng)常會遇到一個尷尬就是跟朋友該如何談錢呢?談錢傷感情,談感情傷錢,我們到底要怎么樣呢?在這里驕...
    墨農(nóng)簡愛閱讀 1,958評論 0 1
  • 7月12日,小家伙四個月14天,我真的感謝上蒼讓這么個小天使降臨到我的身邊(家里目前有媽媽這個大天使,還有他...
    lsf8807閱讀 235評論 0 0
  • 劇組的戲已經(jīng)結(jié)束了,一向不愛看劇的嘉文破天荒地追完了劇。攝影師把餐館拍得真美呀,檔次真是高大上呀。店里已經(jīng)美那么...
    楊家有女閱讀 399評論 0 0