參考:http://blog.csdn.net/gatieme/article/details/51383272linux
進程是處於執行期的程序以及它所管理的資源(如打開的文件、掛起的信號、進程狀態、地址空間等等)的總稱。注意,程序並非進程,實際上兩個或多個進程不只有可能執行同一程序,並且還有可能共享地址空間等資源。程序員
Linux內核經過一個被稱爲進程描述符的task_struct結構體來管理進程,這個結構體包含了一個進程所需的全部信息。它定義在include/linux/sched.h文件中。函數
談到task_struct結構體,是linux內核源碼中最複雜的一個結構體了,成員之多,佔用內存之大。spa
下面來慢慢介紹這些複雜成員.net
state域可以取5個互爲排斥的值(通俗一點就是這五個值任意兩個不能一塊兒使用,只能單獨使用)。系統中的每一個進程都必然處於以上所列進程狀態中的一種。debug
狀態調試 |
描述code |
TASK_RUNNINGblog |
表示進程要麼正在執行,要麼正要準備執行(已經就緒),正在等待cpu時間片的調度隊列 |
TASK_INTERRUPTIBLE |
進程由於等待一些條件而被掛起(阻塞)而所處的狀態。這些條件主要包括:硬中斷、資源、一些信號……,一旦等待的條件成立,進程就會從該狀態(阻塞)迅速轉化成爲就緒狀態TASK_RUNNING |
TASK_UNINTERRUPTIBLE |
意義與TASK_INTERRUPTIBLE相似,除了不能經過接受一個信號來喚醒之外,對於處於TASK_UNINTERRUPIBLE狀態的進程,哪怕咱們傳遞一個信號或者有一個外部中斷都不能喚醒他們。只有它所等待的資源可用的時候,他纔會被喚醒。這個標誌不多用,可是並不表明沒有任何用處,其實他的做用很是大,特別是對於驅動刺探相關的硬件過程很重要,這個刺探過程不能被一些其餘的東西給中斷,不然就會讓進城進入不可預測的狀態 |
TASK_STOPPED |
進程被中止執行,當進程接收到SIGSTOP、SIGTTIN、SIGTSTP或者SIGTTOU信號以後就會進入該 |
TASK_TRACED |
表示進程被debugger等進程監視,進程執行被調試程序所中止,當一個進程被另外的進程所監視,每個信號都會讓進城進入該狀態 |
其實還有兩個附加的進程狀態既能夠被添加到state域中,又能夠被添加到exit_state域中。只有當進程終止的時候,纔會達到這兩種狀態.
/* task state */
int exit_state;
int exit_code, exit_signal;
狀態 |
描述 |
EXIT_ZOMBIE |
進程的執行被終止,可是其父進程尚未使用wait()等系統調用來獲知它的終止信息,此時進程 |
EXIT_DEAD |
進程的最終狀態 |
而int exit_code, exit_signal;咱們會在後面進程介紹
TASK_KILLABLE:Linux 中的新進程狀態
如前所述,進程狀態 TASK_UNINTERRUPTIBLE 和 TASK_INTERRUPTIBLE 都是睡眠狀態。如今,咱們來看看內核如何將進程置爲睡眠狀態。
Linux 內核提供了兩種方法將進程置爲睡眠狀態。
將進程置爲睡眠狀態的普通方法是將進程狀態設置爲 TASK_INTERRUPTIBLE 或 TASK_UNINTERRUPTIBLE 並調用調度程序的 schedule() 函數。這樣會將進程從 CPU 運行隊列中移除。
•若是進程處於可中斷模式的睡眠狀態(經過將其狀態設置爲 TASK_INTERRUPTIBLE),那麼能夠經過顯式的喚醒呼叫(wakeup_process())或須要處理的信號來喚醒它。
•可是,若是進程處於非可中斷模式的睡眠狀態(經過將其狀態設置爲 TASK_UNINTERRUPTIBLE),那麼只能經過顯式的喚醒呼叫將其喚醒。除非萬不得已,不然咱們建議您將進程置爲可中斷睡眠模式,而不是不可中斷睡眠模式(好比說在設備 I/O 期間,處理信號很是困難時)。
當處於可中斷睡眠模式的任務接收到信號時,它須要處理該信號(除非它已被屏弊),離開以前正在處理的任務(此處須要清除代碼),並將 -EINTR 返回給用戶空間。再一次,檢查這些返回代碼和採起適當操做的工做將由程序員完成。
所以,懶惰的程序員可能比較喜歡將進程置爲不可中斷模式的睡眠狀態,由於信號不會喚醒這類任務。
但須要注意的一種狀況是,對不可中斷睡眠模式的進程的喚醒呼叫可能會因爲某些緣由不會發生,這會使進程沒法被終止,從而最終引起問題,由於唯一的解決方法就是重啓系統。一方面,您須要考慮一些細節,由於不這樣作會在內核端和用戶端引入 bug。另外一方面,您可能會生成永遠不會中止的進程(被阻塞且沒法終止的進程)。
如今,咱們在內核中實現了一種新的睡眠方法
Linux Kernel 2.6.25 引入了一種新的進程睡眠狀態,
狀態 描述
TASK_KILLABLE 當進程處於這種能夠終止的新睡眠狀態中,它的運行原理相似於 TASK_UNINTERRUPTIBLE,只不過能夠響應致命信號
它定義以下:
#define TASK_WAKEKILL 128 /** wake on signals that are deadly **/
/* Convenience macros for the sake of set_task_state */
#define TASK_KILLABLE (TASK_WAKEKILL | TASK_UNINTERRUPTIBLE)
#define TASK_STOPPED (TASK_WAKEKILL | __TASK_STOPPED)
#define TASK_TRACED (TASK_WAKEKILL | __TASK_TRACED)
換句話說,TASK_UNINTERRUPTIBLE + TASK_WAKEKILL = TASK_KILLABLE。
而TASK_WAKEKILL 用於在接收到致命信號時喚醒進程
新的睡眠狀態容許 TASK_UNINTERRUPTIBLE 響應致命信號
進程狀態的切換過程和緣由大體以下圖: