**可能的排程策略之前,我們先做一些簡化假設。這些假設與系統中執行的程序有關,有時候統稱為工作負載(workload)。確定工作負載是構建排程策略的關鍵部分。這裡做的工作負載假設是不切實際的,但我們會逐漸放寬這些假定,並最終開發出乙個完全可操作的排程準則。
我們對作業系統中執行的程序(有時也叫工作任務)做出如下的假設:
每乙個工作執行相同的時間
所有的工作同時到達
一旦開始,每個工作保持執行直到完成
所有的工作只使用cpu(即沒有i/o操作)
每個工作的執行時間是已知的
除了做出工作負載假設之外,還需要乙個東西能讓我們比較不同的排程策略:排程指標。任務的周轉時間\(t_\)定義為任務完成時間\(t_\)減去任務到達系統的時間\(t_\)。更正式的周轉時間定義為:
\[t_ = t_ - t_
\]注意到,周轉時間是乙個效能指標,而另乙個有趣的指標是公平。效能和公平在排程系統中往往是矛盾的。例如,排程程式可以優化效能,但代價是以阻止一些任務執行,這就降低了公平。
最基本的演算法被稱為先進先出(first in first out)排程,有時候也稱為先到先服務(first come first served)。它很簡單,易於實現,而且對於目前的假設效果不錯。
假設3個工作a、b和c在大致相同的時間到達系統。因為fifo必須將某個工作放在前面,所以我們假設當它們都同時到達時,a比b早一點點,然後b比c早到達一點點。假設每個工作執行10s,從圖上可以看出,a在10s時完成,b在20s時完成,c在30s時完成。因此,這3個任務的平均周轉時間就是\((10 + 20 + 30)/ 3 = 20s\)。
現在,我們放寬假設1,每個任務的執行時間不再相同。這種情況下fifo的表現如何?具體來說,我們再次假設3個任務(a、b和c),但這次a執行100s,而b和c執行10s。
如圖所示,a先執行100s,b或c才有機會執行。因此,系統的平均周轉時間是比較高的\((100 + 110 + 120)/ 3 = 110s\)。這個問題通常被稱為護航效應(convoy effect),一些耗時較少的潛在資源消費者被排在重量級的資源消費者之後。
事實上,我們乙個非常簡單的方法來解決護航問題。這個新的排程準則被稱為最短任務優先(shortest job first,sjf),即先執行最短的任務,然後是次短的任務,以此類推。
還是上面的例子,但這次以sjf作為排程策略。上圖展示的是執行a、b和c的結果。通過在a之前執行b和c,sjf將平均周轉時間從110s降低到\((10 + 20 + 120)/3 = 50s\)。在所有工作同時到達的情況下,可以證明sjf是乙個最有排程演算法。
現在,讓我們放寬假設2,即工作可以隨時到達,而不是同時到達。假設a在t=0時到達,且需要執行100s。而b和c在t=10時到達,且各需要執行10s。使用sjf,可以得到如下所示的排程。
從圖中可以看出,即使b和c在a之後不久到達,它們仍然被迫等到a完成,從而遭遇同樣的護航問題。這3項工作的平均周轉時間為\((100+(110−10)+(120−10))/3=103.33s\)。
為了解決這個問題,需要放寬假設3(工作必須保持執行直到完成)。也就是說,當b和c到達時,排程程式可以做其他事情:它可以搶占(preempt)工作a,並決定執行另乙個工作,或許稍後繼續工作a。根據我們的定義,sjf是一種非搶占式(non-preemptive)排程程式,因此還是存在護航問題。
通過向sjf新增搶占,我們可以得到最短完成時間優先(shortest time-to-completion first,stcf)排程程式。每當新工作進入系統時,它就會確定剩餘工作和新工作中,誰的剩餘時間最少,然後排程該工作。因此,在我們的例子中,stcf將搶占a並執行b和c以完成。只有在它們完成後,才能排程a的剩餘時間。
根據上圖,3項工作的平均周轉時間是\(((20-10)+(30-10)+120) / 3 = 50s\)。基於新的假設,可證明stcf是最優的。
\[t_ = t_ - t_
\]顯然,stcf和相關方法在響應時間上並不是很好。如果3個工作同時到達,第三個工作必須等待前兩個工作全部執行後才能執行。這種方法雖然有很好的周轉時間,但對於響應時間和互動性是相當糟糕的。
為了提高響應時間,我們將引入輪轉(round-robin,rr)排程。其基本思想很簡單:在乙個時間片內執行乙個工作,然後切換到執行佇列中的下乙個任務,而不是執行乙個任務直到結束,它反覆執行,直到所有任務完成。注意,時間片長度必須是時鐘中斷週期的倍數。因此,如果時鐘中斷是每10ms中斷一次,則時間片可以是10ms、20ms或10ms的任何其他倍數。
假設3個任務a、b和c在系統中同時到達,並且它們都希望執行5s。如下所示,sjf排程程式必須執行完當前任務才可執行下乙個任務,其平均響應時間是\((0+5+10)/3 = 5s\)。
相比之下,1s時間片的rr可以快速地迴圈工作,其平均響應時間為\((0+1+2)/3=1s\)。
顯然,時間片長度對於rr是至關重要的。時間片越短,rr在響應時間上表現越好。然而,時間片太短是有問題的:突然上下文切換的成本將影響整體效能。因此,系統設計者需要權衡時間片的長度,使其足夠長,以便攤銷上下文切換成本,而又不會使系統不及時響應。
接下來我們放寬假設4,現在所有的程式都會執行i/o。排程程式顯然要在工作發起i/o請求時做出決定,因為當前正在執行的作業在i/o期間不會使用cpu,它被阻塞等待i/o完成。如果將i/o傳送到硬碟驅動器,則程序可能會被阻塞幾毫秒或更長時間。因此,這時排程程式應該在cpu上安排另一項工作。排程程式還必須在i/o完成時做出決定。發生這種情況時,會產生中斷,作業系統執行並將發出i/o的程序從阻塞狀態移回就緒狀態。當然,它甚至可以決定在那個時候執行該項工作。作業系統應該如何處理每項工作?
假設有兩項工作a和b,每項工作需要50ms的cpu時間。但是a先執行10ms,然後發出i/o請求(假設i/o每個都需要10ms),而b只是使用cpu 50ms,不執行i/o。排程程式先執行a,然後執行b。
毫無疑問,上圖所示的排程是非常糟糕的。常見的方法是將a的每個10ms的子工作視為一項獨立的工作。因此,當系統啟動時,它的選擇是排程10ms的a,還是50ms的b。stcf會選擇較短的a。然後,a的工作已完成,只剩下b,並開始執行。然後提交a的乙個新子工作,它搶占b並執行10ms。這樣做可以實現重疊,乙個程序在等待另乙個程序的i/o完成時使用cpu,系統因此得到更好的利用。
有了應對i/o的基本方法,我們來到最後的假設5:排程程式知道每個工作的長度。如前所述,這可能是可以做出的最糟糕的假設。事實上,作業系統通常不知道每個作業的長度。因此,我們將在第8章利用最近的歷史**未來,從而解決這個問題。
作業系統 第2章 程序管理 2 2 2 3
一 程序控制的基本過程 1 1 程序的建立 乙個程序建立另一程序的事件 原因 使用者登入 分時情況下使用者的請求 作業排程 批處理中 提供服務 執行中的使用者程式提出功能請求,要建立服務程序 如列印服務 應用請求 應用程式自己建立程序,完成特定功能的新程序。木馬程式 2 建立過程 1 申請空白pcb...
第4章程序排程(六)
4.7 實時排程策略 linux提供兩種實時排程策略 sched fifo和sched rr。普通的 非實時的排程策略是sched normal。借助排程類的框架,這些實時策略被乙個特殊的實時排程器管理。具體實現定義在kernel sched rt.c中。sched fifo是一種簡單的 先入先出的...
第7章 程序環境
main函式之前會有乙個特殊的啟動程式,啟動例程從核心取得命令列引數和環境變數。正常終止 從main函式返回 呼叫exit 呼叫 exit或 exit 最後乙個執行緒從啟動例程返回 最後乙個執行緒呼叫pthread exit 異常終止 呼叫abort 接到乙個訊號終止 最後乙個執行緒對取消請求作出相...