Hello,好久不见,我是云边有个稻草人-CSDN博客,继续与你分享Linux领域专业知识!
《Linux系统》本篇文章所属专栏---持续更新中---欢迎订阅!
目录
[3.2 进程状态续接上节](#3.2 进程状态续接上节)
[3.3 进程优先级](#3.3 进程优先级)
[3、PRI and NI 、 优先级极值问题](#3、PRI and NI 、 优先级极值问题)
[3.4 进程切换](#3.4 进程切换)
正文开始------
【Linux系统】第八节---进程概念(上)---冯诺依曼体系结构+操作系统+进程及进程状态+僵尸进程---详解!-CSDN博客,上节回顾!
3.2 进程状态续接上节
(5)孤儿进程
父子进程关系中,如果父进程先退出,子进程怎么办?此时子进程要被1号进程"收养",这个被领养的进程(子进程),叫做孤儿进程 ,此时的孤儿进程就变成了后台进程(S)。
此时使用ctrl+c是无法停止孤儿进程的,也就是ctrl+c无法停止后台进程,可以使用 kill -9 pid 进行杀掉孤儿进程。
孤⼉进程被1号init/systemd进程自动领养,当然要有init/systemd进程回收。
下面代码营造孤儿进程场景:

bash
while :; do ps axj | head -1 && ps axj | grep myproc ;sleep 1 ; done
为什么要领养?如果不领养,子进程进入僵尸状态之后会出现什么状态?
一定会造成内存泄漏,只有子进程被领养之后才会有父进程去获取子进程的退出信息进而使得子进程可以成功退出。
3.3 进程优先级
1、基本了解
是什么?
是进程得到CPU资源的先后顺序(cpu资源分配的先后顺序,就是指进程的优先权(priority),优先权高的进程有优先执行权利)
优先级 VS 权限?
优先级:能得到资源,先后的问题
权限:是否能得到某种权限
为什么?
目标资源紧缺,导致要通过优先级确认谁先谁后的问题
怎么办?
是一种数字,int,task_struct里面的一种属性。
值越低,优先级越高,反之,优先级越低。基于时间片的分时操作系统,考虑公平性,优先级可能变化,但是变化幅度不大
2、查看系统进程
ps : 用来查看当前进程状态的命令,全称 process status。
bash
ps -al //进程优先级、查看进程细节
ps -al | head -1 && ps -al | grep myproc

3、PRI and NI 、 优先级极值问题
PRI:进程的优先级,默认:80
NI:进程优先级的修正数据,nice值
进程真实的优先级=PRI(默认)+ NI
调整进程优先级,在Linux下,就是调整进程nice值,nice其取值范围是-20⾄19,⼀共40个级别,默认是80,所以,Linux进程的优先级的范围是[60,99]。
优先级设置不合理,会导致优先级低的进程,长时间得不到CPU资源,进而导致:进程饥饿。
小知识:

- 需要强调⼀点的是,进程的nice值不是进程的优先级,他们不是⼀个概念,但是进程nice值会影响到进程的优先级变化。
- 可以理解nice值是进程优先级的修正修正数据。
4、查看进程优先级的命令
⽤top命令更改已存在进程的nice:
- top
- 进⼊top后按"r"‒>输⼊进程PID‒>回车->输⼊nice值
其他调整优先级的命令:nice,renice

5、概念------竞争、独立、并行、并发

不要用人的感觉去衡量CPU的速度,CPU的运行速度很快

3.4 进程切换
1、死循环进程如何运行
**a、**一旦一个进程占有CPU,会把自己的代码跑完吗?不会!有一个时间片的东西。(时间片:当代计算机都是分时操作系统,每个进程都有它合适的时间片(其实就是⼀个计数器)。时间⽚到达,进程就被操作系统从CPU中剥离下来。)
**b、**死循环进程,不会打死系统,不会一直都占有CPU!
2、聊聊CPU、寄存器

3、进程切换

b、具体

4、Linux真实调度算法:O(1)调度算法

调度器通过nr_active判断是否存在就绪进程;扫描bitmap快速定位数值更小、优先级更高的队列,优先执行高优先级。
同一优先级内采用时间片轮转,进程时间片耗尽后,会放回当前优先级队列末尾。
若高优先级(如 60)存在死循环进程,会持续占用调度资源,调度器必须跑完该级所有进程,
才会调度 61 及更低优先级队列,最终造成低优先级进程饥饿。
怎么办?

如果来一个新进程,是放在哪一个队列里面?
新进程,一律放进 expired 队列
完整逻辑
- active:正在 CPU 跑、正在调度的队列
- expired :专门收三类进程
- 时间片耗尽的老进程
- 刚创建的新进程
- 休眠唤醒、重新就绪的进程
一轮流程串死
- 正常调度:只跑 active 队列
- 新进程 / 时间片用完的进程 → 全塞 expired
- 等 active 彻底跑空
- 执行
swap(active, expired)
- 原来满的 expired → 变成新 active(开始调度)
- 原来空的 active → 变成新 expired(清空收纳)
为什么不放 active?
防止新进程插队霸占 CPU,保证轮转公平,避免饥饿。
新进程统一放入 expired 过期队列,等下次指针交换后,才能被调度执行。
梳理看一下文字:
(1)⼀个CPU拥有⼀个runqueue
如果有多个CPU就要考虑进程个数的负载均衡问题
(2)优先级
- 普通优先级:100〜139(我们都是普通的优先级,想想nice值的取值范围,可与之对应!)
- 实时优先级:0〜99(不关⼼)
(3)活动队列
- 时间⽚还没有结束的所有进程都按照优先级放在该队列
- nr_active:总共有多少个运⾏状态的进程
- queue[140]:⼀个元素就是⼀个进程队列,相同优先级的进程按照FIFO规则进⾏排队调度,所以,数组下标就是优先级!
- 从该结构中,选择⼀个最合适的进程,过程是怎么的呢?
- 从0下表开始遍历queue[140]
- 找到第⼀个⾮空队列,该队列必定为优先级最⾼的队列
- 拿到选中队列的第⼀个进程,开始运⾏,调度完成!
- 遍历queue[140]时间复杂度是常数!但还是太低效了!
- bitmap[5]:⼀共140个优先级,⼀共140个进程队列,为了提⾼查找⾮空队列的效率,就可以用5*32个⽐特位表示队列是否为空,这样,便可以大大提高查找效率!

(4)过期队列
- 过期队列和活动队列结构⼀模⼀样
- 过期队列和活动队列结构模样
- 过期队列上放置的进程,都是时间⽚耗尽的进程
- 当活动队列上的进程都被处理完毕之后,对过期队列的进程进⾏时间⽚重新计算
(5)active指针和expired指针
- active指针永远指向活动队列
- expired指针永远指向过期队列
- 可是活动队列上的进程会越来越少,过期队列上的进程会越来越多,因为进程时间⽚到期时⼀直 都存在的。
- 没关系,在合适的时候,只要能够交换active指针和expired指针的内容,就相当于有具有了⼀批新的活动进程!
(6)总结
在系统当中查找⼀个最合适调度的进程的时间复杂度是⼀个常数,不随着进程增多而导致时间成本增加,我们称之为进程调度O(1)算法!
本文继续探讨Linux进程概念,重点解析了孤儿进程、进程优先级和进程切换机制。孤儿进程指父进程退出后被init进程领养的子进程,避免内存泄漏。进程优先级通过PRI和NI值确定,取值范围60-99,可通过top命令调整。Linux采用O(1)调度算法,使用活动队列和过期队列实现高效进程切换,通过时间片轮转保证公平性,避免低优先级进程饥饿。文章详细介绍了调度器如何通过bitmap快速定位高优先级进程,以及指针交换机制确保新进程不会插队霸占CPU资源。
完------
至此结束------
我是云边有个稻草人
期待与你的下一次相遇!
