【Linux篇】进程状态(僵尸进程,孤儿进程),优先级与调度机制

news2025/3/14 5:46:12

📌 个人主页: 孙同学_
🔧 文章专栏:Liunx
💡 关注我,分享经验,助你少走弯路!
在这里插入图片描述

文章目录

    • 1. 前文铺垫
      • 理解内核链表
    • 2. 进程状态
      • 2.1 进程状态查看
      • 2.2 僵尸进程
      • 2.3 僵尸进程危害
      • 2.4 孤儿进程
    • 3. 进程优先级
      • 3.1 概念
      • 3.2 查看系统进程
      • 3.3 查看进程优先级的命令
      • 3.4 补充概念-竞争、独立、并行、并发
    • 4. 进程切换
    • 5.Linux2.6内核进程O(1)调度队列

1. 前文铺垫

进程状态是task_struct内的一个整数;进行:进程在调度队列中,进程的状态都是running,阻塞:等待某种设备或者资源就绪。进程是一个队列,设备也是一个队列,当我们读磁盘,读网卡的时候,如果对应设备未就绪那么进程就要阻塞等待了。进程状态变化的表现之一就是要在不同的队列中进行流动,本质都是数据结构的增删查改!

理解内核链表

在这里插入图片描述
如果一个类里面有多个next,prve,那么就可以把任何一个task_struct即属于运行队列,又属于全局链表,还可以把它放到二叉树中等。
在这里插入图片描述

2. 进程状态

一个进程可以有几个状态(在Linux内核里,进程有时候也叫做任务)。

  • 下面的状态在kernel源代码里定义:
/*
*The task state array is a strange "bitmap" of
*reasons to sleep. Thus "running" is zero, and
*you can test for combinations of others with
*simple bit tests.
*/
static const char *const task_state_array[] = {
 "R (running)", /*0 */
 "S (sleeping)", /*1 */
 "D (disk sleep)", /*2 */
 "T (stopped)", /*4 */
 "t (tracing stop)", /*8 */
 "X (dead)", /*16 */
 "Z (zombie)", /*32 */
};
  1. R 运行或可运行 (Running 或 Runnable)
  • 状态描述: 进程正在CPU上执行,或在运行队列中等待调度。
  • 触发场景: 进程处于活动状态,正在执行或准备执行。
  1. S 可中断睡眠(Interruptible Sleep)
  • 状态描述: 进程在等待事件完成(如I/O操作、信号),可被信号中断。
  • 触发场景: 例如调用 sleep()read() 等阻塞操作时。
  1. D 不可中断睡眠(Uninterruptible Sleep)
  • 状态描述: 进程等待不可中断的操作(如硬件I/O),不响应信号。
  • 触发场景: 常见于磁盘I/O或某些内核操作,需等待操作完成。
  1. T 停止(Stopped)
  • 状态描述: 进程被信号(如 SIGSTOPSIGTSTP)暂停,需 SIGCONT 恢复。
  • 触发场景: 手动暂停进程(如按 Ctrl+Z)或调试时。
  1. Z 僵尸(Zombie)
  • 状态描述: 进程已终止,但父进程未调用 wait() 回收资源。
  • 触发场景: 父进程未正确处理子进程退出,导致残留进程描述符。
  1. t 追踪状态(Tracing Stop)
  • 状态描述: 进程被调试器(如 gdb)跟踪时暂停,属于停止状态的一种。
  • 触发场景: 调试器设置断点或单步执行时。
  1. X 死亡(Dead)
  • 状态描述: 子进程结束之后,父进程获取子进程信息之前。
  • 触发场景: 父进程已回收子进程状态,短暂存在后消失。

2.1 进程状态查看

命令: ps aux / ps axj

a: 用于显示所有用户的进程,包括其他用户的进程(需要适当的权限)。默认情况下,ps 只显示当前用户的进程。
例如:ps a

x: 用于显示没有控制终端的进程。这些进程通常是后台运行的守护进程(daemon)。
例如:ps x
通常,ax 选项一起使用,以显示所有用户的所有进程,无论它们是否有控制终端。
例如:ps ax

j: 用于显示与作业控制相关的信息,包括进程组ID(PGID)、会话ID(SID)、父进程ID(PPID),以及作业号(如果有的话)。
例如:ps j
这对于理解进程如何分组和作业控制很有帮助。

