Linux进程状态转换详解

Linux 内核将进程状态存储在 task_struct 结构体中的 state 字段(一个位图),通过 ps、top、**/proc/pid/status** 等命令可查看(STAT 列)。Linux 的进程状态主要为 R、S、D、T、Z、X(加上可能的前缀标记,如 +、l 等)。


1. Linux进程状态定义

状态码 英文含义 中文含义 说明
R TASK_RUNNING 可执行/运行状态 进程正在 CPU 上运行,或已就绪等待调度
S TASK_INTERRUPTIBLE 可中断睡眠状态 等待事件(如 I/O、信号),可被信号唤醒
D TASK_UNINTERRUPTIBLE 不可中断睡眠状态(Disk Sleep) 等待硬件 I/O(如磁盘、网络),不可被信号打断(kill 无效)
T TASK_STOPPED / TASK_TRACED 暂停/跟踪停止状态 被 SIGSTOP/SIGTSTP 暂停,或被 ptrace 跟踪
Z EXIT_ZOMBIE 僵尸进程状态 进程已退出,但父进程未回收资源(等待 wait())
X EXIT_DEAD 死亡状态 进程即将被完全销毁(短暂,几乎不出现)

其他前缀标记(常见于 STAT 列):

  • +:前台进程
  • l:多线程进程
  • s:会话领导者

2. 进程状态转换图(有限状态机)

077b63df96b2e316a9616f96eb3233e7.png

主要转换路径(实际内核代码中可组合):

  • 创建:fork/clone/vfork/kernel_thread 后进入 R(或 CLONE_STOPPED 时进入 T)。
  • R → S:等待资源(如 sleep()、read() 等待 I/O、等待信号)。
  • S → R:事件完成(I/O 就绪、信号唤醒)或调度器选择。
  • R → D:发起不可中断 I/O 操作(磁盘/网络同步调用)。
  • R → T:收到 SIGSTOP / Ctrl+Z 或被 ptrace 跟踪。
  • T → R:收到 SIGCONT(或调试器 ptrace)。
  • R → Z:子进程 exit(),父进程未调用 wait()。
  • Z → X:父进程 wait() 回收后彻底释放。

Linux 实际运行态(R)是“可运行”而非“正在运行”,多个进程可处于 R(就绪队列)。

3. 排查示例

1
2
3
4
5
6
7
8
9
10
11
12
13
# 1. 查看单个进程状态
ps -o pid,ppid,state,comm -p 1234 # 或 ps -o stat= -p 1234

# 2. 批量查看(top/ps/top 命令)
ps aux | head -n 20
top -b -n 1 | head -n 20

# 3. /proc 伪文件(最直接)
cat /proc/1234/status | grep State # 输出如: State: S (sleeping)

# 4. 查看僵尸进程(Z)
ps aux | grep '[Z]'
# 常见解决:pkill -9 父进程ID 或 kill -9 父进程(init 会自动收尸)

4.场景分析

  • D 状态(常见于 NFS/SAN 磁盘故障):kill -9 无效,需要修复硬件或重启系统。
  • Z 状态:父进程未回收(忘记 wait()),占少量资源,可通过 pstree -p 查看父子关系。
  • S 状态:正常现象(绝大多数进程都在这里等待)。