操作系統原理第五章:CPU調度

1 CPU調度基本概念

1.1 基本概念

CPU調度就是就從就緒隊列中選擇一個進程來分配CPU的過程,進行CPU調度的原因是爲了實現多道,使得CPU有更高的利用率,之所以進程能夠進行CPU調度是因爲進程的特點,進程執行過程中分爲兩個脈衝一個是CPU脈衝 (CPU Burst),一個是 I/O 脈衝 (I/O Burst),即在 CPU 上執行和等待 I/O ,進程的執行以 CPU 脈衝開始,其後跟着 I/O 脈衝,進程的執行就是在這兩個狀態之間進行轉換,如下圖所示:
在這裏插入圖片描述
觀察CPU脈衝的統計後發現,CPU 脈衝的分佈,在系統中存在許多短 CPU 脈衝,只有少量的長 CPU 脈衝,比如 I/O 型作業具有許多短 CPU 脈衝,而 CPU 型作業則會有幾個長 CPU 脈衝,這個分佈規律對CPU 調度算法的選擇是非常重要的,下圖是對CPU脈衝的統計直方圖,橫軸是時間,豎軸是頻率,可以發現頻率在0~8ms的高頻脈衝是比較多的:
在這裏插入圖片描述

1.2 CPU調度的時機

當CPU空閒時,OS就選擇內存中的某個就緒進程,並給其分配CPU,以下是進程狀態轉換圖,當某個進程從running狀態離開時,就代表當前CPU就空閒了,圖中紅色和藍色的箭頭都代表着會發生CPU調度:
在這裏插入圖片描述
CPU的調度可能發生在以下情況:

  • 從運行轉到等待 (Switches from running to waiting state):非搶佔式調度;
  • 從運行轉到就緒 (Switches from running to ready state):搶佔式調度,時間片到;
  • 從等待轉到就緒 (Switches from waiting to ready):搶佔式調度,若某個在就緒隊列的進程優先級較高,則會搶佔CPU,所以是搶佔式調度;
  • 終止運行 (Terminates):非搶佔式調度。

1.3 CPU調度方案

CPU調度方案分爲以下兩種:

  • 非搶佔方式 (nonpreemptive):把處理機分配給某進程後,便讓其一直執行,直到該進程完成或發生某事件而被阻塞時,才把處理機分配給其它進程,不允許其他進程搶佔已經分配出去的處理機,其優點是實現簡單、系統開銷小,適用於大多數批處理系統環境,缺點是難以滿足緊急任務的要求,不適用於實時、分時系統要求
  • 搶佔方式(Preemptive mode):允許調度程序根據某個原則,去停止某個正在執行的進程,將處理機重新分配給另一個進程

對於搶佔方式,搶佔有如下的原則:

  • 時間片原則:各進程按時間片運行,當一個時間片用完後,便停止該進程的執行而重新進行調度。這個原則適用於分時系統;
  • 優先權原則:通常對一些重要的和緊急的進程賦予較高的優先權。當這種進程進入就緒隊列時,如果其優先權比正在執行的進程優先權高,便停止正在執行的進程,將處理機分配給優先權高的進程,使之執行;
  • 短作業優先原則:當新到達的作業比正在執行的作業明顯短時,將暫停當前長作業的執行,將處理機分配給新到的短作業,使之執行。

2 CPU調度算法

設計CPU調度算法的性能指標有如下幾點:

  • CPU利用率:使CPU儘可能的忙碌;
  • 吞吐量:單位時間內運行完的進程數;
  • 週轉時間:進程從提交到運行結束的全部時間 ;
  • 等待時間:進程在就緒隊列中等待調度的時間片總和;
  • 響應時間 :從進程提出請求到首次被響應的時間段,在分時系統環境下不是輸出完結果的時間

注:調度算法影響的是等待時間 , 而不能影響進程真正使用CPU 的時間和 I/O 時間

2.1 先來先服務(FCFS)

