目錄
前言
操作系統進程狀態
運行狀態
阻塞狀態
掛起狀態
Linux中具體的進程狀態
R(running)運行狀態
S(sleeping)阻塞狀態
D(disk sleep)磁盤休眠狀態
T(stopped)和t(tracing stop)
X(dead)終止狀態
Z(zombie)僵尸狀態
僵尸進程的危害
前言
我們在運行可執行程序形成進程后,操作系統要對多個進程進行管理,根據進程的狀態對進程分類,不同類型的進程有不同的處理方案,下面將對不同進程的特點進行介紹。
操作系統進程狀態
以上是進程狀態之間的相互轉化過程,下面將詳細圍繞三個狀態展開:運行狀態,阻塞狀態,掛起狀態。
運行狀態
?運行狀態就是正在運行的進程,很好理解;
問題是:CPU只有一個,但是進程有多個,可能多個進程都處于運行狀態,操作系統是如何平衡這些進程的,如何保證這些進程都能夠持續運行???
有多個進程都要運行,那就意味著在一段時間內每個進程都要得到執行。當然因為CPU只有一個所以在一個時間點只能對運行一個進程。?
在操作系統中有一個概念叫做運行隊列,所有處于運行狀態進程的PCB數據結構體對象都在這個隊列中排隊,一個個的運行;排隊的先后順序是根據進程的優先級決定的。
在進程中有一個時間片的概念,時間片可以保證每個進程在CPU中運算,處理的時間差不多,是每個進程都有機會執行。
CPU對進程依次進行處理,那為什么我并沒有感覺到我打開的程序有卡頓的情況???這是初學者經常會出現的誤區,這是因為CPU計算處理的速度太快了,人根本感知不到。
阻塞狀態
阻塞狀態很形象,不明事宜進程被阻塞了,不能再繼續運行。出現阻塞狀態有很多原因通常是因為:?I/O 操作完成、等待用戶輸入、等待資源分配。就是進程處于等待狀態,沒有處在運行隊列中,即使CPU空閑也無法對這樣的進程進行計算,處理。
處于阻塞狀態的進程存放在哪里???
操作系統對與軟硬件管理的基礎是:先描述,再組織。操作系統也要對硬件進行管理,所以操作系統中理應存在描述硬件信息的結構體對象。所以處于阻塞狀態的進程放在對應外設(等待從那里讀取數據)結構體對象的等待隊列中。
掛起狀態
常見的掛起狀態是阻塞掛起狀態。
阻塞掛起狀態:當操作系統中有多個進程在同時加載,計算機中內存不足時,操作系統就會將一些處于阻塞狀態的進程的信息,數據,PCB結構體對象都置換到外設(硬盤)中去,來使得計算機中空出一些內存繼續進行運算,當一些進程執行完后釋放空間又夠了,再將數據從外設加載到內存中讓進程繼續執行。信息被拷貝到外設的進程就稱為處于掛起狀態的進程。
Linux中具體的進程狀態
上面介紹了操作系統中進程狀態的總體劃分,下面以Linux為例詳細介紹以下Linux下的進程狀態。
*
*The task state array is a strange "bitmap" of
*reasons to sleep. Thus "running" is zero, and
*you can test for combinations of others with
*simple bit tests.
*/
static const char *const task_state_array[] = {
"R (running)", /*0 */
"S (sleeping)", /*1 */
"D (disk sleep)", /*2 */
"T (stopped)", /*4 */
"t (tracing stop)", /*8 */
"X (dead)", /*16 */
"Z (zombie)", /*32 */
}
以上是Linux內核中定義的進程狀態有7種:R(running)運行狀態,S(sleeping)阻塞狀態或淺度睡眠,D(disk sleep)深度睡眠,T(stopped)和t(tracing stop)暫停狀態,X(dead)死亡狀態,Z(zombie)僵尸狀態。下面對這7種進程狀態特點進行一一解釋。
R(running)運行狀態
依舊是將處于運行狀態的進程放入到運行隊列中進行調用,與前面說的一樣沒有特別之處。
S(sleeping)阻塞狀態
也叫淺度睡眠狀態,等待一些外設或I/O,用戶指令......無法繼續向后執行下去。
在上面談到掛起狀態:當內存不足時,操作系統會將一些進程的代碼和數據以及PCB對象從內存置換到外設來空出內存供其他進程使用,被掛起的進程通常是處于阻塞狀態的進程。
但是如果被掛起的進程正在等待磁盤信息的寫入,等著磁盤告訴它是否寫入成功的時候,突然該進程被掛起了,那磁盤內容是否寫入成功就沒人知道了,那數據如果沒有寫入成功還不知道,數據不久丟失了嗎???
使得確實是這樣的,所以操作系統有新增了一個狀態D(disk sleep);
D(disk sleep)磁盤休眠狀態
將正在等待磁盤寫入或高I/O時才會出現,處于這種狀態的進程不能被進程殺掉或掛起。
D狀態的時間很短,一般在查進程狀態時一般看不到這種狀態,如果看到了說明磁盤現在寫入的壓力很大,很有可能操作系統快掛了。
T(stopped)和t(tracing stop)
T(stopped)和t(tracing stop)兩個都表示暫停狀態,只不過暫停的原因是不一樣的。此處將其看作一樣的。
暫停狀態和阻塞狀態有什么區別呢???他們不都是停止運行嗎???
其主要區別在于暫停的原因是什么;阻塞狀態的進程是在等待資源就緒,而處于暫停狀態的進程是用戶操作的,比如kill -19 +PID讓進程暫停,kill -18?+PID讓進程繼續;還有gdb在進行調試的時候停止在一個斷點上也是處于等待狀態。
X(dead)終止狀態
終止狀態,毫無疑問程序運行結束后的狀態,程序運行結束后會放到垃圾回收隊列里面,等待釋放。
Z(zombie)僵尸狀態
我們知道每一個進程都有父進程,在命令行上打開的可執行程序也有父進程。在打開命令行時操作系統會自動將命令行解釋器加載到內存中形成一個進程,所以當使用命令行打開其他程序時,命令行解釋器就是它們的父進程。
當一個進程在進入終止狀態之前,不會立即進入到垃圾回收隊列中,而是先維護一會進程的屬性狀態即PCB結構體對象,讓與其有關的進程(父進程)知道該進程要被釋放了,很容易理解當一個進程要結束了必須要讓操作系統知道,否則一個進程都結束了,而操作系統不知道,那操作系統還怎么管理進程。處于維護進程狀態,等待子進程獲取其狀態信息的進程就處于僵尸進程,即快要死了,但還沒死。
進程推出前,如果都進程沒有主動獲取子進程的相關信息,子進程就會一直處于Z狀態直到父進程來獲取其進程信息。
那如果父進程先子進程結束,怎么辦???
如果父進程先結束,那么子進程就會稱為孤兒進程,子進程的父進程將變成操作系統,被操作系統領養,操作系統直到關機一直都在。
僵尸進程的危害
- 進程推出狀態要一直維護,直到父進程來獲取進程的相關信息;
- 父進程一直不來獲取子進程的相關信息,PCB就需要一直維護,也需要一直保持Z狀態;
- 如果一直不回收子進程就會導致PCB長時間占用內存,導致內存泄漏。