中文字幕日韩精品一区二区免费_精品一区二区三区国产精品无卡在_国精品无码专区一区二区三区_国产αv三级中文在线

如何理解Linux系統(tǒng)中的進程調度-創(chuàng)新互聯(lián)

這篇文章主要講解了“如何理解Linux系統(tǒng)中的進程調度”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“如何理解Linux系統(tǒng)中的進程調度”吧!

創(chuàng)新互聯(lián)-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設、高性價比興業(yè)網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式興業(yè)網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設找我們,業(yè)務覆蓋興業(yè)地區(qū)。費用合理售后完善,十多年實體公司更值得信賴。

操作系統(tǒng)要實現(xiàn)多進程,進程調度必不可少。
有人說,進程調度是操作系統(tǒng)中最為重要的一個部分。我覺得這種說法說得太絕對了一點,就像很多人動輒就說"某某函數(shù)比某某函數(shù)效率高XX倍"一樣,脫離了實際環(huán)境,這些結論是比較片面的。

而進程調度究竟有多重要呢? 首先,我們需要明確一點:進程調度是對TASK_RUNNING狀態(tài)的進程進行調度(參見《linux進程狀態(tài)淺析》)。如果進程不可執(zhí)行(正在睡眠或其他),那么它跟進程調度沒多大關系。
所以,如果你的系統(tǒng)負載非常低,盼星星盼月亮才出現(xiàn)一個可執(zhí)行狀態(tài)的進程。那么進程調度也就不會太重要。哪個進程可執(zhí)行,就讓它執(zhí)行去,沒有什么需要多考慮的。
反之,如果系統(tǒng)負載非常高,時時刻刻都有N多個進程處于可執(zhí)行狀態(tài),等待被調度運行。那么進程調度程序為了協(xié)調這N個進程的執(zhí)行,必定得做很多工作。協(xié)調得不好,系統(tǒng)的性能就會大打折扣。這個時候,進程調度就是非常重要的。

盡管我們平常接觸的很多計算機(如桌面系統(tǒng)、網(wǎng)絡服務器、等)負載都比較低,但是linux作為一個通用操作系統(tǒng),不能假設系統(tǒng)負載低,必須為應付高負載下的進程調度做精心的設計。
當然,這些設計對于低負載(且沒有什么實時性要求)的環(huán)境,沒多大用。極端情況下,如果CPU的負載始終保持0或1(永遠都只有一個進程或沒有進程需要在CPU上運行),那么這些設計基本上都是徒勞的。
優(yōu)先級
現(xiàn)在的操作系統(tǒng)為了協(xié)調多個進程的“同時”運行,最基本的手段就是給進程定義優(yōu)先級。定義了進程的優(yōu)先級,如果有多個進程同時處于可執(zhí)行狀態(tài),那么誰優(yōu)先級高誰就去執(zhí)行,沒有什么好糾結的了。
那么,進程的優(yōu)先級該如何確定呢?有兩種方式:由用戶程序指定、由內核的調度程序動態(tài)調整。(下面會說到)

linux內核將進程分成兩個級別:普通進程和實時進程。實時進程的優(yōu)先級都高于普通進程,除此之外,它們的調度策略也有所不同。

實時進程的調度
實時,原本的涵義是“給定的操作一定要在確定的時間內完成”。重點并不在于操作一定要處理得多快,而是時間要可控(在最壞情況下也不能突破給定的時間)。
這樣的“實時”稱為“硬實時”,多用于很精密的系統(tǒng)之中(比如什么火箭、導彈之類的)。一般來說,硬實時的系統(tǒng)是相對比較專用的。

像linux這樣的通用操作系統(tǒng)顯然沒法滿足這樣的要求,中斷處理、虛擬內存、等機制的存在給處理時間帶來了很大的不確定性。硬件的cache、磁盤尋道、總線爭用、也會帶來不確定性。
比如考慮“i++;”這么一句C代碼。絕大多數(shù)情況下,它執(zhí)行得很快。但是極端情況下還是有這樣的可能:
1、i的內存空間未分配,CPU觸發(fā)缺頁異常。而linux在缺頁異常的處理代碼中試圖分配內存時,又可能由于系統(tǒng)內存緊缺而分配失敗,導致進程進入睡眠;
2、代碼執(zhí)行過程中硬件產生中斷,linux進入中斷處理程序而擱置當前進程。而中斷處理程序的處理過程中又可能發(fā)生新的硬件中斷,中斷永遠嵌套不止……;
等等……
而像linux這樣號稱實現(xiàn)了“實時”的通用操作系統(tǒng),其實只是實現(xiàn)了“軟實時”,即盡可能地滿足進程的實時需求。

如果一個進程有實時需求(它是一個實時進程),則只要它是可執(zhí)行狀態(tài)的,內核就一直讓它執(zhí)行,以盡可能地滿足它對CPU的需要,直到它完成所需要做的事情,然后睡眠或退出(變?yōu)榉强蓤?zhí)行狀態(tài))。
而如果有多個實時進程都處于可執(zhí)行狀態(tài),則內核會先滿足優(yōu)先級高的實時進程對CPU的需要,直到它變?yōu)榉强蓤?zhí)行狀態(tài)。
于是,只要高優(yōu)先級的實時進程一直處于可執(zhí)行狀態(tài),低優(yōu)先級的實時進程就一直不能得到CPU;只要一直有實時進程處于可執(zhí)行狀態(tài),普通進程就一直不能得到CPU。

那么,如果多個相同優(yōu)先級的實時進程都處于可執(zhí)行狀態(tài)呢?這時就有兩種調度策略可供選擇:
1、SCHED_FIFO:先進先出。直到先被執(zhí)行的進程變?yōu)榉强蓤?zhí)行狀態(tài),后來的進程才被調度執(zhí)行。在這種策略下,先來的進程可以執(zhí)行sched_yield系統(tǒng)調用,自愿放棄CPU,以讓權給后來的進程;
2、SCHED_RR:輪轉調度。內核為實時進程分配時間片,在時間片用完時,讓下一個進程使用CPU;
強調一下,這兩種調度策略以及sched_yield系統(tǒng)調用都僅僅針對于相同優(yōu)先級的多個實時進程同時處于可執(zhí)行狀態(tài)的情況。

在linux下,用戶程序可以通過sched_setscheduler系統(tǒng)調用來設置進程的調度策略以及相關調度參數(shù);sched_setparam系統(tǒng)調用則只用于設置調度參數(shù)。這兩個系統(tǒng)調用要求用戶進程具有設置進程優(yōu)先級的能力(CAP_SYS_NICE,一般來說需要root權限)(參閱capability相關的文章)。
通過將進程的策略設為SCHED_FIFO或SCHED_RR,使得進程變?yōu)閷崟r進程。而進程的優(yōu)先級則是通過以上兩個系統(tǒng)調用在設置調度參數(shù)時指定的。

對于實時進程,內核不會試圖調整其優(yōu)先級。因為進程實時與否?有多實時?這些問題都是跟用戶程序的應用場景相關,只有用戶能夠回答,內核不能臆斷。

綜上所述,實時進程的調度是非常簡單的。進程的優(yōu)先級和調度策略都由用戶定死了,內核只需要總是選擇優(yōu)先級高的實時進程來調度執(zhí)行即可。稍微麻煩一點的只是在選擇具有相同優(yōu)先級的實時進程時,要考慮兩種調度策略。

普通進程的調度
實時進程調度的中心思想是,讓處于可執(zhí)行狀態(tài)的高優(yōu)先級的實時進程盡可能地占有CPU,因為它有實時需求;而普通進程則被認為是沒有實時需求的進程,于是調度程序力圖讓各個處于可執(zhí)行狀態(tài)的普通進程和平共處地分享CPU,從而讓用戶覺得這些進程是同時運行的。
與實時進程相比,普通進程的調度要復雜得多。內核需要考慮兩件麻煩事:

一、動態(tài)調整進程的優(yōu)先級
按進程的行為特征,可以將進程分為“交互式進程”和“批處理進程”:
交互式進程(如桌面程序、服務器、等)主要的任務是與外界交互。這樣的進程應該具有較高的優(yōu)先級,它們總是睡眠等待外界的輸入。而在輸入到來,內核將其喚醒時,它們又應該很快被調度執(zhí)行,以做出響應。比如一個桌面程序,如果鼠標點擊后半秒種還沒反應,用戶就會感覺系統(tǒng)“卡”了;
批處理進程(如編譯程序)主要的任務是做持續(xù)的運算,因而它們會持續(xù)處于可執(zhí)行狀態(tài)。這樣的進程一般不需要高優(yōu)先級,比如編譯程序多運行了幾秒種,用戶多半不會太在意;

如果用戶能夠明確知道進程應該有怎樣的優(yōu)先級,可以通過nice、setpriority系統(tǒng)調用來對優(yōu)先級進行設置。(如果要提高進程的優(yōu)先級,要求用戶進程具有CAP_SYS_NICE能力。)
然而應用程序未必就像桌面程序、編譯程序這樣典型。程序的行為可能五花八門,可能一會兒像交互式進程,一會兒又像批處理進程。以致于用戶難以給它設置一個合適的優(yōu)先級。
再者,即使用戶明確知道一個進程是交互式還是批處理,也多半礙于權限或因為偷懶而不去設置進程的優(yōu)先級。(你又是否為某個程序設置過優(yōu)先級呢?)
于是,最終,區(qū)分交互式進程和批處理進程的重任就落到了內核的調度程序上。

調度程序關注進程近一段時間內的表現(xiàn)(主要是檢查其睡眠時間和運行時間),根據(jù)一些經驗性的公式,判斷它現(xiàn)在是交互式的還是批處理的?程度如何?最后決定給它的優(yōu)先級做一定的調整。
進程的優(yōu)先級被動態(tài)調整后,就出現(xiàn)了兩個優(yōu)先級:
1、用戶程序設置的優(yōu)先級(如果未設置,則使用默認值),稱為靜態(tài)優(yōu)先級。這是進程優(yōu)先級的基準,在進程執(zhí)行的過程中往往是不改變的;
2、優(yōu)先級動態(tài)調整后,實際生效的優(yōu)先級。這個值是可能時時刻刻都在變化的;

二、調度的公平性
在支持多進程的系統(tǒng)中,理想情況下,各個進程應該是根據(jù)其優(yōu)先級公平地占有CPU。而不會出現(xiàn)“誰運氣好誰占得多”這樣的不可控的情況。
linux實現(xiàn)公平調度基本上是兩種思路:
1、給處于可執(zhí)行狀態(tài)的進程分配時間片(按照優(yōu)先級),用完時間片的進程被放到“過期隊列”中。等可執(zhí)行狀態(tài)的進程都過期了,再重新分配時間片;
2、動態(tài)調整進程的優(yōu)先級。隨著進程在CPU上運行,其優(yōu)先級被不斷調低,以便其他優(yōu)先級較低的進程得到運行機會;
后一種方式有更小的調度粒度,并且將“公平性”與“動態(tài)調整優(yōu)先級”兩件事情合而為一,大大簡化了內核調度程序的代碼。因此,這種方式也成為內核調度程序的新寵。

強調一下,以上兩點都是僅針對普通進程的。而對于實時進程,內核既不能自作多情地去動態(tài)調整優(yōu)先級,也沒有什么公平性可言。

普通進程具體的調度算法非常復雜,并且隨linux內核版本的演變也在不斷更替(不僅僅是簡單的調整),所以本文就不繼續(xù)深入了。

調度程序的效率
“優(yōu)先級”明確了哪個進程應該被調度執(zhí)行,而調度程序還必須要關心效率問題。調度程序跟內核中的很多過程一樣會頻繁被執(zhí)行,如果效率不濟就會浪費很多CPU時間,導致系統(tǒng)性能下降。
在linux 2.4時,可執(zhí)行狀態(tài)的進程被掛在一個鏈表中。每次調度,調度程序需要掃描整個鏈表,以找出最優(yōu)的那個進程來運行。復雜度為O(n);
在linux 2.6早期,可執(zhí)行狀態(tài)的進程被掛在N(N=140)個鏈表中,每一個鏈表代表一個優(yōu)先級,系統(tǒng)中支持多少個優(yōu)先級就有多少個鏈表。每次調度,調度程序只需要從第一個不為空的鏈表中取出位于鏈表頭的進程即可。這樣就大大提高了調度程序的效率,復雜度為O(1);
在linux 2.6近期的版本中,可執(zhí)行狀態(tài)的進程按照優(yōu)先級順序被掛在一個紅黑樹(可以想象成平衡二叉樹)中。每次調度,調度程序需要從樹中找出優(yōu)先級高的進程。復雜度為O(logN)。

