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

【Linux】Linux进程状态和僵尸进程:一篇看懂“进程在忙啥”

前言:欢迎各位光临本博客,这里小编带你直接手撕Make/Makefile (自动化构建),文章并不复杂,愿诸君耐其心性,忘却杂尘,道有所长!!!!

解释_chmod_命令_(3).gif

**🔥个人主页:IF’Maxue-CSDN博客

🎬作者简介:C++研发方向学习者

📖**个人专栏:
《C语言》
《C++深度学习》
《Linux》
《数据结构》
《数学建模》
**

⭐️人生格言:生活是默默的坚持,毅力是永久的享受。不破不立,远方请直行!

文章目录

    • 一、先搞懂:进程状态藏在哪?
    • 二、课本里的核心逻辑:3句话说透
    • 三、基础三态:运行、阻塞、挂起(大白话版)
      • 1. 运行态:“在工位上,要么干活要么等活”
      • 2. 阻塞态:“等材料,暂时离开工位”
      • 3. 挂起态:“工位不够,去临时仓库待着”
    • 四、内核小知识:用“链表”管进程
    • 五、Linux实际进程状态:逐个拆,附代码
      • 1. R状态:运行态(Running)
      • 2. S状态:可中断休眠(浅睡眠)
      • 3. T状态:暂停态(Stopped)
      • 4. t状态:断点态(Trace Stopped)
      • 5. D状态:不可中断休眠(深睡眠)
      • 6. Z状态:僵尸态(Zombie)
      • 7. X状态:死亡态(Dead)
    • 六、孤儿进程:爹跑了,谁管孩子?
      • 为啥要领养?
    • 七、总结:3个核心记牢

一、先搞懂:进程状态藏在哪?

进程不是“黑盒子”,它的所有信息——比如在干啥、代码存在哪、有啥权限——都记在一个叫task_struct的“档案本”里。而进程状态,就是这个档案本里的一个整数,像员工的“工作状态标签”,直接告诉操作系统“这进程现在能干活不”。

image.png

二、课本里的核心逻辑:3句话说透

不管啥操作系统,进程状态的底层逻辑都逃不开这3点(对应你放的课本截图):
image.png

  1. 进程不只有“跑”和“不跑”,有好几种状态;
  2. 状态能互相转——比如“等键盘输入”时会从“能跑”变“等着”,输入完又变回去;
  3. 只有“运行状态”的进程,才真正拿着CPU干活。

三、基础三态:运行、阻塞、挂起(大白话版)

咱们用“工厂干活”的例子理解,比硬记定义简单:

1. 运行态:“在工位上,要么干活要么等活”

操作系统里,每个CPU都有一个“调度队列”(像工厂的“待岗工位”),里面放的全是task_struct(进程档案本)。
只要进程在这个队列里,状态就是运行态(Running) ——不管是正在被CPU“叫去干活”,还是排队等CPU,都算运行态。

调度时,CPU会按规则(比如“先进先出”FIFO)从队列里挑一个档案本,找到对应的代码和数据,让它跑起来。
image.png

2. 阻塞态:“等材料,暂时离开工位”

比如你写了个带scanf的程序——运行后不敲键盘,进程就“卡住了”。这不是它偷懒,是它在等“键盘输入”这个“材料”,这就是阻塞。

操作系统怎么管这种情况?它会给每个硬件(键盘、磁盘、网卡)建个“设备档案”(struct device),档案里专门留了个“等待队列”——所有等这个硬件的进程,都会被移到这个队列里。
简单说:阻塞 = 进程档案本从“调度队列”挪到“硬件等待队列”,直到“材料”备好(比如你敲了键盘),再挪回调度队列。
image.png
image.png
image.png

3. 挂起态:“工位不够,去临时仓库待着”

如果内存实在不够(工厂工位满了),操作系统会把进程的“代码和数据”挪到磁盘(临时仓库),只留task_struct(档案本)在内存——这叫“阻塞挂起”(本来就在等材料,现在连工具都收起来了)。
要是内存还不够,连调度队列里的进程也会被挪去磁盘,叫“运行挂起”(本来在等活,现在先去仓库)。

不过不用记这么细——Linux里不细分挂起态,咱们重点看实际能用的状态就行。
image.png
image.png
image.png

四、内核小知识:用“链表”管进程