u : 用于以用户为中心的格式显示进程信息。它提供了每个进程的详细信息,如用户、CPU使用率、内存使用率、虚拟内存大小、驻留内存大小、控制终端、进程状态、启动时间、CPU时间和命令行。
例如:ps u
通常,u 选项与 aux 一起使用,以显示所有用户的详细进程信息。
例如:ps aux

2.2 僵尸进程

在这里插入图片描述

  • 僵死状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程(使用wait()系统调用)没有读取到子进程退出的返回代码时就会产生僵死(尸)进程。
  • 僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。
  • 只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态。

2.3 僵尸进程危害

  • 进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程),你交给我的任务,我
    办的怎么样了。可父进程如果一直不读取,那子进程就一直处于Z状态?是的!
  • 维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话说,Z状态⼀直不退出,PCB一直都要维护?是的!
  • 那一个父进程创建了很多子进程,就是不回收,是不是就会造成内存资源的浪费?是的!因为数据结构对象本身就要占用内存,C语言中定义一个结构体变量(对象),是要在内存的某个位置进行开辟空间,那就会存在内存泄漏?是的!
    如何避免呢?我们后期讲。

2.4 孤儿进程

  1. 我们先来创建一段代码
    在这里插入图片描述
  2. 代码运行后,子进程一直运行,父进程运行5秒后退出
    在这里插入图片描述
  3. 这个1号进程是谁呢?top一下,我们可以看到它是systemd
    在这里插入图片描述
  4. 我们继续查一下这个systemd
    在这里插入图片描述
  5. 为什么子进程会被1(systemd)号进程领养呢?如果不领养会出现什么问题呢?
    答案是如果不被领养,那么这个子进程就进入僵尸进程,有可能会造成内存泄漏
  6. 父进程为什么不会变成孤儿进程或者僵尸进程呢?
    答案是父进程也有自己的父进程,父进程的父进程就是bash
  7. 一旦进程变成孤儿进程,它就会被1号进程领养,变成后台进程,这时候Ctrl c就杀不掉它了,我们只能使用kill来杀死。

3. 进程优先级

3.1 概念

  • cpu资源分配的先后顺序,就是指进程的优先级(priority)。
  • 目标资源稀缺,导致要通过优先级确认谁先谁后的问题。
  • 优先权高的进程有优先执行权利。配置进程优先级对多任务环境的linux很有用,可以改善系统性能。
  • 还可以把进程运行到指定的CPU上,这样一来,把不重要的进程安排到某个CPU,可以大大改善系统整体性能。
  • 优先级 vs 权限:优先级是能得到资源,先后的问题,权限是能否得到资源的问题

✏️优先级其实也是一种数字,是task_struct中的一种属性,数字值越低,优先级越高 ,基于时间片的分时操作系统,优先级未来可能变化,但变化的幅度不能太大

3.2 查看系统进程

  1. 命令ps -al,其中a表示所有,l表示详细信息。
  2. 我们上上面代码中的父进程不再退出,父子进程一直运行,再运行代码
    在这里插入图片描述
    linux系统中,每个用户都有一个UID,linux中识别用户就是用UID识别的。
  • UID:代表执行者的身份
  • PID:代表这个进程的代号
  • PPID:代表这个进程是由哪个进程发展衍生出来的,亦即父进程的代号
  • PRI:代表这个进程可被执行的优先级,其值越小越早被执行。进程优先级默认:80
  • NI:代表这个进程优先级的修正数据,nice
    ✏️进程真实的优先级 = PRI(默认) + NI
    ✏️PRI(new) = PRI(old) + nice
  • 所以,调整进程优先级,在Linux下,就是调整进程nice
  • nice其取值范围是-2019,一共40个级别。linux进程优先级范围[60,99]
  1. UID,命令ls -ln
    在这里插入图片描述
    sp用户对应的UID就是1001,文件创建的时候会把这个UID保存起来表明这个文件是谁创建的,进程创建的时候也会把UID保存起来表明进程是谁创建的。
    📌 所以当我们访问一个文件时,系统怎么识别出我们是拥有者,所属组,或者other呢,我们访问文件时本质就是进程在访问文件,进程怎么知道我们是谁呢?答案是是谁启动的这个进程,进程就知道这个人的UID,这个文件是谁创建的这个文件的UID就有了,所以一个进程将来拿着它的UID和文件的UID做对比,相等了就是拥有者,不相等查下一个,两个都不相等就是 other
    ✏️linux系统中,访问任何资源都是进程访问,进程就代表用户。

