【Linux 学习计划】-- 系统中进程是如何调度的(内核进程调度队列)

发布于:2025-06-05 ⋅ 阅读:(27) ⋅ 点赞:(0)

目录

回顾进程优先级与进程调度的引入

内核runqueue图例

关于queue[140]前100个位置 | 实时进程与分时进程

遍历需要调度的进程与bitmap的引入

active、expired指针

结语


回顾进程优先级与进程调度的引入

在我们之前的学习中,我们是有学习过进程优先级这个概念的,这里简单回顾一下

默认优先级是80,但是还有一个nice值可以供我们修改优先级的值

这是因为:优先级 = 默认优先级 + nice值

而nice值的范围是从-20~19,也就是说,进程优先级是有40个值的,即从60 ~ 99

但是现在进程的优先级我们知道了,而在系统之中,他是如何使用这些优先级的呢?

内核runqueue图例

如下图:

这个是我们内核中的runqueue,前面我们在进程状态那篇博客中也有提到他,只要进程被链入runqueue之中,就代表他会被CPU调度执行,也就是就绪和运行状态

并且,一个CPU只有一个runqueue

而今天我们将会详细谈一谈runqueue里面的几个字段,因为我们今天要讲调度,那就必然和这些绕不开

首先是上图中用蓝色框框框起来的,第三个,也就是queue[140]

需要说明的是,这140个空间中,前100个是给实时进程的(后文会有所举例),也就是0~99位置,而后面的100~139这40个位置

不对,40个位置,这和我们的nice值的范围,也就是进程优先级的范围不是正好吻合了吗!

事实也的确如此,我们来看一下图例:

我们的每一个下标,在这样子分布的情况下,就可以和进程的优先级一一对应,而我们这时候如果有进程进来了,那么就会直接根据他的优先级进行插入到相应位置:

比如这样,接着就能够调度起来了

关于queue[140]前100个位置 | 实时进程与分时进程

可能很多同学对这几个字眼比较陌生,这里举一个例子就明白了

分时操作系统就好比我们的电脑,需要同时让多个进程进行轮转,同时运行

而实时操作系统则像是车子,一台汽车里面可能有很多功能,音乐、影视等等,但是总不能说有紧急情况了,现在我要刹车,结果操作系统说:不行,我音乐还在放呢,你不能刹车,这也太扯了

以上就是关于实时操作系统和分时操作系统的讲解,这里并不打算详说,因为今天的重点是动态理解进程的调度

遍历需要调度的进程与bitmap的引入

首先,我们并不是所有进程的优先级都是从60开始的,大部分甚至都是80

那问题来了,我们前面还有100个空间没有使用,空着放在那里给实时进程准备着,那我们每一次要找下一个需要调度的进程的时候,都需要一个一个去找吗?这样的话效率太低了

所以runqueue中还有一个东西,叫做bitmap[5],也就是所谓的位图:

至于为什么是 5 呢,因为5*32=160,而4*32=128,5 个可以刚好覆盖,但是4个则会直接不够

而我们有了位图之后,效率的提升是明显的

比如我们现在要看前32个空间有没有进程,我们只需要这样:

bitmap[i]==0

这样我们一次就能知道32个位置有没有进程,如果为0,那就下一个32,如果不为0,那再一个一个找进程

active、expired指针

active(活跃)expired(过期)

我们现在再来看回最开始那张图片:

我们可以看到,这里面其实有两个框,蓝和红两个,并且,里面的内容是完全一样的

在看到蓝色框框上面的两个变量,那是两个指针,active 和 expired,而这两个指针指向的就是下面的两个框框

我们再通过画图来理解一下这个过程:

在最开始的时候,进程在活跃(active)指针指向的queue下面,等到调度完之后

这个进程就会被链入到expired所指向的queue中(下图用蓝色框框表示的就是已经调用结束的进程):

而所有的进程在被调度完之后,上面active指针所指向的queue,直接遍历 1 次bitmap,发现全是 0,就知道全部调度完了

接下来就是:两个指针的值直接交换(swap(*active, *expired))

这样我们的活跃queue和过期queue就完成了交换

接下来就是继续调度active指针指向的进程,全部执行完了之后,就再交换,过期的重新变成活跃的

如此往复

结语

这篇文章到这里就结束啦!!~( ̄▽ ̄)~*

如果觉得对你有帮助的,可以多多关注一下喔


网站公告

今日签到

点亮在社区的每一天
去签到