Linux 进程状态:内核角度与应用层角度
Linux 进程状态:内核角度与应用层角度
目标:系统梳理 Linux 进程状态的内核定义、取值语义与应用层展示的关系;明确 ps/top/proc 的映射;说明常见状态转移与调试要点。
代码树:
kernel-4.4.94。
1. 内核角度:状态位与字符映射
- 概念:
task->state表示“可运行性”相关状态位;task->exit_state表示退出相关位。二者分离,避免误修改。
- 关键宏(
include/linux/sched.h):- 基本位:
TASK_RUNNING(0)、TASK_INTERRUPTIBLE(1)、TASK_UNINTERRUPTIBLE(2)、__TASK_STOPPED(4)、__TASK_TRACED(8)。 - 退出位:
EXIT_DEAD(16)、EXIT_ZOMBIE(32)、EXIT_TRACE(EXIT_ZOMBIE|EXIT_DEAD)。 - 扩展位:
TASK_DEAD(64)、TASK_WAKEKILL(128)、TASK_WAKING(256)、TASK_PARKED(512)、TASK_NOLOAD(1024),最大TASK_STATE_MAX(2048)。 - 组合便捷宏:
TASK_KILLABLE = TASK_WAKEKILL | TASK_UNINTERRUPTIBLETASK_STOPPED = TASK_WAKEKILL | __TASK_STOPPEDTASK_TRACED = TASK_WAKEKILL | __TASK_TRACEDTASK_IDLE = TASK_UNINTERRUPTIBLE | TASK_NOLOADTASK_NORMAL = TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLETASK_ALL = TASK_NORMAL | __TASK_STOPPED | __TASK_TRACED
- 报告集:
TASK_REPORT = TASK_RUNNING | TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE | __TASK_STOPPED | __TASK_TRACED | EXIT_ZOMBIE | EXIT_DEAD
- 基本位:
- 字符映射(
TASK_STATE_TO_CHAR_STR):"RSDTtXZxKWPN"- R: running
- S: sleeping(可中断睡眠)
- D: disk sleep(不可中断睡眠,通常是 I/O 等待)
- T: stopped
- t: tracing stop
- X: dead
- Z: zombie
- x/K/W/P/N:扩展/内部使用字符位,供调试/trace 映射(不同子系统可能裁剪显示)。
/proc映射(fs/proc/array.c:get_task_state()):- 以
TASK_REPORT为掩码,将state|exit_state映射到字符串数组:"R (running)"、"S (sleeping)"、"D (disk sleep)"、"T (stopped)"、"t (tracing stop)"、"X (dead)"、"Z (zombie)"。
TASK_PARKED单独处理:视为TASK_INTERRUPTIBLE(睡眠),避免误报为 running。
- 以
2. 应用层角度:ps/top/proc 的展示
ps -o state/top的状态字符一般对应TASK_STATE_TO_CHAR_STR的前七类(R/S/D/T/t/X/Z)。/proc/<pid>/status的State:行来自get_task_state(),显示为完整字符串(如S (sleeping))。tools/perf中的状态字符串可能有独立定义(例如builtin-sched.c中的TASK_STATE_TO_CHAR_STR),但语义与内核一致。
3. 常见状态语义与转移
- R(running):
- 任务在 CPU 上运行或可运行队列上等待调度;
state == 0。
- 任务在 CPU 上运行或可运行队列上等待调度;
- S(sleeping,可中断):
- 正在等待事件(如信号/条件);可被信号唤醒;
TASK_INTERRUPTIBLE。
- 正在等待事件(如信号/条件);可被信号唤醒;
- D(disk sleep,不可中断):
- 常见于设备 I/O 等不可中断等待;不会响应信号;
TASK_UNINTERRUPTIBLE。
- 常见于设备 I/O 等不可中断等待;不会响应信号;
- T(stopped):
- 被
SIGSTOP/SIGTSTP等信号停止或处于ptrace停止;__TASK_STOPPED。
- 被
- t(tracing stop):
- 由
ptrace等导致的跟踪停止;__TASK_TRACED。
- 由
- Z(zombie):
- 任务已退出但父进程尚未
wait回收;EXIT_ZOMBIE;/proc/<pid>仍存在。
- 任务已退出但父进程尚未
- X(dead):
- 将被彻底回收;
EXIT_DEAD;通常用户态看不到。
- 将被彻底回收;
- 其他内部位:
TASK_WAKING(即将被唤醒)、TASK_PARKED(kthread park)、TASK_NOLOAD(不计入 load)等用于调度器与内核态控制。
状态转移示例:
- R → S:
schedule()、wait_event()等进入可中断睡眠; - S/D → R:事件达成或
wake_up_process()唤醒; - R/S/D → T/t:收到停止/跟踪信号或进入
ptrace停止; - 任意 → Z:调用
do_exit(),执行退出流程,等待父回收; - Z → 移除:父进程
wait*()系列回收后,内核清理任务结构。
4. 调试与排查建议
- 长期处于 D(不可中断):
- 可能设备驱动/块层卡住;查看栈回溯(
echo t > /proc/sysrq-trigger或echo w > /proc/sysrq-trigger)与sched_debug,定位持锁点或 I/O;结合ftrace的block事件与perf trace。
- 可能设备驱动/块层卡住;查看栈回溯(
- 僵尸进程(Z)清理:
- 确认父进程是否正确
wait;若父丢失,init会接管并回收;检查父进程的SIGCHLD处理。
- 确认父进程是否正确
- 频繁切换 R/S:
- 正常活跃任务;若有抖动或负载异常,检查
CFS参数与抢占阈值(sched_wakeup_granularity)以及锁竞争。
- 正常活跃任务;若有抖动或负载异常,检查
- kthread parked:
- 属于内核线程管理行为,通常正常;
TASK_PARKED在/proc中映射为 S。
- 属于内核线程管理行为,通常正常;
5. 源码索引(4.4.94)
- 状态宏与字符:
include/linux/sched.h(TASK_*、TASK_STATE_TO_CHAR_STR)。 /proc映射:fs/proc/array.c:get_task_state()。- 调度器使用:
kernel/sched/core.c(state_to_char引用、状态统计)。 - trace 输出:
kernel/trace/trace_output.c(state_to_char[])。 - perf 工具:
tools/perf/builtin-sched.c的状态表。
6. 小结
- 内核将进程状态设计为位图集,以便组合表达可运行性与退出等不同维度;应用层以字符或字符串方式展示主要状态。
- 正确理解 S/D/T/t/Z 的语义与转移,有助于定位性能瓶颈(I/O 卡顿、锁竞争)、功能问题(僵尸进程、停止/跟踪状态)与调度行为。
7. 状态转换图(更清晰的可视描述)
说明:以下为 Mermaid 状态图。
7.1 总览转换图
图例:
- Running=R、Sleeping=S、DiskSleep=D、Stopped=T、TracingStop=t、Zombie=Z。