先來先服務 (First-Come-First-Served),其算法思想和字面意思一樣,就是先到來的進程,先被調度,這是最簡單的調度算法,FCFS屬於非搶佔方式,一旦一個進程佔有處理機,它就一直運行下去,直到該進程完成或者因等待某事件而不能繼續運行時才釋放處理機。FCFS 算法易於實現,表面上很公平 ,實際上有利於長作業,不利於短作業;有利於 CPU 繁忙型,不利於 I/O 繁忙型,可以看下面的例子。

假設有 P1P_1P2P_2P3P_3 三個進程,所需的CPU脈衝時間分別爲24,3,3,如下表:

進程 CPU脈衝時間
P1P_1 24
P2P_2 3
P3P_3 3

現設三個進程到來的順序是 P1P_1P2P_2P3P_3,那麼該調度的Gantt圖如下:
在這裏插入圖片描述
各個進程的等待時間如下表:

進程 等待時間
P1P_1 0
P2P_2 24
P3P_3 27

平均等待時間爲 t=0+24+273=17t=\frac{0 + 24 + 27}{3}=17

現假設三個進程到來的順序是 P2P_2P3P_3P1P_1,那麼該調度的Gantt圖如下:
在這裏插入圖片描述
各進程的等待時間如下表:

進程 等待時間
P1P_1 6
P2P_2 0
P3P_3 3

平均等待時間爲 t=6+0+33=3t=\frac{6 + 0 + 3}{3}=3

由上面兩個例子可以看出,在先來先服務算法中,進程到來的次序對平均等待時間的影響是很大的,這裏有個專業名詞叫做 護航效應 (Convoy effect)

護航效應 (Convoy effect)

  • 假設有一個CPU進程和許多I/O型進程
  • 當CPU進程佔用CPU運行時, I/O型進程可能完成了其I/O操作,回到就緒隊列等待CPU, I/O設備空閒
  • CPU進程釋放CPU後, I/O型進程陸續使用CPU,並很快轉爲I/O操作,CPU空閒

在這種情況下,CPU和 I/O 設備並沒有得到有效的利用。

2.2 短作業優先(SJF)

短作業優先 (Shortest-Job-First),其算法思想是關聯到每個進程下次運行的 CPU 脈衝長度,調度最短的進程,由於進程是不斷調入到就緒隊列中的,其整個就緒隊列中的最短作業,也是動態變化的,此時就要面臨一個問題了,若現在到來了一個所需CPU脈衝時間最短的一個進程,那麼是讓當前執行的進程讓位,還是等當前進程執行完再執行,所以有如下兩種策略:

  • 非搶佔式調度:一旦進程擁有 CPU , 它的使用權限只能在該 CPU 脈衝結束後讓出;
  • 搶佔式調度 :發生在有比當前進程剩餘時間片更短的進程到達時,也稱爲最短剩餘時間優先調度

短作業優先SJF算法是最優的,因爲對一組指定的進程而言,它給出了最短的平均等待時間,如下面的例子:

現有四個進程 P1P_1P2P_2P3P_3P4P_4,他們的到達時間和所需CPU脈衝時間如下表:

進程 到達時間 CPU脈衝時間
P1P_1 0 7
P2P_2 2 4
P3P_3 4 1
P4P_4 5 4

若採用搶佔式的調度,其調度Gantt圖如下:
在這裏插入圖片描述
平均等待時間爲 t=9+1+0+24=3t=\frac{9 + 1 + 0 + 2}{4}=3

若採用非搶佔式的調度,其調度Gantt圖如下:
在這裏插入圖片描述
平均等待時間爲 t=0+6+3+74=4t=\frac{0 + 6 + 3 + 7}{4}=4


雖說短作業優先算法是最優的算法,但是實際上在實現起來確實很難的,因爲要不斷的統計各個進程所需的CPU脈衝時間,這顯然實現難度高,就算能實現,其開銷也會非常大,所以實際應用中是估計進程所需時間,可以通過先前的CPU脈衝長度及計算指數均值進行估計。

