進程調度, 一個調度器的自白


我是一個進程調度器。

我的職責是調度計算機內所有的進程,為他們分配 CPU 資源。

1. 批處理時代

想當初,操作系統創造我時,只是打算讓我用 FCFS 調度算法,簡單維護下進程的秩序。但我后來的發展,遠遠超過了他的想象。

1.1 FCFS

所謂 FCFS 就是「先來先服務(First Come First Serve)」,每個進程按進入內存的時間先后排成一隊。每當 CPU 上的進程運行完畢或者阻塞,我就會選擇隊伍最前面的進程,帶着他前往 CPU 執行。

就拿這幾個進程來說吧:

按照 FCFS 算法,我就會就按 A,B,C,D,E這樣的順序來將他們送往 CPU:

這一算法聽起來簡單又公平,然而好景不長,我收到了一個短進程的抱怨:”上次我前面排了一個長進程,等了足足 200 秒他才運行完。我只用 1 秒就運行結束了,就因為等他,我多花了這么長時間,太不值得了。”

我仔細一想, FCFS 算法確實有這個缺陷——短進程的響應時間太長了,用戶交互體驗會變差。

所以我決定,更換調度算法。

1.2 SPN

這次我設計的算法叫做「短任務優先」(Shortest Process Next,SPN)。每次選擇預計處理時間最短的進程。因此,在排隊的時候,我會把短進程從隊列里提到前面。

這一次,短進程得到了很好的照顧,進程的平均響應時間大大降低,我和操作系統都很滿意。

但長進程們不干了:那些短進程天天插隊,導致他們經常得不到 CPU 資源,造成了「飢餓」現象。

取消 SPN 算法的呼聲越來越高。

這可是個大問題。FCFS 雖然響應時間長,但最后所有進程一定有使用 CPU 資源的機會。但 SPN 算法就不一樣了,如果短進程源源不斷加入隊列,長進程們將永遠得不到執行的機會——太可怕了。

因此,短任務優先算法需要得到改進。有什么方法既能照顧短進程,又能照顧長進程呢?

1.3 HRRN

經過和操作系統的討論,我們決定綜合考量進程的兩個屬性:等待時間要求服務時間——等待時間長,要求服務時間短(就是短進程)的進程更容易被選中。

為了量化,我們制定了一個公式:響應比 = (等待時間+要求服務時間)/ 要求服務時間。響應比高的算法會先執行。我們稱之為「高響應比優先」(Highest Response Ratio Next,HRRN)。

這個算法得到了長短進程的一致好評。雖然我的工作量增加了(每次調度前,我都要重新計算所有等待進程的響應比)但為了進程們的公平性,這一切都是值得的。

2. 並發時代

新時代到了。

隨着計算機的普及,個人用戶大量增長,並發,即一次運行多個程序的需求出現了。這可難倒我了——處理器只有一個,怎么運行多個程序?

所幸 CPU 點醒了我:“我現在的運算速度既然這么快,何不發揮這項長處,弄一個「偽並行」出來?“

“偽並行?什么意思”

“就是看起來像並行,實際上還是串行。每個進程短時間交替使用我的資源,但在人類看來,這些進程就像在「同時」運行。”

我恍然大悟。

2.1 RR

經過 CPU 的提醒,我很快制定出了新的調度算法——時間片輪轉算法(Round Robin,RR)。

在這個算法里,每個進程將輪流使用 CPU 資源,只不過在他們開始運行時,我會為他們打開定時器,如果定時器到時間(或者執行阻塞操作),進程將被迫「下機」,切換至下一個進程。至於下一個進程的選擇嘛,直接用 FCFS 就好了。

新的算法必然會面臨新的問題,現在我的問題就是,時間片的長度怎么設計?

直觀來看,時間片越短,固定時間里可運行的進程就越多,可 CPU 說過,切換進程是要消耗他不少指令周期的,時間片過短會導致大量 CPU 資源浪費在切換上下文上。時間片過長,短交互指令響應會變慢。所以具體怎么取,還得看交互時間大小(感覺像沒說一樣,但至少給了個標准嘛)。

這一階段,我的工作量大大提升——以前十幾秒都不用切換一次程序,現在倒好,一秒鍾就得切換數十次。

2.2 VRR

時間片輪轉算法看起來十分公平——所有的進程時間片都是一樣的。但事實真是這樣嗎?

I/O 密集型進程不這么認為,他對我說:“調度器大哥,時間片輪轉沒有照顧到我們這類進程啊!我們經常在 CPU 沒呆到一半時間片,就遇到了阻塞操作,被你趕下去。而且我們在阻塞隊列,往往要停留很長時間。等阻塞操作結束,我們還得在就緒隊列排好長時間隊。那些處理器密集型進程,使用了大部分的處理器時間,導致我們性能降低,響應時間跟不上”

考慮到這些進程的要求,我決定為他們創建一個新的輔助隊列。阻塞解除的進程,將進入這個輔助隊列,進行進程調度時,優先選擇輔助隊列里的進程。

這就是「虛擬輪轉法」(Virtual Round Robin,VRR)。

從后來實際性能結果來看,這種方法確實優於輪轉法。我頗為自豪。

2.3 優先級調度

有一天,操作系統忽然找到我,神神秘秘的說:“調度器啊,你是知道的,我要給整個系統提供服務,可最近用戶進程太多,導致我的服務進程有時候響應跟不上。我有點擔心這會給系統穩定性造成影響。”

我一聽,這可是個大事,系統不穩定那還得了?調度算法得換!

既然要讓操作系統的服務得到足夠的運行資源,那就,干脆讓他們具有最高的 CPU 使用優先權吧。

優先級調度算法就此產生了。

我向大家做出了規定——每個進程將被賦予一個優先級,自己根據自己的情況確定優先級數值,但是,用戶進程的優先級不准高於內核進程的優先級。

切換程序的時候,我會從優先級 1 的隊列里選擇一個進程,如果優先級 1 隊列為空,才會選擇優先級 2 中的進程,以此類推。

當然,為了保證低優先級進程不會飢餓,我會調高等待時間長的進程的優先級。

使用這個算法,我更忙碌了,不僅需要大量切換進程,還需要動態調節優先級。可能這就是能力越大,責任越大吧。

不過我知道,正是因為我的存在,人類才能在計算機上運行多道程序——這令我感到自豪。

希望你在看完我的文章之后有所收獲。

感謝你的閱讀,我們后會有期!

聲明:原創文章,未經授權,禁止轉載


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM