進程如同數字世界中的生命體,誕生時被系統母體賦予初始資源,在CPU的脈搏中呼吸,于內存的疆域里生長。它睜開線程之眼觀察世界,伸出系統調用之手與環境互動,時而如幼童般單純執行指令,時而如哲人般陷入阻塞沉思。當時間片如春雨灑落便舒展枝椏,遭遇死鎖風暴則蜷縮休眠。最終在exit的凋零中歸還所有記憶,化作進程列表里一道轉瞬即逝的微光,完成從二進制胚胎到硅基消亡的完整輪回。
內核定義的進程狀態
在 include/linux/sched.h 文件中對進程的狀態進行了具體的定義,如下所示:
/* Used in tsk->state: */
#define TASK_RUNNING 0x0000
#define TASK_INTERRUPTIBLE 0x0001
#define TASK_UNINTERRUPTIBLE 0x0002
#define __TASK_STOPPED 0x0004
#define __TASK_TRACED 0x0008
/* Used in tsk->exit_state: */
#define EXIT_DEAD 0x0010
#define EXIT_ZOMBIE 0x0020
#define EXIT_TRACE (EXIT_ZOMBIE | EXIT_DEAD)
/* Used in tsk->state again: */
#define TASK_PARKED 0x0040
#define TASK_DEAD 0x0080
#define TASK_WAKEKILL 0x0100
#define TASK_WAKING 0x0200
#define TASK_NOLOAD 0x0400
#define TASK_NEW 0x0800
/* RT specific auxilliary flag to mark RT lock waiters */
#define TASK_RTLOCK_WAIT 0x1000
#define TASK_STATE_MAX 0x2000
這些狀態可以分為以下三類 :
1. 運行與睡眠狀態
狀態 | 值(十六進制) | 描述 |
---|---|---|
TASK_RUNNING | 0x0000 | 進程正在運行(CPU 執行)或就緒(在運行隊列中等待調度)。 |
TASK_INTERRUPTIBLE | 0x0001 | 可中斷睡眠:進程因等待資源(如 I/O、信號量)被阻塞,但可被信號或事件喚醒。 |
TASK_UNINTERRUPTIBLE | 0x0002 | 不可中斷睡眠:進程因關鍵操作(如磁盤 I/O)被阻塞,不可被信號喚醒。需謹慎使用。 |
__TASK_STOPPED | 0x0004 | 進程被信號(如?SIGSTOP 、SIGTSTP )暫停,直到收到?SIGCONT ?恢復。 |
__TASK_TRACED | 0x0008 | 進程被調試器(如?ptrace )跟蹤,通常與?STOPPED ?聯合出現。 |
TASK_PARKED | 0x0040 | 進程主動休眠(如內核線程),需通過特定喚醒機制恢復。 |
TASK_DEAD | 0x0080 | 進程正在結束,資源尚未完全釋放(與?EXIT_DEAD ?配合使用)。 |
TASK_WAKEKILL | 0x0100 | 附加標志:允許致命信號(如?SIGKILL )喚醒處于?INTERRUPTIBLE/UNINTERRUPTIBLE ?的進程。 |
TASK_WAKING | 0x0200 | 臨時狀態:進程正在從睡眠狀態轉移到運行隊列。 |
狀態轉換
-
運行 → 睡眠:因等待資源(如?
TASK_INTERRUPTIBLE
)或主動暫停(如?__TASK_STOPPED
)。 -
睡眠 → 運行:被事件喚醒(如 I/O 完成)或收到信號(如?
SIGCONT
)。
不可中斷睡眠(UNINTERRUPTIBLE)
常見于磁盤 I/O 或內核關鍵路徑,無法通過?kill
?終止,需解決底層阻塞問題。
調試相關狀態
__TASK_TRACED
?和?__TASK_STOPPED
?用于調試器(如?gdb
)或 shell 作業控制(如?jobs
)。
2. 退出狀態
狀態 | 值(十六進制) | 描述 | |
---|---|---|---|
EXIT_ZOMBIE | 0x0020 | 僵尸進程:進程已終止,但父進程尚未通過?wait() ?回收其資源(如 PID、退出狀態)。 | |
EXIT_DEAD | 0x0010 | 徹底退出:進程資源已完全釋放,是退出過程的最終狀態。 | |
EXIT_TRACE | 0x0030 | 被調試進程的退出狀態(`ZOMBIE | DEAD`)。 |
退出流程:進程終止后先變為?EXIT_ZOMBIE
,父進程回收后轉為?EXIT_DEAD
。
僵尸進程:若父進程未調用?wait()
,子進程會長期保持?EXIT_ZOMBIE
,占用內核資源。
3. 其他輔助狀態
狀態 | 描述 |
---|---|
TASK_NOLOAD | 進程不參與系統負載計算(如某些內核線程)。 |
TASK_NEW | 進程剛創建,尚未完全初始化。 |
TASK_RTLOCK_WAIT | 進程正在等待實時(RT)互斥鎖(用于實時調度策略)。 |
結構體中狀態的定義
struct task_struct
?中的?unsigned int __state
?成員是用來標記進程狀態的核心字段,它存儲了進程的當前狀態標志(如?TASK_RUNNING
、TASK_INTERRUPTIBLE
?等)
struct task_struct {
...
unsigned int __state;
...
}
打印進程狀態(內核態)
通過 current 宏打印當前進程的狀態,再通過dmesg進行查看
struct task_struct *current_task = current;
printk(KERN_INFO "Current process state: %d\n", current_task->__state);
用戶態進程狀態
ps
?通過解析?/proc/<pid>/status
?或?/proc/<pid>/stat
?獲取進程的狀態,顯示為單字母縮寫,僅反映內核狀態的子集:
ps ?狀態 | 含義 | 對應的內核狀態 |
---|---|---|
R | Running (運行/就緒) | TASK_RUNNING |
S | Interruptible Sleep | TASK_INTERRUPTIBLE (可中斷睡眠) |
D | Uninterruptible Sleep | TASK_UNINTERRUPTIBLE (不可中斷睡眠,通常因等待磁盤 I/O 或內核鎖) |
Z | Zombie | EXIT_ZOMBIE |
T | Stopped | __TASK_STOPPED (如通過?SIGSTOP ?暫停) |
t | Tracing stop | __TASK_TRACED (被調試器跟蹤,如?gdb ) |
X | Dead (已退出) | EXIT_DEAD (極少在?ps ?中看到,因進程已完全退出) |
I | Idle (空閑線程) | 內核線程的特殊狀態(無直接對應標志,可能結合?TASK_RUNNING ?和?TASK_NOLOAD ) |
P ?/?W | Parked / Waking | TASK_PARKED ?或?TASK_WAKING (某些內核版本支持) |
內核態 VS 用戶態
維度 | 內核狀態 | ps ?狀態 |
---|---|---|
表示方式 | 位掩碼(多狀態組合) | 單字母縮寫(互斥狀態) |
粒度 | 細粒度(支持復合狀態) | 粗粒度(簡化映射) |
退出狀態 | 明確區分?EXIT_ZOMBIE ?和?EXIT_DEAD | 僅顯示?Z (僵尸)或?X (徹底退出極少見) |
調試狀態 | 單獨標記?__TASK_TRACED | 顯示為?t (與?T ?區分) |
實時狀態 | 支持?TASK_RTLOCK_WAIT ?等擴展標志 | 無直接對應 |
用戶友好性 | 面向內核開發者 | 面向系統管理員/開發者 |
-
內核狀態:豐富、細粒度,用于調度和資源管理。
-
ps
?狀態:簡化、用戶友好,覆蓋常見場景。 -
關鍵區別:
ps
?隱藏了復合狀態和部分擴展標志(如?TASK_WAKING
),但足以滿足日常監控需求。
示例分析
場景 1:進程因磁盤 I/O 阻塞
-
內核狀態:
__state = TASK_UNINTERRUPTIBLE | TASK_NOLOAD
(不可中斷睡眠 + 不計入負載) -
ps
?顯示:
D
(僅體現不可中斷睡眠)
場景 2:被調試的暫停進程
-
內核狀態:
__state = __TASK_STOPPED | __TASK_TRACED
-
ps
?顯示:
t
(優先顯示?TRACED
,而非?T
)
場景 3:僵尸進程
-
內核狀態:
exit_state = EXIT_ZOMBIE
,?__state = TASK_DEAD
-
ps
?顯示:
Z