【Linux】探索進程優(yōu)先級的奧秘,解鎖進程的調度與切換

  1. 進程優(yōu)先級:

    1.2. 進程優(yōu)先級的定義是什么?

    進程優(yōu)先級指的是CPU資源分配的先后順序,即進程的優(yōu)先權(priority)。

    1.3. 為何存在進程優(yōu)先級的概念?

    根本原因在于資源的稀缺性。

    linux環(huán)境中,默認優(yōu)先級為80,且Linux的優(yōu)先級是可調的,范圍在【60,99】之間,共有40個級別。

    Linux優(yōu)先級的本質是數字,數字越小,優(yōu)先級越高!

    Linux系統(tǒng)允許用戶調整優(yōu)先級,但不能直接修改pri,而是通過修改nice值(不是優(yōu)先級,而是進程優(yōu)先級的修正數據)來實現。

    pri = pri(old) + nice

    1.4. 為什么Linux調整優(yōu)先級需要受限制?

    如果不加限制,用戶可以將自己進程的優(yōu)先級設得極高,而將他人的優(yōu)先級設得極低,高優(yōu)先級的進程會優(yōu)先獲得資源,導致后續(xù)產生的進程難以享受到CPU資源,從而引發(fā)進程饑餓問題。

    1.5. PRI與NICE的區(qū)別需要特別強調的是什么?

    進程的nice值不是進程的優(yōu)先級,它們是不同的概念,但nice值會影響進程優(yōu)先級的變化。可以將nice值理解為進程優(yōu)先級的修正數據。

    在Linux下,調整進程優(yōu)先級就是調整進程的nice值,nice值的范圍是-20至19,共有40個級別。

    使用top命令更改已存在進程的nice值:進入top后按“r”->輸入進程PID->輸入nice值。

  2. Linux的調度與切換:

    2.1. 概念準備:

    1. 進程在運行時,是否必須在CPU上運行完整個代碼?

      不是!現代操作系統(tǒng)是基于時間片進行輪轉執(zhí)行的(時間片:給每個進程規(guī)定的最大運行時間)。

    2. 進程的競爭性、獨立性、并行性和并發(fā)性:

      競爭性:系統(tǒng)中進程數量眾多,而CPU資源有限,進程之間具有競爭屬性。為了高效完成任務和合理競爭資源,便有了優(yōu)先級。

      獨立性:多進程運行時,需要獨享各種資源,多進程運行期間互不干擾。

      并行:多個進程在多個CPU下分別、同時進行運行,稱之為并行。

      并發(fā):多個進程在一個CPU下通過進程切換,在一段時間內讓多個進程都得以推進,稱之為并發(fā)。

    2.2. 如何完成進程的調度和切換?

    當一個進程的時間片到期后,如何保存進程以便下次調用?

    CPU內部有許多寄存器,進程在運行過程中會產生大量臨時數據,存放在CPU的寄存器中。這些CPU內部的臨時數據稱為進程的硬件上下文。通過硬件上下文的保存,進程可以被再次調度時恢復運行。

    因此,當進程再次被調度時,將之前保存的硬件上下文恢復,使進程繼續(xù)從上次運行的位置進行。

    上下文并不是寄存器,而是寄存器的內容。CPU的寄存器只有一套,但寄存器內部保存的數據可以有多套。

    所以,寄存器 ≠ 寄存器的內容。

    雖然寄存器數據放在共享的CPU設備中,但所有數據實際上是進程私有的。

    小結:所有的保存都是為了最終的恢復,所有的恢復都是為了繼續(xù)上次的運行位置繼續(xù)進行。


    2.4 Linux實現進程調度的算法需要考慮哪些因素?

    Linux實現進程調度的算法需要考慮優(yōu)先級、進程饑餓問題和效率問題。

    解決優(yōu)先級問題:

    普通優(yōu)先級:100~139(對應nice值的取值范圍)

    實時優(yōu)先級:0~99(不關心)

    時間片未結束的所有進程都按優(yōu)先級放在隊列中。nr_active表示總共有多少個運行狀態(tài)的進程,queue[140]表示一個元素就是一個進程隊列,相同優(yōu)先級的進程按照FIFO規(guī)則進行排隊調度,數組下標即優(yōu)先級。

    從0下標開始遍歷queue[140],找到第一個非空隊列,該隊列必定是優(yōu)先級最高的隊列。選中隊列的第一個進程開始運行,調度完成,優(yōu)先級問題解決。

    解決進程饑餓問題:

    采用引入活動隊列和過期隊列來解決。

    過期隊列和活動隊列結構相同,過期隊列上放置的是時間片耗盡的進程。當活動隊列上的進程都被處理完畢后,對過期隊列的進程進行時間片重新計算。

    我們先將活動隊列中的進程都運行完畢,注意活動隊列上的進程運行完畢后會減少,不會增加,而過期隊列里的進程只會越來越多。此時需要將活動隊列的內容與過期隊列的內容進行交換。

    交換方式:有兩個指針分別指向活動隊列和過期隊列,active指針永遠指向活動隊列,expired指針永遠指向過期隊列。活動隊列上的進程會越來越少,過期隊列上的進程會越來越多,因為進程時間片到期時一直存在。只要在合適的時候交換active指針和expired指針的內容,就相當于獲得了一批新的活動進程。注意交換時只是交換指針的內容。

    解決效率問題:

    遍歷queue[140]的時間復雜度是常數,但仍然不夠高效。

    于是采用位圖方法解決:

    bitmap[5]:一共140個優(yōu)先級,一共140個進程隊列。為了提高查找非空隊列的效率,可以用5*32個比特位表示隊列是否為空。我們每次可以先遍歷一個整數,如果這個整數是0,就可以直接跳過,到下一個整數,直到發(fā)現不等于0,再遍歷內部。

    位圖將對數組的遍歷轉化為對比特位的遍歷,效率會高很多。

    【Linux】探索進程優(yōu)先級的奧秘,解鎖進程的調度與切換

? 版權聲明
THE END
喜歡就支持一下吧
點贊10 分享