【Linux】深入理解Linux进程(二):进程的状态

目录

一、Linux中的进程状态

R:运行态

S:休眠态(浅度休眠)

[D : 磁盘休眠态(深度休眠)](#D : 磁盘休眠态(深度休眠))

挂起状态

T:暂停状态

[X :终止态](#X :终止态)

[Z :🧟‍♀️僵尸状态](#Z :🧟‍♀️僵尸状态)

二、Linux中的进程优先级


一、Linux中的进程状态

进程在Linux中有以下几个状态

  1. R (running)
  2. S (sleeping)
  3. D (disk sleep)
  4. T (stopped)
  5. t (tracing stop)
  6. X (dead)
  7. Z (zombie)
R:运行态

表明进程要么是在运⾏中要么在运⾏队列⾥

演示一下,依旧makefile

mycode.c:

运行一下

R+ : 表示这个进程在前台运行,此时我们的bash就不运行了。

bash 复制代码
./mycode &

表示在后台运行,此时用 ps ajx | grep mycode

就显示 R 在后台运行,此时bash 依旧能相应我们的指令

kill -9 12183 只能这样杀掉进程了。


S:休眠态(浅度休眠)

在操作系统中有一种状态叫阻塞态,要等待资源的就绪才能运行的状态

Linux中的休眠态就是阻塞态。


D : 磁盘休眠态(深度休眠)

浅度休眠可以被唤醒也可以被kill (杀死)。

假如在内存中有一个进程向磁盘中做写入1GB数据,磁盘把数据拷贝到某个地方是要花时间的,此时这个进程就必须要在这里等。如果此时好巧不巧,内存资源严重不足,操作系统把这个进程都挂起了,还是不行,进程没有什么情况说明的话,操作系统会把这个进程干掉(操作系统是会杀进程的,比如windows中的闪退),此时磁盘的数据还没写成功,磁盘可能就直接把数据丢失了。

为了避免这种情况,这种进程就要向外界传达信息:任何人不能杀掉我这个进程,于是就有了D这种状态:不响应任何请求。

当然,当出现D这种状态的进程时,操作系统就已经要挂了。

同样Linux中的D也是阻塞态。


挂起状态

挂起状态在Linux中,用户是不可见的,由操作系统一手来操作的,用户不可知。


T:暂停状态

在 LInux当中,我们可以主动的暂停一个进程

bash 复制代码
kill -l
bash 复制代码
kill -19 PID 暂停一个进程
bash 复制代码
kill -18 cont  (continue) 继续一个进程

Stop状态与Sleep状态的区别:

T : 不一定是硬件上的资源的等待,包含了主观要求的等待

S : 是由于硬件上的等待

T : 也是一种阻塞状态。

T 状态的使用场景 : 代码的调试


X :终止态

这种进程会被放到一个垃圾回收的队列当中,操作系统就可以定期的把这个队列中的占用资源释放掉


Z :🧟‍♀️僵尸状态

当一个进程死亡的时候,它并不会立即进入dead的状态,也就是一个进程运行完了,它不会立即被放到垃圾♻️回收队列当中,而是先进入一个状态叫Z状态。

为什么 :

一个进程运行完了是要被检测的,要清楚这个进程当前的信息,还要把结果返回给它的父进程。

在这个,进程结束了,要等待父进程来关系这个进程,的过程中,这个进程的状态要标记为Z/僵尸状态。

进程一般退出的时候,如果父进程没有主动回收♻️子进程的信息,子进程会一直让自己处于Z状态,进程的相关资源尤其是task_struct 结构体不能被释放。

如果一个进程的资源一直不退,会导致内存泄露。

如果一个子进程在运行,但父进程掉了,子进程会有什么影响。

子进程的父进程会变成操作系统,此时这个子进程被称为孤儿进程。

:父子进程,父进程先退出,子进程的父进程会被改成1号进程(操作系统)父进程是1号进程----孤儿进程

该进程被系统领养!

一为什么要被领养???因为孤儿进程未来也会退出,也要被释放


二、Linux中的进程优先级

每个进程都要排队等待CPU的调度和执行,这里的排队就是进程之间的优先级。

进程和进程之间不是按固定的一个链表链接的。

想把一个进程放到哪个数据结构中去,就创建哪个数据结构的对象放到该进程的PCB中

把这个数据结构放到该进程的PCB中,这个数据结构也许是哈希表,或者链表,多叉树......., 只要有了这个数据结构,通过图示的方法,就能拿到该PCB的地址,就能访问PCB中的数据了。

在Linux中是怎么安排进程的优先级呢?

ps -l 是 Linux/Unix 系统中用于查看当前用户进程的常用命令,它会以长格式(Long Format)显示更详细的进程信息。

ps -l 是你排查"进程为什么卡住"、"谁占用了太多资源"时的首选工具。

字段 含义 说明
F Flags 进程标志(常为 0/4,4 表示 root 权限)
S STAT 进程状态(最重要,如 R=运行, S=睡眠, Z=僵尸)
UID User ID 进程所有者的用户 ID
PID Process ID 进程唯一标识符
PPID Parent PID 父进程 ID
PRI Priority 进程优先级(数值越小优先级越高)
NI Nice Value 友好值(用于调整优先级,-20 到 19)
SZ Size 占用内存大小(KB)
TTY Terminal 关联的终端设备
TIME CPU Time 累计占用 CPU 时间
CMD Command 启动进程的命令名

我们主要来看PRI ,NI 。

PRI的值越小越快被执行,PRI (new) = 80 + nice

所以调整进程的优先级,在Linux下,就是调整nice值。

nice 其取值范围是-20~19,可以把nice值当做优先级的修正值。

普通用户是不能更改的


操作系统是如何根据优先级进行调度的呢

优化后的文本:

系统维护两个指针数组:运行指针数组和等待指针数组。运行指针(二级指针)指向运行指针数组,等待指针(二级指针)指向等待指针数组。

由于进程优先级可能相同,相同优先级的进程的PCB会被链入同一个运行队列,不同优先级的进程则分别链入不同的运行队列。系统将预先划分好的40个不同优先级运行队列(同一个优先级的PCB被分在同一个小队列中)的头指针存入运行指针数组中。基于Linux内核的O(1)调度算法,通过位图机制判断指针数组中哪些位置的运行队列尚未执行,然后按优先级顺序依次执行这些队列。

我们的调度优先级就是开散列哈西表的优先级,在task_struct* runqueue[]数组中的下标就是某一小队列的优先级

每个进程都分配有时间片,当进程运行时间达到时间片设定值时,会被重新链入当前运行队列的末尾排队等待。

在执行过程中,若有新进程需要运行,为避免影响当前按优先级划分的运行队列的执行,这些新进程会被链入等待队列。等待队列同样按优先级划分,其头指针存入等待指针数组中。

当运行指针数组中的所有运行队列都执行完毕后,等待指针数组中已按优先级划分的运行队列就绪待执行。此时交换两个指针数组的角色(swap(&run,&wait)):运行指针指向原等待指针数组,等待指针指向原运行指针数组。这样原等待指针数组成为新的运行指针数组,原运行指针数组则转为等待指针数组。通过这种轮换机制,系统可以持续运行进程,同时保持进程优先级调度不受影响。


所有在runqueue中的PCB的状态都是R,它们会根据优先级被分散到不同的小队列中(task_struct * 数组中的不同下标数,依据数组下标的不同,我们从上到下访问PCB,就是按照优先级遍历。

调整优先级的本质就是把PCB链入到不同数组下标的队列中。

位置不同访问的优先级不同。


相关推荐
草莓熊Lotso1 小时前
Linux Socket 编程筑基:从底层本质到核心 API,一文吃透 Socket 预备知识
linux·运维·服务器·数据库·c++
hhb_6182 小时前
Terra常见技术问题梳理与实战应用案例解析
运维·服务器·网络
TimberWill2 小时前
git worktree实现分支管理
git
say_fall2 小时前
装软件慢到崩溃?用户创建总出错?Linux 工具避坑指南
linux·运维·服务器·c++·学习
嵌入式小杰2 小时前
一阶低通滤波入门教程:从原理到单片机 C 代码实现
c语言·开发语言·stm32·单片机·算法
叼烟扛炮2 小时前
C++ 知识点02 输入输出
开发语言·c++·算法·输入输出
qcx232 小时前
深度解析Deepseek V4:1M 上下文不是军备竞赛,是养 Agent 的人才知道的痛
java·开发语言
GZ_TOGOGO2 小时前
2026 年 RHCE 考试到底有哪些变化?给你盘盘干货
运维·rhce·rhce考试·rhce认证·it培训·rhce 10.0
小则又沐风a2 小时前
基础的开发工具(2)---Linux
java·linux·前端