【Linux】进程切换与优先级
前言:
上文我们讲到了操作系统与Linux中进程的状态【Linux】进程状态-CSDN博客
本文我们来讲进程的优先级、以及进程的切换
进程优先级
什么是优先级?
CPU中资源是有限的,而进程的数量一定是远大于CPU资源的,所以优先级是进程得到CPU资源的先后顺序。优先级也是进程的属性之一,保存在PCB中。
优先级的实现
优先级是进程的属性之一,保存在PCB中。
优先级中PCB中用整型表示,其值越小表示优先级越高,反之优先级越低。
优先级是可以被修改的。但考虑到时间片的分时操作系统,以及公平性,优先级不能出现大幅度的修改。
如上图,我在Linux中使用执行查看当前正在运行的进程信息。可以看到红圈这两个值:
PRI:表示进程的优先级,其默认值是80
NI:表示进程优先级的修正数据,称为nice值
优先级的修改:是通过nice值的修改实现的,既最终的优先级 = PRI + NI
如图,通过renice指令来修改进程的优先级后,我们再次查看进程信息可以发现第一个被修改的进程NI变成了10。最终的优先级变成了90。 说明默认值是不改变的,优先级修改是通过nice值的修改而实现的
补充:UID
如上图,我们可以看到第三列有一个叫做UID的。那什么是UID呢?
UID:user id,表示用户标识符
在linux中任何访问资源的操作都是进程实现的,进程代表当前的用户。那系统是如何判断当前进程访问的权限的呢?
其实就是通过UID实现的:通过进程中的UID与文件的UID相比较,就可以判断出这个进程的访问权限是拥有者、所属组还是other。
优先级的极值
如图可知,优先级的范围是[60 - 99],而nice值的范围是[-20 - 19]
优先级范围设置的并不宽泛,因为优先级范围设置过大会导致,优先级低的进程长时间不能获得CPU资源,进而导致:进程饥饿。
进程关系
竞争性:进程与进程之间是存在竞争关系的。CPU资源有限,为获得CPU资源,为了高效完成任务,更合理的竞争相关资源,便有了优先级。
独立性:多进程运行时,各个进程之间是独享资源的,互不干扰。
并行:多个进程在多个CPU下,同时运行。
并发:多个进程在一个CPU下不停的切换运行,在一段时间内,让多个进程不断推进。
进程切换
进程的切换讨论范围在长代码与死循环代码,因为较短的代码一瞬间就执行完毕了,没有切换这一说法
死循环进程
死循环进程一段占用CPU执行代码,会一直占用CPU吗?
并不会,因为在计算机是分时操作系统,在进程执行的过程中存在“时间片”。每个进程都有其适合的“时间片”(本质其实就是计数器),时间片达到时,进程就会从CPU上剥离下来。
所以死循环并不会一直占用CPU。
CPU中的寄存器
CPU中存在各种各样的寄存器,用于保存当前正在运行进程的各种临时数据
寄存器就是CPU内部的临时空间
寄存器!=寄存器中的数据
如何切换
A进程占用CPU执行完一个时间片后,要被剥离CPU,进而执行下一个进程。
那么当再次执行A进程时,应该从上次执行位置开始继续向下执行。 这就意味着剥离时,需要当前进程把自己的上下文记录下来,以便于下一次继续执行。
进程上下文保存到了哪里呢?保存到了进程task_struct的TSS中(TSS:任务状态段),下一次执行时,之间覆盖CPU中的寄存器内容即可。
对于以及执行过的进程才需要记录上下文,对于之前还没有执行过的继承无需记录,及其将寄存器内容初始化即可。
Linux中真实的调度算法:O(1)调度算法
如上图,runqueue是一个运行队列,且一个CPU只有一个运行队列。
queue[140]
我们先来介绍一下queue[140]:它的数据类型是 struct task_struct*
struct task_struct* queue[140]
queue一共有140个元素,一个元素就是一个进程队列,其下标映射了优先级。前100个元素代表实时优先级(我们不关心)后40个代表我们上面所讲的普通优先级。
我们之前讲到优先级的范围是:60~99,那对应在queue中的下标表示就是:100~139(x - 60 +100)。比如优先级为64的进程就会链接至下标为104的节点下,多个优先级一样的进程都会被依次链接在同一个进程队列中。
bitmap
bitmap[5]用于在queue中快速查找进程。
bitmap的数据类型是 unsigned int,一个元素有32bit,一个有5个这样的元素。
用bit位记录进程信息,0表示没有进程,1表示有进程。从下标0开查询,一次性查询32个位置,并从最后一个“1”开始调用进程(既优先级最高的进程位置)。
nr_active
记录进程的个数,当进程个数为0时,不在使用bitmap查询进程。
过期队列与活跃队列
在图中我们可以看到有两个一模一样的队列结构(蓝框与红框),并由两个指针分别指向:active(活跃)、expired(过期)。
active指向的队列叫做活跃队列,反之另一个叫过期队列。
活跃队列上的进程是要占用CPU资源,执行代码的。当活跃队列上的进程执行完一个时间片后,会放到过期队列中的相应位置上(优先级对应的位置)。当活跃队列上的进程全部执行完时,active指针与expired指针交换:过期队列再次变为活跃队列,继续执行之前的进程。
Linux中进程切换的整体过程
1.由bitmap在活跃队列中查询进程位置(优先级最高进程的位置)
2.依次占用CPU资源,执行相关进程
3.时间片耗尽,记录上下文后从CPU上剥离,并链接至过期队列中
4.直到活跃队列中没有进程,指针交换,再次循环至第一步
补充:
如果新建了一个进程,是插入活跃队列还是过期队列?
:活跃队列,新创建的进程应该尽快获得执行机会,而不是放入已经执行过的过期队列中等待下一次的调度