进程状态:Linux的幕后指挥管理,穿越操作系统进程的静与动

📅 发布时间:2026/7/6 17:15:40 👁️ 浏览次数:
进程状态:Linux的幕后指挥管理,穿越操作系统进程的静与动
一、操作系统中的进程状态概述操作系统中的进程状态是进程在生命周期中可能处于的不同状态。这些状态帮助操作系统识别进程的运行情况并在不同状态间进行合理的资源分配。操作系统中的经典进程状态包括就绪、运行、阻塞和终止。1.1 经典的进程状态模型典型的操作系统中进程状态可以分为以下几种在这里插入图片描述在这种经典模型中进程会在不同状态之间流转。具体来说就绪 - 运行CPU调度器分配CPU给就绪状态的进程。 运行 - 阻塞进程等待I/O或其他资源时进入阻塞状态。 阻塞 - 就绪等待的条件满足后进程重新进入就绪队列等待CPU调度。 运行 - 终止进程执行完毕或异常终止进入终止状态。1.2 进程状态转换图在这里插入图片描述该图展示了一个经典进程状态的转换流程。箭头表示进程状态转换的可能路径。二、Linux操作系统中的进程状态Linux操作系统在经典的进程状态基础上进行了一系列扩展允许内核更细粒度地控制进程尤其是当系统资源紧张或多任务并发性很高时。Linux内核中的进程状态可以使用ps命令或读取/proc文件系统来查看进程的状态信息。2.1 Linux进程状态的分类在这里插入图片描述在进程的task_struct结构体中state字段用来表示进程的当前状态。根据内核中的定义不同状态的进程会被挂载在不同的等待队列上以实现细粒度的调度与控制。而在我们 Linux 中新建、就绪、运行都可以看作 运行R这一个状态所以比较清晰在这里插入图片描述2.2 各状态的详细解释TASK_RUNNING进程正在运行或准备运行。它可以被调度器分配到CPU执行。TASK_RUNNING的进程始终是就绪队列的一部分。TASK_INTERRUPTIBLE进程处于可中断等待状态等待某一条件满足。进程在此状态下可以被信号唤醒。关于信号的知识我们在后面会讲TASK_UNINTERRUPTIBLE进程处于不可中断的等待状态。这通常用于等待特定资源例如设备I/O操作完成。进程在此状态下不会被信号打断即便外部发送信号也不会响应。TASK_STOPPED进程被暂停通常是由于接收到SIGSTOP信号或调试器干预等待继续或恢复信号。TASK_TRACED进程被调试工具如gdb跟踪和控制。此状态下的进程会暂停直到调试器进一步控制。EXIT_DEAD进程终止后进入清理阶段等待系统回收资源EXIT_ZOMBIE进程已结束系统未回收其资源。僵尸进程会保留在系统中直到其父进程调用wait()系统调用收集它的退出状态。TASK_DEAD表示进程已彻底结束系统已回收其所有资源。2.3 Linux进程状态表在这里插入图片描述2.4 使用ps查看进程状态在Linux系统中可以通过ps命令查看进程的状态代码语言javascriptAI代码解释ps -aux在这里插入图片描述ps命令会显示每个进程的详细信息其中状态列标记着每个进程的状态。状态的含义如下R : 运行或就绪状态S可终止等待D 不可终止等待Z 僵尸进程等待回收X终止死亡进程T 停止状态我们也可以通过ps命令查看某个指定的进程的信息代码语言javascriptAI代码解释ps axj | grep 进程名字三、进程状态具体分析️运行 R首先来看看第一种状态 R 以我们以往的认知来说一个程序在运行就表示该 进程 处于 运行 状态那么事实真的如此吗先来看看下面这段代码代码语言javascriptAI代码解释#includeiostream using namespace std; #includeunistd.h #includesys/types.h int main() { while(1) { cout Im a process, my PID is: getpid() endl; sleep(1); } return 0; }当前makefile文件为代码语言javascriptAI代码解释myProcess:test.cpp g -o myProcess test.cpp .PHONY:catPI catPI: ps ajx | head -1 ps ajx | grep myProcess | grep -v grep .PHONY:clean clean: rm -r myProcess通过make catPI指令调用 Makefile 中提前设定好的指令查看当前进程信息在这里插入图片描述可以看到当前的进程状态为睡眠 S注 表示当前进程在前台运行中进程 难道没有运行吗 运行了但我们 很难捕捉到 对于 CPU 来说将这么简单的一句话输出到屏幕上是一件很小的事可能几毫秒就完成了 而其他大多数时间进程 都在外设等待队列中 排队 当我们将打印语句和睡眠语句屏蔽后进程 不用在等待队列中 排队 CPU 就一直在处理死循环此时可以观察到 运行R 状态在这里插入图片描述️睡眠 S睡眠 S 的本质就是进程阻塞表示此时进程因等待某种资源而暂停运行睡眠 S 又称为可中断休眠当 进程 等待时间过长时我们可以手动将其关闭应用卡死后强制关闭也是这个道理在这里插入图片描述还有一种方式终止进程killkill -9 PID终止进程当进程在后台运行时状态不加 我们是无法通过 ctrlc 终止的但kill指令可以终止️休眠 D还存在一种特殊睡眠状态休眠 D休眠 又被称为不可中断休眠顾名思义休眠 D 状态下的 进程 是无法终止的kill 指令和 OS都无能为力只能默默等待 进程阻塞 结束拿到资源了进程 才会停止 休眠 D 状态终止 休眠 D 进程的一个方法就是切断电源此时进程是结束了但整个系统也结束了️暂停 T我们还可以使 进程 进入暂停 T状态kill -19 PID 暂停进程kill -18 PID 恢复进程在输入暂停指令后进程进进入暂停状态在这里插入图片描述在这里插入图片描述我们可以通过 kill -18 PID 使 进程 恢复运行恢复后的 进程 在后台运行可以看到恢复后进程继续执行并且状态由T变为S在这里插入图片描述注意 进程 在后台运行时是无法通过ctrlc·指令终止的只能通过kill -9 PID终止在 gdb 中调试代码时打断点实际上就是 使 进程 在指定行暂停运行此时 进程 处于 追踪暂停状态 t在这里插入图片描述在这里插入图片描述️死亡 X当进程被终止后就处于死亡 X 状态死亡状态是无法在任务列表中观察到的死亡 X 状态只是一个返回状态️僵尸 Z与死亡状态相对应的还有一个僵尸 Z 状态通俗来说僵尸状态 是给 父进程 准备的当 子进程 被终止后会先维持一个 僵尸 状态方便 父进程 来读取到 子进程 的- 退出结果然后再将 子进程 回收单纯的在 bash 环境下终止 子进程是观察不到 僵尸状态 的因为 bash 会执行回收机制将 僵尸 回收我们可以利用 fork() 函数自己创建 父子进程 关系观察到这一现象代码示例如下代码语言javascriptAI代码解释#includeiostream using namespace std; #includeunistd.h #includesys/types.h int main() { pid_t ret fork(); if(ret 0) { while(1) { cout Im son process, my PID: getpid() PPID: getppid() endl; sleep(1); } } else if(ret 0) { while(1) { cout Im father process, my PID: getpid() PPID: getppid() endl; sleep(1); } } else { while(1) { cout Make son process fail! endl; sleep(1); } } return 0; }此时进程开始执行在这里插入图片描述此时父子进程都处于常规睡眠状态在这里插入图片描述此时输入指令kill -9 PID即kill -9 1007716终止 子进程 再次查看进程状态在这里插入图片描述僵尸进程如果不被回收会导致内存泄漏问题和标识符占用问题孤儿进程孤儿进程是一种特殊的进程状态通过程序创建 父子进程通过指令终止 父进程此时 子进程 会被OS领养子进程 的 父进程 变为1号进程子进程 就变成了一个孤儿进程同样执行上述代码起初都正常运行在这里插入图片描述现在我们消灭父进程观察其执行结果和运行状态在这里插入图片描述可以看到子进程被1号进程领养在这里插入图片描述假设子进程不被1号进程领养子进程退出时就会无人回收成为一只游离的僵尸僵尸进程有 内存泄漏 的风险因此子进程会被OS领养总结进程状态的舞蹈Linux操作系统中的进程状态不仅仅是抽象的计算机术语它们是系统中每个进程生命周期的具体体现。正如一场精彩的舞蹈每个进程都有自己的节奏和步伐它们或快速跃动或缓慢舞动或瞬间消失而每个转变都与操作系统对资源的调度和管理息息相关。通过理解进程状态与状态转变的过程我们能够更好地把握Linux系统的脉搏掌握进程管理与调度的奥秘。这不仅是操作系统中的技术问题更是数字世界中的一场优雅的舞蹈。本篇关于进程状态的介绍就暂告段落啦希望能对大家的学习产生帮助欢迎各位佬前来支持斧正​​​​​​​