?
目錄
?
前言
?1. 進程狀態
?2. 運行狀態
?3. 阻塞狀態
?4. 掛起狀態
5. Linux中具體的狀態
總結
前言
? ? ? ? ?在Linux操作系統中,進程狀態非常重要,它可以幫助我們了解進程在系統中的運行情況,從而更好地管理和優化系統資源,在Linux系統中,進程可以處于不同的狀態,本文我們來聊一聊運行、阻塞、掛起這幾狀態;
?1. 進程狀態
?????????在許多教材以及資料當中有許多對進程狀態的總結與描述,資料不同它們的描述也各有略同,但總都是一些概念,Linux進程狀態具體是什么?本文我們將從底層出發,聊一聊運行、阻塞、掛起這幾狀態;
?溫馨提示:如果在本文中某些名稱或者內容不太了解,可以先閱讀這篇文章:
Linux進程的理解
?2. 運行狀態
? ? ? ?從計算機硬件出發,我們寫的代碼生成可執行文件都被存儲在磁盤當中,想要讓程序運行就必須將程序加載到內存當中;
????????每一個程序(進程)都會有一個屬于自己的PCB,通過PCB來進行排隊,等待CPU的調度;
????????為了便于調度管理,操作系統會在內存當中維護一個叫運行隊列的結構,所有就緒狀態的進程的PCB會被加入到這個隊列當中;
????????CPU在調度執行時就會通過這個運行隊列拿到進程的PCB,進而調度執行該進程;
?????????只要進程在這個運行隊列當中,它的狀態就是運行狀態;每個CPU在系統中都會維護一個運行隊列;
?3. 阻塞狀態
? ? ? ? 了解完運行狀態,我們再來聊一聊阻塞狀態,阻塞狀態是建立在進程被調度執行的基礎上;
?????????在CPU執行一個進程時,都可能會或多或少的去訪問系統的某些資源,比如:我們使用的scanf,在執行時需要調用鍵盤(本質就是從鍵盤中讀取數據);
????????我們不輸入,鍵盤的數據就是沒有就緒(進程需要訪問的數據沒有就緒),此時進程無法繼續執行,需要等待數據;
狀態又是如何轉變的呢?
?????????操作系統和驅動程序它們對硬件進行管理,每個硬件都會有一個屬于自己的結構描述,通過指針鏈接,操作系統通過鏈表(dev_list)達到對硬件設施的管理;
????????當進程正在等待某個硬件的資源時,把進程的PCB加入到硬件設備結構描述的等待隊列當中,并把PBC的狀態設置為阻塞狀態;當PCB在這個等待隊列中等待數據資源時,這個狀態就叫做阻塞狀態;
?????????系統資源等待結束之后,操作系統會再次將等待隊列中的PCB移入到運行隊列當中,并把狀態修改為運行狀態,等待CPU的執行調度;
?4. 掛起狀態
?了解完阻塞狀態,我們來聊一聊掛起狀態;掛起全稱:阻塞掛起;
掛起是基于阻塞的一種狀態;
????????進程處于阻塞狀態時,并且內存不足的情況下就會出現;
? ? ? ? ?針對于這種情況,操作系統會將阻塞進程的代碼和數據置換到外設,此時該進程的狀態就被稱為掛起狀態;
? ? ? ? ?阻塞進程的代碼和數據一般會存放在磁盤的swap分區,當進程被操作系統調度時,被置換到外設的代碼和數據又會重新加載到內存;
?拓展補充
? ? ? ? ?一般情況下,swap分區的大小不會太大,大概等于內存的大小,過大的swap分區會導致操作系統過于依賴swap分區,導致效率變低;
5. Linux中具體的狀態
?說了這么多理論,那么在Linux中進程的狀態又是怎樣的?
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內核源碼對進程狀態的定義;它其實并沒有像阻塞掛起這樣的狀態;
我們也可以寫一個程序來測試一下:
#include <stdio.h>
#include <unistd.h>int main()
{while(1){ printf("hello world! \n");}return 0;
}
在Linux環境下編譯運行,然后使用監控進行觀察:
while :; do ps ajx | head -1 && ps ajx | grep myprocess | grep -v grep; sleep 1; done
//myprocess是可執行文件的名稱
?觀察到的情況分為兩種,大多數是S+,極少數是R+:
????????主要是因為調用的printf,在輸出時需要調用顯示器,大多數的時間都是在等待顯示器;我們也可以寫一個空的死循環執行來觀察;
R狀態我們都知道是運行狀態,S狀態是什么?
? ? ? ? ?S(sleeping)休眠狀態,這里的睡眠是淺度睡眠,可以對發送的信號做出響應;
?這里的 “+” 號是什么意思?
? ? ? ? 進程被分為前臺進程和后臺進程,帶+號就表示是前臺進程;
- 前臺進程:正常使用 ./可執行程序,這種執行方式運行起來就是前臺進程,前臺進程運行時,無論我們怎么輸入指令都無法被執行(Ctrl +c可終止進程)
- 后臺進程:./ 可執行程序 &?這種執行方式運行起來就是后臺進程,后臺進程運行時,我們輸入的指令依然可以執行(Ctrl +c 無法終止進程,使用kill + 9 +進程pid 殺死進程)
?這里的S狀態其實就是上述阻塞狀態;
?D狀態
? ? ? ? ?D(disk sleep)也是休眠狀態,它是深度休眠,專門針對磁盤設計的;
?當進程需要將較大的數據寫入到磁盤當中,在等待磁盤寫入時進程的狀態就是休眠狀態;如果是S狀態:
????????在內存嚴重不足的情況下,操作系統沒辦法時會通過殺死進程的方式來節省資源;如果在等待的過程中進程被操作系統殺掉,并且磁盤寫入數據失敗,那么就會導致數據無法再加載(數據丟失);為了避免這種情況,就可以把等待數據寫入的進程狀態設為D狀態;
D狀態無法被殺掉(OS也不行),只能等待執行完畢后狀態轉換;
?注意:
如果用戶看到了D狀態,說明計算機幾乎要掛掉了
?T狀態
?T停止狀態(stopped): 可以通過發送 SIGSTOP 信號給進程來停止(T)進程。這個被暫停的進程可以通過發送 SIGCONT 信號讓進程繼續運行
kill -SIGSTOP <進程ID>
?使用kill指令可以查看發送給信號的所有類型:
kill -l
?為什么要停止?
進程在訪問資源時,可能暫時不允許進程訪問,這時OS就會將進程的狀態設置為stop(T狀態)
?t狀態
t狀態也是停止狀態,Linux中沒有進行區分;
?主要出現在程序Debug時,在Debug的時候,遇到斷點,進程就暫停,此時就是t狀態
?在上述的D狀態、T狀態、t狀態其實都是阻塞狀態,阻塞可以等待硬件資源也可以等待軟件資源
?比如:一個進程等待另一個進程,進程的PCB里可以有PCB* wait_queue,比如gdb的進程等待Debug的進程;
?X狀態
? ? ? ? X狀態(死亡狀態),就是我們常說的終止狀態,它是一個瞬時狀態,不會在任務列表里看到這個狀態
?
?最后就是Z(zombie)僵尸狀態,僵尸狀態較為復雜,Linux系統中的僵尸進程狀態也是一種特殊的進程狀態,通常是指一個子進程已經結束運行,但其父進程還未對其進行善后處理(如調用wait()函數)。如果不及時清理僵尸進程,會導致系統資源泄漏,影響系統性能甚至造成系統崩潰;
?
總結
? ? ? ? ?本文主要從底層出發向大家介紹了運行、阻塞、掛起這幾種常見的狀態,并且將Linux中具體的狀態進行了一系列介紹,可以劃分為這幾種狀態;最后是僵尸狀態,僵尸狀態的情況較為特殊,如果不及時處理也會造成比較嚴重的后果,我們下期再來進行詳細的介紹,以上便是本文的全部內容,希望可以對你有所幫助,感謝閱讀!