操作系统不是瞎管进程的,靠的是“链表”这种数据结构。Linux用的是list_head链表,特点很实用:

  • 每个task_struct里可以放多个list_head(像一个员工有多个“身份标签”);
  • 这样一个进程能同时属于多个链表——比如既在“进程组链表”,又在“调度队列链表”;
  • 想通过list_head找到完整的task_struct?靠“地址偏移”——知道list_head在档案本里的位置,就能算出整个档案本的地址。

简单说:进程状态切换,本质就是list_head在不同链表间“挪位置”,无非是增删查改的操作。
image.png
image.png
image.png
image.png
image.png
image.png

五、Linux实际进程状态:逐个拆,附代码

Linux的进程状态存在task_state_array里,咱们逐个讲,每个都给代码例子,跟着做就能看懂。

1. R状态:运行态(Running)

  • 特点:在调度队列里,要么正在跑,要么等CPU;不能被kill打断(想停它得等它自己出队列)。
  • 为啥有时查不到?比如printf这种操作太快,进程瞬间切到其他状态,得用“死循环不做IO”才能稳定抓到。

代码例子(抓R状态):

#include <stdio.h>
int main() {while(1); // 死循环,不做任何IO,一直待在调度队列return 0;
}
  • 操作步骤:
    1. 编译:gcc test.c -o test
    2. 后台运行(不占终端):./test &
    3. 查看状态:ps aux | grep test,会看到状态是R

image.png
image.png
image.png
image.png
(注:状态后的+表示“前台进程”,后台进程没有+

2. S状态:可中断休眠(浅睡眠)

  • 特点:等资源(键盘、文件),处于“浅睡”;能被kill命令打断(比如等输入时,kill一下就退出)。
  • 最常见的阻塞态,比如scanf等输入、读文件时都算S状态。

代码例子(抓S状态):

#include <stdio.h>
int main() {int a;scanf("%d", &a); // 等键盘输入,进程阻塞,状态变Sprintf("%d\n", a);return 0;
}
  • 操作步骤:
    1. 运行:./test,不输入任何内容;
    2. 另开终端查状态:ps aux | grep test,状态是S
    3. 测试kill:kill 进程号,进程会直接退出(S状态能被打断)。

image.png
image.png

3. T状态:暂停态(Stopped)

  • 特点:进程被“暂停”,既不在调度队列也不在等待队列;得用命令恢复kill -18)。
  • 触发方式:按ctrl+z暂停前台进程,或用kill -19手动暂停。

操作例子

  1. 运行上面的scanf程序:./test
  2. ctrl+z,终端提示“已暂停”;
  3. 查状态:ps aux | grep test,状态是T
  4. 恢复:kill -18 进程号,进程继续等输入;
  5. 再暂停:kill -19 进程号,变回T。

image.png

4. t状态:断点态(Trace Stopped)

  • 特点:只有调试时会出现!进程在断点处停下,比如gdb设断点后运行。

操作例子

  1. 用gdb调试:gdb ./test
  2. 设断点:b main(在main函数开头停);
  3. 运行:r
  4. 另开终端查状态:ps aux | grep test,状态是t

image.png
image.png

5. D状态:不可中断休眠(深睡眠)

  • 特点:等“关键资源”(比如磁盘IO),处于“深睡”;kill -9都杀不掉(怕打断磁盘操作导致数据损坏)。
  • 常见场景:用dd命令拷贝大文件时。

操作例子(抓D状态):

  1. 执行磁盘读写命令:dd if=/dev/zero of=/tmp/test bs=1G count=10(往/tmp写10G文件);
  2. 另开终端查状态:ps aux | grep dd,状态是D
  3. 试杀:kill -9 进程号,进程纹丝不动,直到磁盘操作完成才退出。

image.png
image.png

6. Z状态:僵尸态(Zombie)

  • 特点:子进程退出了,但父进程没“要它的退出信息”(比如退出码),只剩task_struct(档案本)在内存;不能被调度,也杀不掉(因为进程已经死了,只剩空壳)。
  • 风险:僵尸进程占内存,父进程一直不管就会“内存泄露”(尤其是开机就跑的常驻进程)。

代码例子(造僵尸进程):

#include <stdio.h>
#include <unistd.h>
int main() {pid_t pid = fork(); // 创建子进程if (pid == 0) {// 子进程:直接退出,没被回收printf("子进程PID:%d\n", getpid());return 0;} else if (pid > 0) {// 父进程:死循环,不回收子进程while(1) sleep(1); }return 0;
}
  • 操作步骤:
    1. 运行:./test
    2. 查状态:ps aux | grep test,会看到子进程状态是Z
    3. 解决办法:让父进程调用wait()回收,或杀掉父进程(子进程会被领养)。