3.3 查看进程优先级的命令

top命令更改已存在进程的nice

  • top

  • 进入top后按“r”‒>输入进程PID‒>输入nice

  • 其他调整优先级的命令:nicerenice

  • linux调整优先级的系统调用

3.4 补充概念-竞争、独立、并行、并发

  • 竞争性: 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级
  • 独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰
  • 并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行
  • 并发: 多个进程在⼀个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发
    在这里插入图片描述

4. 进程切换


先谈两个问题:

  1. 死循环进程是如何运行的
    我们平时在vs中写一个while(1)的死循环,一旦跑起来我们就会发现系统会变卡了,但是不会卡死。
    a.一旦一个进程占有CPU,会把自己的代码跑完吗?不会!(除非这个代码很短)每个进程系统都会为它分配一个叫做时间片的东西。所以每一个进程拥有CPU资源都不是永久性的,而是临时性的。
    b.死循环进程不会打死进程,因为死循环进程不会一直占用CPU!
  2. cpu,寄存器
    cpu执行一个进程的时候就和PCB的关系不大了,cpu重点是访问的是进程的代码和数据,所以cpu会访问当前进程的代码和数据,为了能够处理一条一条的代码和数据,所以cpu中会存在很多的寄存器,每个寄存器在cpu内部都有着临时保存数据的任务,所以当进程再跑时,寄存器就会被填上临时值,有的是计算结果,浮点数计算有没有错误等。
    结论: a.寄存器就是cpu内部的临时空间 b. 寄存器 != 寄存器里面的数据

进程如何切换?
CPU上下文切换:其实际含义是任务切换,或者CPU寄存器切换。当多任务内核决定运行另外的任务时,它保存正在运行任务的当前状态,也就是CPU寄存器中的全部内容。这些内容被保存在任务自己的堆栈中,入栈工作完成后就把下一个将要运行的任务的当前状况从该任务的栈中重新装入CPU寄存器,并开始下一个任务的运行,这一过程就是context switch
在这里插入图片描述
进程切换最核心的就是保存和恢复当前进程的硬件上下文数据,即cpu内寄存器的内容。

  1. 保存在哪里?
    保存到进程的task_struct里面
  2. 如何区分新的进程和已经调度过的进程?
    task_struct中增加一个标记位。

5.Linux2.6内核进程O(1)调度队列

在这里插入图片描述

  1. 一个CPU拥有一个runqueue
  • 如果有多个CPU就要考虑进程个数的负载均衡问题
  1. 优先级
  • 普通优先级:100〜139(我们都是普通的优先级,想想nice值的取值范围,可与之对应!)
  • 实时优先级:0〜99(不关心)
  1. 活动队列
  • 时间片还没有结束的所有进程都按照优先级放在该队列
  • nr_active:总共有多少个运行状态的进程
  • queue[140]:一个元素就是一个进程队列,相同优先级的进程按照FIFO规则进行排队调度,所以,数组下标就是优先级!
  • 从该结构中,选择一个最合适的进程,过程是怎么的呢?
    a. 从0下标开始遍历queue[140]
    b. 找到第一个非空队列,该队列必定为优先级最高的队列
    c. 拿到选中队列的第一个进程,开始运行,调度完成!
    d. 遍历queue[140]时间复杂度是常数!但还是太低效了!
  • bitmap[5]:一共140个优先级,一共140个进程队列,为了提高查找非空队列的效率,就可以用5*32个比特位表示队列是否为空,这样,便可以大 大提高查找效率。
    在这里插入图片描述
  1. 过期队列
  • 过期队列和活动队列结构一模一样
  • 过期队列上放置的进程,都是时间片耗尽的进程
  • 当活动队列上的进程都被处理完毕之后,对过期队列的进程进行时间片重新计算
  1. active指针和expired指针
  • active指针永远指向活动队列
  • expired指针永远指向过期队列
  • 活动队列上的进程会越来越少,过期队列上的进程会越来越多,因为进程时间片到期时一直都存在的。
  • 在合适的时候,只要能够交换active指针和expired指针的内容,就相当于有具有了一批新的活动进程!