綜上所述,採用SJF有利於系統減少平均週轉時間,提高系統吞吐量,一般情況下SJF調度算法比FCFS調度算法的效率要高一些, 但實現相對要困難些。如果作業的到來順序及運行時間不合適,會出現飢餓現象,例如,系統中有一個運行時間很長的作業JN,和幾個運行時間小的作業,然後,不斷地有運行時間小於JN的作業的到來,這樣,作業JN就因得不到調度而餓死。另外,作業運行的估計時間也有問題。

2.3 優先級

上面所講的短作業優先算法實際上是優先級算法的一個特例,短作業優先算法將作業所需時間定爲衡量優先級的量,表示優先級的量一般爲一個整數,這裏假定越小的數優先級越高,下面 P1P_1P2P_2P3P_3P4P_4P5P_5 五個進程的調度狀況如下:

進程 CPU脈衝時間 優先級
P1P_1 10 3
P2P_2 1 1
P3P_3 2 4
P4P_4 1 5
P5P_5 5 2

根據優先級,其調度順序爲 P2P_2P5P_5P1P_1P3P_3P4P_4,平均等待時間爲 8.2 。

那麼進程的優先級如何確定呢?通常在進程創建時確定,且在整個生命期中保持不變,這種叫靜態優先級,靜態優先級就會出現飢餓問題,即某個進程若優先級非常低,它幾乎永遠得不到CPU調度。

一個很有意思的例子:當MIT的IBM7094機器於1973年關掉時,人們發現一個於1967年提交的一個低優先權的進程還沒有得到運行。

解決方法是老化,根據進程等待時間的延長提高其優先數,也就是動態優先級,優先級會根據等待時間不斷調整。考慮改變優先級的因素通常有進程的等待時間,已使用CPU的時間,資源使用情況等。

2.4 RR時間片輪轉

RR (Round Robin),這個算法主要用在分時系統裏,這個算法的思想是每個進程將得到小單位的 CPU 時間 (時間片),通常爲 10-100 毫秒 。時間片用完後,該進程將被搶佔並插入就緒隊列末尾。

例如有四個進程 P1P_1P2P_2P3P_3P4P_4 如下表,設時間片大小爲 20:

進程 CPU脈衝時間
P1P_1 53
P2P_2 17
P3P_3 68
P4P_4 24

其調度Gantt圖如下:
在這裏插入圖片描述
一般來說,RR的平均週轉時間比SJF長,但響應時間要短一些。

對於時間片輪轉算法,確定時間片大小是非常重要的,若時間片過大,則每個進程都能在單個時間片能完成,則時間片輪轉等價於先來先服務算法,若時間片過小,則各個進程要頻繁的切換,造成大量的資源開銷。

2.5 多級隊列和多級反饋隊列

多級隊列的意思是把進程根據其某種屬性進行分類,每一類的進程都會組成一個就緒隊列,也就是說在操作系統中會有多個就緒隊列,每個進程固定的處在自己所屬的隊列中,對於不同的隊列,也可以有自己專屬的調度算法,那麼此時就要進行隊列的調度,可以給每個隊列設置不同的優先級,若是固定優先級,則會產生飢餓問題。那麼另一種解決方案就是基於時間片的算法,給定 時間片調度,即個隊列得到一定的 CPU 時間,進程在給定時間內執行,如下圖:
在這裏插入圖片描述
若某個進程在一個優先級較低的隊列中,那麼它就會一直處於飢餓狀態,解決方案是多級反饋隊列調度,存在多個就緒隊列,具有不同的優先級,各自按時間片輪轉法調度,它與多級隊列的不同是它允許進程在隊列之間移動,當一個進程執行完一個完整的時間片後被搶佔處理器,被搶佔的進程優先級降低一級而進入下級就緒隊列,如此繼續,直至降到進程的基本優先級。而一個進程從阻塞態變爲就緒態時要提高優先級,最後會將I/O型和交互式進程留在較高優先級隊列,如下圖:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章