当前位置: 首页 > article >正文

内核编程十三:进程状态详解

进程如同数字世界中的生命体,诞生时被系统母体赋予初始资源,在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_RUNNING0x0000进程正在运行(CPU 执行)或就绪(在运行队列中等待调度)。
TASK_INTERRUPTIBLE0x0001可中断睡眠:进程因等待资源(如 I/O、信号量)被阻塞,但可被信号或事件唤醒。
TASK_UNINTERRUPTIBLE0x0002不可中断睡眠:进程因关键操作(如磁盘 I/O)被阻塞,不可被信号唤醒。需谨慎使用。
__TASK_STOPPED0x0004进程被信号(如 SIGSTOPSIGTSTP)暂停,直到收到 SIGCONT 恢复。
__TASK_TRACED0x0008进程被调试器(如 ptrace)跟踪,通常与 STOPPED 联合出现。
TASK_PARKED0x0040进程主动休眠(如内核线程),需通过特定唤醒机制恢复。
TASK_DEAD0x0080进程正在结束,资源尚未完全释放(与 EXIT_DEAD 配合使用)。
TASK_WAKEKILL0x0100附加标志:允许致命信号(如 SIGKILL)唤醒处于 INTERRUPTIBLE/UNINTERRUPTIBLE 的进程。
TASK_WAKING0x0200临时状态:进程正在从睡眠状态转移到运行队列。

状态转换

  • 运行 → 睡眠:因等待资源(如 TASK_INTERRUPTIBLE)或主动暂停(如 __TASK_STOPPED)。

  • 睡眠 → 运行:被事件唤醒(如 I/O 完成)或收到信号(如 SIGCONT)。

不可中断睡眠(UNINTERRUPTIBLE)

常见于磁盘 I/O 或内核关键路径,无法通过 kill 终止,需解决底层阻塞问题。

调试相关状态

__TASK_TRACED 和 __TASK_STOPPED 用于调试器(如 gdb)或 shell 作业控制(如 jobs)。


2. 退出状态

状态值(十六进制)描述
EXIT_ZOMBIE0x0020僵尸进程:进程已终止,但父进程尚未通过 wait() 回收其资源(如 PID、退出状态)。
EXIT_DEAD0x0010彻底退出:进程资源已完全释放,是退出过程的最终状态。
EXIT_TRACE0x0030被调试进程的退出状态(`ZOMBIEDEAD`)。

退出流程:进程终止后先变为 EXIT_ZOMBIE,父进程回收后转为 EXIT_DEAD

僵尸进程:若父进程未调用 wait(),子进程会长期保持 EXIT_ZOMBIE,占用内核资源。


3. 其他辅助状态

状态描述
TASK_NOLOAD进程不参与系统负载计算(如某些内核线程)。
TASK_NEW进程刚创建,尚未完全初始化。
TASK_RTLOCK_WAIT进程正在等待实时(RT)互斥锁(用于实时调度策略)。

结构体中状态的定义

struct task_struct 中的 unsigned int __state 成员是用来标记进程状态的核心字段,它存储了进程的当前状态标志(如 TASK_RUNNINGTASK_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 状态含义对应的内核状态
RRunning (运行/就绪)TASK_RUNNING
SInterruptible SleepTASK_INTERRUPTIBLE(可中断睡眠)
DUninterruptible SleepTASK_UNINTERRUPTIBLE(不可中断睡眠,通常因等待磁盘 I/O 或内核锁)
ZZombieEXIT_ZOMBIE
TStopped__TASK_STOPPED(如通过 SIGSTOP 暂停)
tTracing stop__TASK_TRACED(被调试器跟踪,如 gdb
XDead (已退出)EXIT_DEAD(极少在 ps 中看到,因进程已完全退出)
IIdle (空闲线程)内核线程的特殊状态(无直接对应标志,可能结合 TASK_RUNNING 和 TASK_NOLOAD
P / WParked / WakingTASK_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


http://www.kler.cn/a/601195.html

相关文章:

  • React 知识回顾(HOC、合成事件、Fiber)
  • 【数据结构进阶】位图
  • Python Sanic面试题及参考答案
  • 手动创建kkFileView4.4.0镜像
  • 嵌入式八股RTOS与Linux--hea4与TLSF篇
  • 算法题(107):function
  • ARM异常处理流程与中断机制总结,与常见丢中断情况
  • 【服务器环境安装指南-指定 cuda 版本】在 Ubuntu 22.04 上完成 cuda-toolkit 12.0 和 cudnn 12.x 的安装教程
  • 风格混合增强的解纠缠学习在医学图像分割的无监督域自适应中的应用|文献速递-医学影像人工智能进展
  • 程序化广告行业(31/89):人群分类与广告投放策略全解析
  • 沪深300股指期货的看涨看跌方式是怎样的?
  • 【鸿蒙开发】第五十一章 Camera Kit(相机服务)
  • ragflow安装es报错怎么办
  • 云原生进化:架构现代化的核心引擎
  • 优先级与环境变量的艺术:驾驭 Linux 系统的核心
  • 鸿蒙入门——ArkUI 跨页面数据同步和应用全局单例的UI状态存储AppStorage 小结(三)
  • 贪心算法——思路与例题
  • 华为云助力数字化转型
  • 第一天学爬虫
  • 【干货,实战经验】nginx缓存问题