image.png
(注:slab是Linux内核的内存分配机制,专门管理像task_struct这样的小对象,僵尸进程的task_struct就存在这里,不回收会占 slab 内存)
image.png

7. X状态:死亡态(Dead)

  • 特点:进程彻底退出,所有资源(代码、数据、task_struct)被OS回收;看不到这个状态(因为瞬间就没了),只是理论上的状态。

六、孤儿进程:爹跑了,谁管孩子?

如果父进程先退出,子进程没人管,就成了“孤儿进程”——这时候Linux会让1号进程领养它:

  • 新内核(比如Ubuntu、CentOS 7+):1号进程是systemd
  • 老内核:1号进程是init

为啥要领养?

怕孤儿进程退出后没人回收,变成僵尸进程,导致内存泄露。1号进程会负责“要它的退出信息”,相当于“福利院”。

代码例子(造孤儿进程):

#include <stdio.h>
#include <unistd.h>
int main() {pid_t pid = fork();if (pid == 0) {// 子进程:睡10秒,等父进程先退出printf("子进程PID:%d,当前父进程PID:%d\n", getpid(), getppid());sleep(10); printf("子进程现在父进程PID:%d\n", getppid()); // 会变成1return 0;} else if (pid > 0) {// 父进程:马上退出,不管子进程printf("父进程退出,PID:%d\n", getpid());return 0;}return 0;
}
  • 操作步骤:
    1. 运行:./test
    2. 父进程瞬间退出,子进程一开始的父进程是终端(比如bash);
    3. 10秒后,子进程的父进程变成1(被1号进程领养);
    4. 孤儿进程会变成后台进程,终端看不到它的输出(除非重定向)。

image.png
image.png
image.png
image.png
image.png
image.png

七、总结:3个核心记牢

  1. 进程状态本质:task_struct在不同链表间挪位置(调度队列、等待队列);
  2. Linux重点状态:R(跑)、S(浅睡等资源)、D(深睡杀不掉)、Z(僵尸要回收)、T(暂停);
  3. 孤儿/僵尸处理:孤儿找1号进程领养,僵尸靠父进程wait()回收,避免内存泄露。
http://www.xdnf.cn/news/20046.html

相关文章:

  • 基于OpenGL封装摄像机类:视图矩阵与透视矩阵的实现
  • 如何下载B站视频,去水印,翻译字幕
  • .Net程序员就业现状以及学习路线图(四)
  • 创建线程有哪几种方式
  • 【数字孪生核心技术】数字孪生有哪些核心技术?
  • Kubernetes(四):Service
  • HyperWorks许可服务器设置
  • 企业微信AI怎么用?食品集团靠它砍掉50%低效操作,答案就是选对企业微信服务商
  • ZeroMQ 编译 项目使用流程文档
  • Android 生命周期函数调用原理
  • 《计算机网络安全》实验报告一 现代网络安全挑战 拒绝服务与分布式拒绝服务攻击的演变与防御策略(3)
  • 2025年数学建模国赛参考论文发布
  • 从碎片化到一体化:Java分布式缓存的“三级跳”实战
  • Spring Security 深度学习(六): RESTful API 安全与 JWT
  • 服务器IP暴露被攻击了怎么办?
  • 微算法科技 (NASDAQ:MLGO)利用量子密钥分发QKD技术,增强区块链系统的抗攻击能力
  • 自动化运维-ansible中对roles的创建与使用
  • 数据无言,网关有声 耐达讯自动化RS485转Profinet让千年液位数据“开口说话”
  • 在VSCode中更新或安装最新版的npx和uv工具
  • 数码视讯TR100-OTT-G1_国科GK6323_安卓9_广东联通原机修改-TTL烧录包-可救砖
  • 容器的定义及工作原理
  • 【华为Mate XTs 非凡大师】麒麟芯片回归:Mate XTs搭载麒麟9020,鸿蒙5.1体验新境界
  • Java 21 虚拟线程微服务进阶实战:2 个企业级场景源码 + 底层调度原理 + 性能调优指南
  • 艾克斯图片转换器,不只图片压缩
  • 音响皇帝BO,牵手全球第一AR眼镜雷鸟,耳机党坐不住了?
  • Kafka 内存池MemoryPool 设计
  • 海盗王64位dx9客户端修改篇之五
  • 别再手工缝合API了!开源LLMOps神器LMForge,让你像搭积木一样玩转AI智能体!
  • 《sklearn机器学习——回归指标1》
  • Linux中的fork详解