2017-04-05 16:14:22
今天腦子中突然想起進程的掛起和阻塞有什么區別,自己頭腦風暴了下,還真不好解釋,結合進程的睡眠,於是就有了今天這篇文章,以下內容均是個人參考資料后得到的自己的理解,如有錯誤,還請指正!
要說掛起、阻塞、睡眠難免讓人想到進程生命周期中的阻塞態或者等待狀態,而掛起和睡眠卻沒有出現在進程生命周期中,說明這三個其實在本質上區別並不那么大,但是既然稱呼不同,應該就有不同的道理。
先說阻塞,既然它能出現在進程生命周期,必然是每個進程都會經歷的一個階段,眾所周知,進程在運行過程中必然要獲取資源,暫且不說CPU,進程運行肯定要和磁盤進行交互,繼而發生IO操作,IO操作勢必要引起等待,在資源未讀取完成,進程必然要等待,那么在等待IO完成這個部分就是阻塞狀態。所以從這里來看,阻塞是一種被動的方式,由於獲取資源獲取不到而引起的等待。
再說睡眠,睡眠就是一種主動的方式,其實個人認為睡眠和阻塞在一個層次上,為何這么說呢?當一個進程獲取資源比如獲取最普通的鎖而失敗后,可以有兩種處理方式,1、自己睡眠,觸發調度;2、忙等待,使用完自己的時間。所以從這里看,睡眠的確是一種主動的方式,且僅僅作為一種處理手段。當然睡眠不僅僅用於阻塞,更多的,我們可以在適當的時候設置讓進程睡眠一定的時間,那么在這里,就可以發現,睡眠之前,我們已經預先規定了,你只能睡多長時間,這段時間過后,比必須返回來工作。
最后說掛起,掛起也是一種主動的行為,具體而言,掛起是系統層面對進程作出的合理操作。本來想說調度,但是進程調度作為專業術語指CPU資源的分配,那么這里就說操作。掛起的標志就是換出到外存,在外存的進程肯定是不能執行的,所以掛起的目的就很明顯,在內存資源不足時,需要把一些進程換出到外存,給着急運行的進程騰地方。掛起傾向於換出阻塞態的進程,也可以是就緒態的進程。只是這個轉換幾乎不會采用,因為任意時刻,肯定可以找到在內存中的阻塞態進程,但也不能缺少這種直接把就緒轉換到掛起的能力。
其實相比之下,睡眠和其他兩個結合的不太緊密,有資料說掛起釋放內存,而阻塞不釋放內存也有一定的道理。下面結合一個圖看掛起和阻塞的狀態轉換:
- 就緒態:進程在內存中並可以執行。
- 阻塞態:進程在內存中並等待一個事件。
- 阻塞/掛起態:進程在外存中並等待一個事件。
- 就緒/掛起態:進程在外存中,但是只要被載入內存就可以執行。
阻塞和掛起之間的相互轉換如下:
阻塞→阻塞/掛起:如果沒有就緒進程,則至少一個阻塞進程被換出,為另一個沒有阻塞的進程讓出空間。如果操作系統確定當前正在運行的進程,或就緒進程為了維護基本的性能要求而需要更多的內存空間,那么,即使有可用的就緒態進程也可能出現這種轉換。
阻塞/掛起→就緒/掛起:如果等待的事件發生了,則處於阻塞/掛起狀態的進程可以轉換到就緒/掛起狀態。注意,這要求操作系統必須能夠得到掛起進程的狀態信息。
就緒/掛起→就緒:如果內存中沒有就緒態進程,操作系統需要調入一個進程繼續執行。此外,當處於就緒/掛起態的進程比處於就緒態的任何進程的優先級都要高時,也可以進行這種轉換。這種情況的產生是由於操作系統設計者規定調入高優先級的進程比減少交換量更重要。
就緒→就緒/掛起:通常,操作系統更傾向於掛起阻塞態進程而不是就緒態進程,因為就緒態進程可以立即執行,而阻塞態進程占用了內存空間但不能執行。但如果釋放內存以得到足夠空間的唯一方法是掛起一個就緒態進程,那么這種轉換也是必需的。並且,如果操作系統確信高優先級的阻塞態進程很快將會就緒,那么它可能選擇掛起一個低優先級的就緒態進程,而不是一個高優先級的阻塞態進程。
參考:《操作系統:精髓與設計原理(原書第6版)》