那么,為什么從linux 2.6早期到近期linux 2.6版本,調度程序選擇進程時的復雜度反而增加了呢?
這是因為,與此同時,調度程序對公平性的實現(xiàn)從上面提到的第一種思路改變?yōu)榈诙N思路(通過動態(tài)調整優(yōu)先級實現(xiàn))。而O(1)的算法是基于一組數(shù)目不大的鏈表來實現(xiàn)的,按我的理解,這使得優(yōu)先級的取值范圍很?。▍^(qū)分度很低),不能滿足公平性的需求。而使用紅黑樹則對優(yōu)先級的取值沒有限制(可以用32位、64位、或更多位來表示優(yōu)先級的值),并且O(logN)的復雜度也還是很高效的。

調度觸發(fā)的時機
調度的觸發(fā)主要有如下幾種情況:
1、當前進程(正在CPU上運行的進程)狀態(tài)變?yōu)榉强蓤?zhí)行狀態(tài)。
進程執(zhí)行系統(tǒng)調用主動變?yōu)榉强蓤?zhí)行狀態(tài)。比如執(zhí)行nanosleep進入睡眠、執(zhí)行exit退出、等等;
進程請求的資源得不到滿足而被迫進入睡眠狀態(tài)。比如執(zhí)行read系統(tǒng)調用時,磁盤高速緩存里沒有所需要的數(shù)據(jù),從而睡眠等待磁盤IO;
進程響應信號而變?yōu)榉强蓤?zhí)行狀態(tài)。比如響應SIGSTOP進入暫停狀態(tài)、響應SIGKILL退出、等等;

2、搶占。進程運行時,非預期地被剝奪CPU的使用權。這又分兩種情況:進程用完了時間片、或出現(xiàn)了優(yōu)先級更高的進程。
優(yōu)先級更高的進程受正在CPU上運行的進程的影響而被喚醒。如發(fā)送信號主動喚醒,或因為釋放互斥對象(如釋放鎖)而被喚醒;
內核在響應時鐘中斷的過程中,發(fā)現(xiàn)當前進程的時間片用完;
內核在響應中斷的過程中,發(fā)現(xiàn)優(yōu)先級更高的進程所等待的外部資源的變?yōu)榭捎?,從而將其喚醒。比如CPU收到網(wǎng)卡中斷,內核處理該中斷,發(fā)現(xiàn)某個socket可讀,于是喚醒正在等待讀這個socket的進程;再比如內核在處理時鐘中斷的過程中,觸發(fā)了定時器,從而喚醒對應的正在nanosleep系統(tǒng)調用中睡眠的進程。
 
 
所有任務都采用linux分時調度策略時:
1,創(chuàng)建任務指定采用分時調度策略,并指定優(yōu)先級nice值(-20~19)。
2,將根據(jù)每個任務的nice值確定在cpu上的執(zhí)行時間(counter)。
3,如果沒有等待資源,則將該任務加入到就緒隊列中。
4,調度程序遍歷就緒隊列中的任務,通過對每個任務動態(tài)優(yōu)先級的計算權值(counter+20-nice)結果,選擇計算結果較大的一個去運行,當這個時間片用完后(counter減至0)或者主動放棄cpu時,該任務將被放在就緒隊列末尾(時間片用完)或等待隊列(因等待資源而放棄cpu)中。
5,此時調度程序重復上面計算過程,轉到第4步。
6,當調度程序發(fā)現(xiàn)所有就緒任務計算所得的權值都為不大于0時,重復第2步。
 
所有任務都采用FIFO時:
1,創(chuàng)建進程時指定采用FIFO,并設置實時優(yōu)先級rt_priority(1-99)。
2,如果沒有等待資源,則將該任務加入到就緒隊列中。
3,調度程序遍歷就緒隊列,根據(jù)實時優(yōu)先級計算調度權值(1000+rt_priority),選擇權值高的任務使用cpu,該FIFO任務將一直占有cpu直到有優(yōu)先級更高的任務就緒(即使優(yōu)先級相同也不行)或者主動放棄(等待資源)。
4,調度程序發(fā)現(xiàn)有優(yōu)先級更高的任務到達(高優(yōu)先級任務可能被中斷或定時器任務喚醒,再或被當前運行的任務喚醒,等等),則調度程序立即在當前任務堆棧中保存當前cpu寄存器的所有數(shù)據(jù),重新從高優(yōu)先級任務的堆棧中加載寄存器數(shù)據(jù)到cpu,此時高優(yōu)先級的任務開始運行。重復第3步。
5,如果當前任務因等待資源而主動放棄cpu使用權,則該任務將從就緒隊列中刪除,加入等待隊列,此時重復第3步。
 
