1. 程式人生 > >程序的掛起、阻塞和睡眠

程序的掛起、阻塞和睡眠

轉:https://www.cnblogs.com/ck1020/p/6669661.html

要說掛起、阻塞、睡眠難免讓人想到程序生命週期中的阻塞態或者等待狀態,而掛起和睡眠卻沒有出現在程序生命週期中,說明這三個其實在本質上區別並不那麼大,但是既然稱呼不同,應該就有不同的道理。

先說阻塞,既然它能出現在程序生命週期,必然是每個程序都會經歷的一個階段,眾所周知,程序在執行過程中必然要獲取資源,暫且不說CPU,程序執行肯定要和磁碟進行互動,繼而發生IO操作,IO操作勢必要引起等待,在資源未讀取完成,程序必然要等待,那麼在等待IO完成這個部分就是阻塞狀態。所以從這裡來看,阻塞是一種被動的方式,由於獲取資源獲取不到而引起的等待。

再說睡眠,睡眠就是一種主動的方式,其實個人認為睡眠和阻塞在一個層次上,為何這麼說呢?當一個程序獲取資源比如獲取最普通的鎖而失敗後,可以有兩種處理方式,1、自己睡眠,觸發排程;2、忙等待,使用完自己的時間。所以從這裡看,睡眠的確是一種主動的方式,且僅僅作為一種處理手段。當然睡眠不僅僅用於阻塞,更多的,我們可以在適當的時候設定讓程序睡眠一定的時間,那麼在這裡,就可以發現,睡眠之前,我們已經預先規定了,你只能睡多長時間,這段時間過後,比必須返回來工作。

最後說掛起,掛起也是一種主動的行為,具體而言,掛起是系統層面對程序作出的合理操作。本來想說排程,但是程序排程作為專業術語指CPU資源的分配,那麼這裡就說操作。掛起的標誌就是換出到外存,在外存的程序肯定是不能執行的,所以掛起的目的就很明顯,在記憶體資源不足時,需要把一些程序換出到外存,給著急執行的程序騰地方。掛起傾向於換出阻塞態的程序,也可以是就緒態的程序。只是這個轉換幾乎不會採用,因為任意時刻,肯定可以找到在記憶體中的阻塞態程序,但也不能缺少這種直接把就緒轉換到掛起的能力。

其實相比之下,睡眠和其他兩個結合的不太緊密,有資料說掛起釋放記憶體,而阻塞不釋放記憶體也有一定的道理。下面結合一個圖看掛起和阻塞的狀態轉換:

  • 就緒態:程序在記憶體中並可以執行。
  • 阻塞態:程序在記憶體中並等待一個事件。
  • 阻塞/掛起態:程序在外存中並等待一個事件。
  • 就緒/掛起態:程序在外存中,但是隻要被載入記憶體就可以執行。

 

 阻塞和掛起之間的相互轉換如下:

阻塞→阻塞/掛起:如果沒有就緒程序,則至少一個阻塞程序被換出,為另一個沒有阻塞的程序讓出空間。如果作業系統確定當前正在執行的程序,或就緒程序為了維護基本的效能要求而需要更多的記憶體空間,那麼,即使有可用的就緒態程序也可能出現這種轉換。

阻塞/掛起→就緒/掛起:如果等待的事件發生了,則處於阻塞/掛起狀態的程序可以轉換到就緒/掛起狀態。注意,這要求作業系統必須能夠得到掛起程序的狀態資訊。

就緒/掛起→就緒:如果記憶體中沒有就緒態程序,作業系統需要調入一個程序繼續執行。此外,當處於就緒/掛起態的程序比處於就緒態的任何程序的優先順序都要高時,也可以進行這種轉換。這種情況的產生是由於作業系統設計者規定調入高優先順序的程序比減少交換量更重要。

就緒→就緒/掛起:通常,作業系統更傾向於掛起阻塞態程序而不是就緒態程序,因為就緒態程序可以立即執行,而阻塞態程序佔用了記憶體空間但不能執行。但如果釋放記憶體以得到足夠空間的唯一方法是掛起一個就緒態程序,那麼這種轉換也是必需的。並且,如果作業系統確信高優先順序的阻塞態程序很快將會就緒,那麼它可能選擇掛起一個低優先順序的就緒態程序,而不是一個高優先順序的阻塞態程序。

 

參考:《作業系統:精髓與設計原理(原書第6版)》

分類: linux 核心原始碼分析