目錄
回顧進程優先級與進程調度的引入
內核runqueue圖例
關于queue[140]前100個位置 | 實時進程與分時進程
遍歷需要調度的進程與bitmap的引入
active、expired指針
結語
回顧進程優先級與進程調度的引入
在我們之前的學習中,我們是有學習過進程優先級這個概念的,這里簡單回顧一下
默認優先級是80,但是還有一個nice值可以供我們修改優先級的值
這是因為:優先級 = 默認優先級 + nice值
而nice值的范圍是從-20~19,也就是說,進程優先級是有40個值的,即從60 ~ 99
但是現在進程的優先級我們知道了,而在系統之中,他是如何使用這些優先級的呢?
內核runqueue圖例
如下圖:
這個是我們內核中的runqueue,前面我們在進程狀態那篇博客中也有提到他,只要進程被鏈入runqueue之中,就代表他會被CPU調度執行,也就是就緒和運行狀態
并且,一個CPU只有一個runqueue
而今天我們將會詳細談一談runqueue里面的幾個字段,因為我們今天要講調度,那就必然和這些繞不開
首先是上圖中用藍色框框框起來的,第三個,也就是queue[140]
需要說明的是,這140個空間中,前100個是給實時進程的(后文會有所舉例),也就是0~99位置,而后面的100~139這40個位置
不對,40個位置,這和我們的nice值的范圍,也就是進程優先級的范圍不是正好吻合了嗎!
事實也的確如此,我們來看一下圖例:
我們的每一個下標,在這樣子分布的情況下,就可以和進程的優先級一一對應,而我們這時候如果有進程進來了,那么就會直接根據他的優先級進行插入到相應位置:
比如這樣,接著就能夠調度起來了
關于queue[140]前100個位置 | 實時進程與分時進程
可能很多同學對這幾個字眼比較陌生,這里舉一個例子就明白了
分時操作系統就好比我們的電腦,需要同時讓多個進程進行輪轉,同時運行
而實時操作系統則像是車子,一臺汽車里面可能有很多功能,音樂、影視等等,但是總不能說有緊急情況了,現在我要剎車,結果操作系統說:不行,我音樂還在放呢,你不能剎車,這也太扯了
以上就是關于實時操作系統和分時操作系統的講解,這里并不打算詳說,因為今天的重點是動態理解進程的調度
遍歷需要調度的進程與bitmap的引入
首先,我們并不是所有進程的優先級都是從60開始的,大部分甚至都是80
那問題來了,我們前面還有100個空間沒有使用,空著放在那里給實時進程準備著,那我們每一次要找下一個需要調度的進程的時候,都需要一個一個去找嗎?這樣的話效率太低了
所以runqueue中還有一個東西,叫做bitmap[5],也就是所謂的位圖:
至于為什么是 5 呢,因為5*32=160,而4*32=128,5 個可以剛好覆蓋,但是4個則會直接不夠
而我們有了位圖之后,效率的提升是明顯的
比如我們現在要看前32個空間有沒有進程,我們只需要這樣:
bitmap[i]==0
這樣我們一次就能知道32個位置有沒有進程,如果為0,那就下一個32,如果不為0,那再一個一個找進程
active、expired指針
active(活躍)expired(過期)
我們現在再來看回最開始那張圖片:
我們可以看到,這里面其實有兩個框,藍和紅兩個,并且,里面的內容是完全一樣的
在看到藍色框框上面的兩個變量,那是兩個指針,active 和 expired,而這兩個指針指向的就是下面的兩個框框
我們再通過畫圖來理解一下這個過程:
在最開始的時候,進程在活躍(active)指針指向的queue下面,等到調度完之后
這個進程就會被鏈入到expired所指向的queue中(下圖用藍色框框表示的就是已經調用結束的進程):
而所有的進程在被調度完之后,上面active指針所指向的queue,直接遍歷 1 次bitmap,發現全是 0,就知道全部調度完了
接下來就是:兩個指針的值直接交換(swap(*active, *expired))
這樣我們的活躍queue和過期queue就完成了交換
接下來就是繼續調度active指針指向的進程,全部執行完了之后,就再交換,過期的重新變成活躍的
如此往復
結語
這篇文章到這里就結束啦!!~( ̄▽ ̄)~*
如果覺得對你有幫助的,可以多多關注一下喔