所有任務都采用RR調度策略時:
1,創(chuàng)建任務時指定調度參數(shù)為RR,并設置任務的實時優(yōu)先級和nice值(nice值將會轉換為該任務的時間片的長度)。
2,如果沒有等待資源,則將該任務加入到就緒隊列中。
3,調度程序遍歷就緒隊列,根據(jù)實時優(yōu)先級計算調度權值(1000+rt_priority),選擇權值高的任務使用cpu。
4,如果就緒隊列中的RR任務時間片為0,則會根據(jù)nice值設置該任務的時間片,同時將該任務放入就緒隊列的末尾。重復步驟3。
5,當前任務由于等待資源而主動退出cpu,則其加入等待隊列中。重復步驟3。
 
系統(tǒng)中既有分時調度,又有時間片輪轉調度和先進先出調度:
1,RR調度和FIFO調度的進程屬于實時進程,以分時調度的進程是非實時進程。
2,當實時進程準備就緒后,如果當前cpu正在運行非實時進程,則實時進程立即搶占非實時進程。
3,RR進程和FIFO進程都采用實時優(yōu)先級做為調度的權值標準,RR是FIFO的一個延伸。FIFO時,如果兩個進程的優(yōu)先級一樣,則這兩個優(yōu)先級一樣的進程具體執(zhí)行哪一個是由其在隊列中的未知決定的,這樣導致一些不公正性(優(yōu)先級是一樣的,為什么要讓你一直運行?),如果將兩個優(yōu)先級一樣的任務的調度策略都設為RR,則保證了這兩個任務可以循環(huán)執(zhí)行,保證了公平。
 
Ingo Molnar-實時補丁
為了能并入主流內核,Ingo Molnar的實時補丁也采用了非常靈活的策略,它支持四種搶占模式:
1.No Forced Preemption (Server),這種模式等同于沒有使能搶占選項的標準內核,主要適用于科學計算等服務器環(huán)境。
2.Voluntary Kernel Preemption (Desktop),這種模式使能了自愿搶占,但仍然失效搶占內核選項,它通過增加搶占點縮減了搶占延遲,因此適用于一些需要較好的響應性的環(huán)境,如桌面環(huán)境,當然這種好的響應性是以犧牲一些吞吐率為代價的。
3.Preemptible Kernel (Low-Latency Desktop),這種模式既包含了自愿搶占,又使能了可搶占內核選項,因此有很好的響應延遲,實際上在一定程度上已經達到了軟實時性。它主要適用于桌面和一些嵌入式系統(tǒng),但是吞吐率比模式2更低。
4.Complete Preemption (Real-Time),這種模式使能了所有實時功能,因此完全能夠滿足軟實時需求,它適用于延遲要求為100微秒或稍低的實時系統(tǒng)。


感謝各位的閱讀,以上就是“如何理解Linux系統(tǒng)中的進程調度”的內容了,經過本文的學習后,相信大家對如何理解Linux系統(tǒng)中的進程調度這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是創(chuàng)新互聯(lián)網(wǎng)站建設公司,,小編將為大家推送更多相關知識點的文章,歡迎關注!

當前文章:如何理解Linux系統(tǒng)中的進程調度-創(chuàng)新互聯(lián)
網(wǎng)頁路徑:http://www.rwnh.cn/article18/psddp.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供手機網(wǎng)站建設、App設計網(wǎng)站排名、關鍵詞優(yōu)化、軟件開發(fā)外貿建站

廣告

聲明:本網(wǎng)站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

h5響應式網(wǎng)站建設
宣汉县| 崇明县| 庐江县| 黄骅市| 福泉市| 故城县| 乐陵市| 马山县| 东宁县| 民乐县| 泌阳县| 青神县| 重庆市| 平江县| 池州市| 黑山县| 鲁甸县| 庄浪县| 金乡县| 五寨县| 凌海市| 桃江县| 台前县| 海门市| 大石桥市| 淄博市| 沁阳市| 辽阳县| 基隆市| 高清| 永平县| 比如县| 顺昌县| 垫江县| 苏尼特左旗| 兴宁市| 峡江县| 时尚| 大兴区| 洛扎县| 信宜市|