linux真是算法调度:O(1)调度算法
再次理解nice值:nice值是为了保证老进程的优先级不被强制改变,原本进程的优先级不改变,加上一个nice值,当本次调度完重新放入过期队列时,更新优先级,链入到指定位置。


👍 如果对你有帮助,欢迎:

  • 点赞 ⭐️
  • 收藏 📌
  • 关注 🔔

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2314672.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AI应用加速落地丨MaxKB正在被政府、公共事业、教育和医疗行业用户广泛采纳

2025年2月至3月上旬,伴随着各个行业接入并使用DeepSeek,MaxKB开源知识库问答系统正在被越来越多的行业用户所采纳,是人工智能行业落地的强应用。目前,MaxKB在政府、公共事业、教育和医疗四大行业已经拥有了众多典型案例&#xff0…

2024年第十五届蓝桥杯软件C/C++大学A组——五子棋对弈

蓝桥杯原题: 题目描述: “在五子棋的对弈中,友谊的小船说翻就翻? ” 不!对小蓝和小桥来说,五子棋不仅是棋盘上的较量,更是心与心之间的沟通。这两位挚友秉承着 “ 友谊第一,比赛第二…

复试难度解析,西电先进材料与纳米科技学院学院考研录取情况

01、先进材料与纳米科技学院各个方向 02、24先进材料与纳米科技学院近三年复试分数线对比 PS:材料院24年院线学硕方向降低10分,专硕上涨15分;材料院在分数线相对于其他211、985院校对比来看,依然分数偏低,推荐大家关注…

Deepseek Chatgpt Kimi 推荐的深度学习书单

朋友让推荐一些深度学习的书,让 Deepseek、Chatgpt、Kimi 分别生成了一份书单并做了对比,记录一下以备以后用到。 Chatgpt 推荐的深度学习书 1. chatgpt 推荐的书目截图 1.2 Chatgpt 推荐的深度学习书目文字版 如果你想学习 Deep Learning&#xff0…

高频面试题(含笔试高频算法整理)基本总结回顾25

干货分享,感谢您的阅读! (暂存篇---后续会删除,完整版高频面试题基本总结回顾(含笔试高频算法整理)) 备注:引用请标注出处,同时存在的问题请在相关博客留言&#xff0c…

mac安装mysql之后报错zsh: command not found: mysql !

在Mac上安装MySQL后,如果终端中找不到mysql命令,通常是 因为MySQL的命令行工具(如mysql客户端)没有被正确地添加到你的环境变量中。 检查 MySQL 是否已安装 ps -ef|grep mysql查看到路径在 /usr/local/mysql/bin 查看 .bash_pro…

蓝桥杯备考:set容器用法(lower_bound)---营业额统计

如图所示,这道题的暴力解法就是枚举每天的营业额,让该营业额和前面的天的营业额依次相减取最小值这样的话我们的时间复杂度就是N平方,我们是很有可能超时的 所以我们选择用set容器的二分查找功能 我们每次遍历到一个数的时候,前…

VSCode集成C语言开发环境

下载MinGW https://sourceforge.net/projects/mingw/ 点击download按钮下载exe文件到本地 点击exe文件安装 选择基础包和c编译版 vscode安装部分跳过 安装code runner和c/c插件 **(1) 创建 C 文件** 新建一个测试文件(例如 hello.c)&#xf…

Python----数据可视化(pyecharts二:绘图一:条形图,直方图,折线图,散点图,箱图,饼图,热力图)

1、条形图 from pyecharts.charts import Bar from pyecharts.faker import Faker from pyecharts import options as opts # 绘制柱状图 bar (Bar() # 创建柱状图.add_yaxis("商家A", Faker.values(),colorFaker.rand_color()) # 添加数据.add_yaxis("商家B&…

Training-free Neural Architecture Search for RNNs and Transformers(预览版本)

摘要 神经架构搜索 (NAS) 允许自动创建新的有效神经网络架构,为手动设计复杂架构的繁琐过程提供了替代方案。然而,传统的 NAS 算法速度慢,需要大量的计算能力。最近的研究调查了图像分类架构的无训练 NAS 指标,大大加快了搜索算…

计算机考研C语言

C语言程序设计从入门到精通【2025完整版】考研复试 嵌入式 计算机二级 软考 专升本也适用_哔哩哔哩_bilibili 1、第一个C程序 helloC #include <stdio.h>int main(){printf("hehe");return 0;}每个C语言程序不管有多少行代码&#xff0c;都是从main函数开始执…

【MySQL】(4) 表的操作

一、创建表 语法&#xff1a; 示例&#xff1a; 生成的数据目录下的文件&#xff1a; 二、查看表结构 三、修改表 语法&#xff1a; 另一种改表名语法&#xff1a;rename table old_name1 to new_name1, old_name2 to new_name2; 示例&#xff1a; 四、删除表 语法&#xf…

Qt 中实现自定义控件子类化

一、子类化关键步骤 ‌1、选择基类‌ 根据需求选择合适的 Qt 原生控件作为基类&#xff08;如 QWidget、QPushButton、QSpinBox 等&#xff09;&#xff0c;通过继承实现功能扩展‌。 ‌2、重写关键方法‌ ‌绘制逻辑‌&#xff1a;重写 paintEvent() 方法&#xff0c;使用 Q…

6. MySQL 索引的数据结构(详细说明)

6. MySQL 索引的数据结构(详细说明) 文章目录 6. MySQL 索引的数据结构(详细说明)1. 为什么使用索引2. 索引及其优缺点2.1 索引概述 3. InnoDB中索引的推演3.1 索引之前的查找3.2 设计索引3.3 常见索引概念1. 聚簇索引2. 二级索引&#xff08;辅助索引、非聚簇索引&#xff09;…

pytorch 50 大模型导出的onnx模型优化尝试

本博文基于Native-LLM-for-Android项目代码实现,具体做了以下操作: 1、尝试并实现将模型结构与权重零散的onnx模型进行合并,通过该操作实现了模型加载速度提升,大约提升了3倍 2、突破了onnxconverter_common 无法将llm模型导出为fp16的操作,基于该操作后将10g的权重降低到…

LeetCode1871 跳跃游戏VII

LeetCode 跳跃游戏 IV&#xff1a;二进制字符串的跳跃问题 题目描述 给定一个下标从 0 开始的二进制字符串 s 和两个整数 minJump 和 maxJump。初始时&#xff0c;你位于下标 0 处&#xff08;保证该位置为 0&#xff09;。你需要判断是否能到达字符串的最后一个位置&#xf…

RabbitMQ 从入门到精通

1 MQ架构设计原理 1.1 什么是消息中间件 消息中间件基于队列模型实现异步/同步传输数据 作用&#xff1a;可以实现支撑高并发、异步解耦、流量削峰、降低耦合度。 1.2 传统的http请求存在那些缺点 1.Http请求基于请求与响应的模型&#xff0c;在高并发的情况下&#xff0c…

考研复试c语言常见问答题汇总2

11. 关键字和一般标识符有什么不同&#xff1f; C语言中关键字与一般标识符区别&#xff1a; 定义&#xff1a;关键字是C语言预定义的特殊单词&#xff08;如int、for&#xff09;&#xff0c;有固定含义&#xff1b;标识符是自定义的名称&#xff08;如变量名、函数名&#xf…

Qt表格美化笔记

介绍 表格是一种常见的数据管理界面形式&#xff0c;在大批量的数据交互情形下使用的比较多 表格 可以通过样式表设置线条以及边框的颜色 QTableWidget { gridline-color : rgb(55, 60, 62); border: 1px solid rgb(62,112,181);}表头 如果表头和第一行的分割线显示&#…

『PostgreSQL』PGSQL备份与还原实操指南

&#x1f4e3;读完这篇文章里你能收获到 了解逻辑备份与物理备份的区别及适用场景&#x1f50d;。掌握全库、指定库、指定表备份还原的命令及参数&#x1f4dd;。学会如何根据业务需求选择合适的备份策略&#x1f4ca;。熟悉常见备份还原问题的排查与解决方法&#x1f527;。 …