Linux六種程序狀態R S D T Z X

2021-10-10 21:23:48 字數 3036 閱讀 9805

此文章已同步更新至我的個人部落格

​ 只有在該狀態的程序才可能在cpu上執行。而同一時刻可能有多個程序處於可執行狀態,這些程序的task_struct結構(程序控制塊)被放入對應cpu的可執行佇列中(乙個程序最多只能出現在乙個cpu的可執行佇列中)。程序排程器的任務就是從各個cpu的可執行佇列中分別選擇乙個程序在該cpu上執行。 很多作業系統教科書將正在cpu上執行的程序定義為running狀態、而將可執行但是尚未被排程執行的程序定義為ready狀態,這兩種狀態在linux下統一為 task_running狀態。 linux程序狀態:s (task_interruptible),可中斷的睡眠狀態。 處於這個狀態的程序因為等待某某事件的發生(比如等待socket連線、等待訊號量),而被掛起。這些程序的task_struct結構被放入對應事件的等待佇列中。當這些事件發生時(由外部中斷觸發、或由其他程序觸發),對應的等待佇列中的乙個或多個程序將被喚醒。 通過ps命令我們會看到,一般情況下,程序列表中的絕大多數程序都處於task_interruptible狀態(除非機器的負載很高)。畢竟cpu就這麼一兩個,程序動輒幾十上百個,如果不是絕大多數程序都在睡眠,cpu又怎麼響應得過來。

​ 處於這個狀態的程序,因為等待某某事件的發生(比如等待socket連線、等待訊號量),而被掛起。這些程序的task_struct結構被放入對應事件的等待佇列中。當這些事件發生時(由外部中斷觸發、或由其他程序觸發),對應的等待佇列中的乙個或多個程序將被喚醒。 程序列表中的絕大多數程序都處於task_interruptible狀態。cpu就這麼一兩個,程序動輒幾十上百個,如果不是絕大多數程序都在睡眠,cpu將會響應不過來。

​ 程序處於睡眠狀態,但是此刻程序是不可中斷的。不可中斷,指的並不是cpu不響應外部硬體的中斷,而是指程序不響應非同步訊號。絕大多數情況下,程序處在睡眠狀態時,總是應該能夠響應非同步訊號的。

而task_uninterruptible狀態存在的意義在於,程序對某些硬體進行操作時(比如程序呼叫read系統呼叫對某個裝置檔案進行讀操作,而read系統呼叫最終執行到對應裝置驅動的**,並與對應的物理裝置進行互動),可能需要使用task_uninterruptible狀態對程序進行保護,以避免程序與裝置互動的過程被打斷,造成裝置陷入不可控的狀態。這種情況下的task_uninterruptible狀態總是非常短暫的,通過ps命令基本上不可能捕捉到。

linux系統中也存在容易捕捉的task_uninterruptible狀態。執行vfork系統呼叫後,父程序將進入task_uninterruptible狀態,直到子程序呼叫exit或exec。通過下面的**就能得到處於task_uninterruptible狀態的程序:

#include

#include

void

main()

編譯執行,然後ps一下:

$ ps -ax |

grep a\.out

4371 pts/0 d+ 0:00 ./a.out

4372 pts/0 s+ 0:00 ./a.out

4374 pts/1 s+ 0:00 grep a.out

然後我們可以試驗一下task_uninterruptible狀態的威力。不管kill還是kill -9,這個task_uninterruptible狀態的父程序依然屹立不倒。

​ 向程序傳送乙個sigstop訊號,它就會因響應該訊號而進入task_stopped狀態(除非該程序本身處於task_uninterruptible狀態而不響應訊號)。(sigstop與sigkill訊號一樣,是非常強制的。不允許使用者程序通過signal系列的系統呼叫重新設定對應的訊號處理函式。)向程序傳送乙個sigcont訊號,可以讓其從task_stopped狀態恢復到task_running狀態。

程序在退出的過程中,處於task_dead狀態。

在這個退出過程中,程序占有的所有資源將被**,除了task_struct結構(以及少數資源)以外。於是程序就只剩下task_struct這麼個空殼,故稱為殭屍。之所以保留task_struct,是因為task_struct裡面儲存了程序的退出碼、以及一些統計資訊。而其父程序很可能會關心這些資訊。釋放掉task_struct,則需要建立一些新的資料結構,以便讓父程序找到它的子程序的退出資訊。

父程序可以通過wait系列的系統呼叫(如wait4、waitid)來等待某個或某些子程序的退出,並獲取它的退出資訊。然後wait系列的系統呼叫會順便將子程序的屍體(task_struct)也釋放掉。子程序在退出的過程中,核心會給其父程序傳送乙個訊號,通知父程序來「收屍」。這個訊號預設是sigchld,但是在通過clone系統呼叫建立子程序時,可以設定這個訊號。

通過下面的**能夠製造乙個exit_zombie狀態的程序:

#include

#include

void

main()

編譯執行,然後ps一下:

$ ps -ax |

grep a\.out

10410 pts/0 s+ 0:00 ./a.out

10411 pts/0 z+ 0:00 [a.out]

10413 pts/1 s+ 0:00 grep a.out

只要父程序不退出,這個殭屍狀態的子程序就一直存在。那麼如果父程序退出了呢,誰又來給子程序「收屍」?當程序退出的時候,會將它的所有子程序都託管給別的程序(使之成為別的程序的子程序)。託管給誰呢?可能是退出程序所在程序組的下乙個程序(如果存在的話),或者是1號程序。所以每個程序、每時每刻都有父程序存在。除非它是1號程序。

1號程序,pid為1的程序,又稱init程序。linux系統啟動後,第乙個被建立的使用者態程序就是init程序。它有兩項使命:1、執行系統初始化指令碼,建立一系列的程序(它們都是init程序的子孫);2、在乙個死迴圈中等待其子程序的退出事件,並呼叫waitid系統呼叫來完成「收屍」工作;init程序不會被暫停、也不會被殺死(這是由核心來保證的)。它在等待子程序退出的過程中處於task_interruptible狀態,「收屍」過程中則處於task_running狀態。

Linux程序六種狀態(R S D T Z X)

1 r執行狀態 runing 並不意味著程序一定在執行中,也可以在執行佇列裡 2 s睡眠狀態 sleeping 程序在等待事件完成 淺度睡眠,可以被喚醒 3 d磁碟睡眠狀態 disk sleep 不可中斷睡眠 深度睡眠,不可以被喚醒,通常在磁碟寫入時發生 4 t停止狀態 stopped 可以通過傳送...

六種執行緒狀態詳解

執行緒從建立到執行到結束是乙個執行緒的生命週期,當執行緒被建立到結束過程中,不是一直處於執行狀態的,下面來介紹一下執行緒從執行到結束所有的狀態.執行緒狀態 導致狀態發生條件 new 新建 執行緒剛被建立,沒有啟動,也就是還沒呼叫start 方法.mythread t new mythread只有執行...

Thread的六種狀態

執行緒共有6種狀態 在某一時刻只能是這6種狀態之一。這些狀態由thread.state這個列舉型別表示,並且可以通過getstate 方法獲得當前具體的狀態型別。包括 new,runnable,blocked,waiting,timed waiting,terminatmed new至今尚未啟動的執...