多道程序系统中,进程数量往往大于处理器的数量,故进程会争用处理机
处理机调度的目标是以满足系统目标的方式通过特定算法决定进程是否执行、在哪一个或者多个处理器上运行
调度决定了哪个进程需要等待哪个进程可以继续运行,有一定的时间和计算能力开销,并且会影响系统的性能。
调度的概念
调度的类型
长程调度1
长程调度决定了什么进程可以被调入处理器被处理。
调度的类型:由新建态–>就绪态/就绪挂起态
长程调度程序执行频率较低
何时需要调度
- 有作业终止时
- 处理器的空余时间片超过了一定的阈值
长程调度的四种考虑:
- 先来先服务
- 优先级
- 实时性
- I/O需求
中程调度2
中级调度就是要按照某种策略决定处于挂起状态的进程重新调入内存。
-
暂时调到外存等待的进程状态为挂起状态,需要注意PCB一般不会一起调到外存,而是会常驻内存,被挂起的PCB会被放到挂起队列中
-
中程调度程序执行频率稍高,因一个进程可能会被多次调出、调入内存,因此中级调度发生的频次要高于高级调度
换入和换出的考虑
- 换入:取决于管理系统并发度的要求;
- 换出:进程的存储需求。
短程调度
按照某些规则从就绪队列中选择进程分配处理机
- 进程调度是操作系统最基本的一种调度
- 其频率非常高,一般几十毫秒一次。这样才可以保证进程在宏观上并行运行
IO调度
在操作系统的IO操作中,进行系统中断和IO进程调度即IO调度。
此处不细讲IO调度,详见IO相关章节。
调度与队列
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ItyJSB7c-1690355917757)(https://s2.loli.net/2023/05/03/PuV3gUEa59MAWfz.png)]
调度的准则
面向用户:单个用户或进程感知到的系统行为
面向系统:处理器使用的效果和效率
性能相关:与性能相关的数值的,定量的,可以很容易地度量的准则
性能无关:或者本质上是定性的,或者不容易测量和分析
面向用户,与性能相关
- 周转时间:从提交到完成之间的时间间隔
- 响应时间:从提交到开始接收响应之间的时间间隔
- 最后期限:进程完成的最后期限
面向用户,与性能无关
- 可预测性
- 希望提供给用户的服务能够随着时间的流逝展现给用户一贯相同的特性,而与系统执行的其他工作无关。
面向系统,与性能相关
- 吞吐量:单位时间内完成的进程数目
- 处理器利用率:处理器处于忙的状态的时间百分比
面向系统,与性能无关
- 公平性:进程被平等对待
- 强制优先级
- 进程被指定优先级
- 调度策略优先选择高优先级进程
- 平衡资源
- 保持系统中所有资源处于繁忙状态,
- 较少适用紧缺资源的进程应该受到照顾。
优先级
每个进程被指定一个优先级,调度程序总是选择具有较高优先级的进程。
- 纯粹的优先级调度方案可能会导致低优先级进程长时间处于饥饿状态;
- 一个进程的优先级可随着它的时间或执行历史而变化,也可以由应用程序或用户手动设置
- 在Linux中,数字越小优先级越高;Windows等部分系统,数字越大优先级越高
调度算法
选择调度策略
进程选择函数(方式)
确定在就绪进程中选择哪一个进程在下一次执行。
进程调度方式
是指:当某个进程正在处理机上执行时,如果有某个更重要的进程需要处理时(也即优先级更高),此时应该如何分配处理机
- 非剥夺调度方式(非抢占):允许进程主动放弃处理机,在运行过程中即便有更紧迫的任务到达时,当前进程依然会继续使用处理机,直到该进程终止或主动要求进入阻塞态。该种方式实现简单,系统开销小但是无法及时处理紧急任务,适合于早期的批处理系统
- 剥夺调度方式(抢占):当一个进程正在处理机上执行时,如果有一个优先级更高的进程需要使用处理机时,则立即暂停正在执行的进程,将处理机分配给那个优先级更高的进程。该种方式可以优先处理更紧急的进程,也可以实现让各种进程按时间片轮转的功能,适合于分时操作系统、实时操作系统
性能相关准则的计算
- 进程的周转时间是结束时间-开始时间而非所有运行时间片(即该进程的运行时间)之和(前者会计算调度开支和进程调度的碎片度)
- 归一化周转时间 = 周转时间 该进程运行时间 归一化周转时间=\frac{周转时间}{该进程运行时间} 归一化周转时间=该进程运行时间周转时间
- 处理器利用率:见计算IO设备、CPU利用率-CSDN博客
吞吐量
FCFS(先来先服务)
算法思想:先来后到,每次从就绪队列选择最优先进入队列的进程,然后一直运行,直到进程退出或被阻塞,才会继续在队列中选择下一个第一个进程继续运行,属于非抢占
- 作业调度:考虑的是哪个作业先到达后备队列
- 进程队列:考虑的是哪个进程先到达就绪队列
优缺点
- 优点: 公平、算法实现简单
- 缺点: 如果带权周转时间很大,表明该进程只需很短的时间能被处理,却还要花费很长时间处理。这就像你在屏幕上打字,明明是瞬间的事情,但是却要卡半天才能出来
适用情况:对长作业有利,对短作业不利。适用于CPU繁忙型作业的系统,不适用于I/O繁忙型作业的系统
例题
平均调度时间:
[
3
+
(
9
−
2
)
+
(
13
−
4
)
+
(
18
−
6
)
+
(
20
−
8
)
]
/
5
=
8.6
[3+(9-2)+(13-4)+(18-6)+(20-8)]/5=8.6
[3+(9−2)+(13−4)+(18−6)+(20−8)]/5=8.6
平均归一化调度时间:
(
3
/
3
+
7
/
6
+
9
/
4
+
12
/
5
+
12
/
2
)
/
5
=
2.564
(3/3+7/6+9/4+12/5+12/2)/5=2.564
(3/3+7/6+9/4+12/5+12/2)/5=2.564
RR(轮转)
这是一个抢占式算法!
最古老、最简单、最公平且使用最广的算法就是时间片轮转(Round Robin, RR)调度算法。
每个进程被分配一个时间段,称为时间片(Quantum),即允许该进程在该时间段中运行。
- 如果时间片用完,进程还在运行,那么将会把此进程从 CPU 释放出来,并把 CPU 分配另外一个进程;
- 如果该进程在时间片结束前阻塞或结束,则 CPU 立即进行切换;
另外,时间片的长度就是一个很关键的点:
- 如果时间片设得太短会导致过多的进程上下文切换,降低了 CPU 效率;
- 如果设得太长又可能引起对短作业进程的响应时间变长
例题
时间片为1
平均周转时间:
(
4
+
16
+
13
+
14
+
7
)
/
5
=
10.8
(4+16+13+14+7)/5=10.8
(4+16+13+14+7)/5=10.8
平均归一化周转时间:
(
1.33
+
2.67
+
3.25
+
2.8
+
3.5
)
/
5
=
2.71
(1.33+2.67+3.25+2.8+3.5)/5=2.71
(1.33+2.67+3.25+2.8+3.5)/5=2.71
时间片为6
平均周转时间:
(
3
+
15
+
7
+
14
+
11
)
/
5
=
10
(3+15+7+14+11)/5=10
(3+15+7+14+11)/5=10
平均归一化周转时间:
(
1
+
2.5
+
1.75
+
2.8
+
5.5
)
/
5
=
2.71
(1+2.5+1.75+2.8+5.5)/5=2.71
(1+2.5+1.75+2.8+5.5)/5=2.71
注意到时间片不同,归一化周转时间相同
SPN(最短进程优先)
算法思想:最短(要求服务时间最短)的作业/进程优先得到服务,既可以用于作业调度,也可以用于进程调度
- 如果属于进程调度时,又称为“短进程优先算法(SPF)”
- SPF和SJF都是非抢占式算法。但也有对应的抢占式版本,称之为最短剩余时间优先算法(SRTN)
SRF
非抢占设计,到达之后即使预定服务时间短也要等当前进程完成
平均周转时间:
(
3
+
7
+
3
+
11
+
15
)
/
5
=
7.6
(3+7+3+11+15)/5=7.6
(3+7+3+11+15)/5=7.6
平均归一化周转时间:
(
1
+
1.17
+
2.75
+
2.8
+
1.5
)
/
5
=
1.84
(1+1.17+2.75+2.8+1.5)/5=1.84
(1+1.17+2.75+2.8+1.5)/5=1.84
SRTN(最短剩余时间)
抢占式的,进来的进程只要服务时间小于当前进程的剩余时间就抢占下来
平均周转时间:
(
3
+
13
+
4
+
14
+
2
)
/
5
=
7.2
(3+13+4+14+2)/5=7.2
(3+13+4+14+2)/5=7.2
平均归一化周转时间:
(
1
+
2.17
+
2
+
2.8
+
1
)
/
5
=
1.59
(1+2.17+2+2.8+1)/5=1.59
(1+2.17+2+2.8+1)/5=1.59
HRRN(最高响应比优先)
非抢占算法
R = ( w + s ) / s R=(w+s)/s R=(w+s)/s
- R:响应比
- w:等待处理器的时间(需要动态计算)
- s:预计的服务时间
优先级算法
随着计算机的发展,特别是实时操作系统的出现,越来越多的应用场景需要根据任务的紧急程度(优先级) 来决定处理顺序。进程的优先级可以被划分为
- 静态优先级:创建进程的时候,就已经确定好了优先级,整个运行过程优先级都不会发生变化
- 动态优先级:根据进程的动态变化调整优先级(比如当进程的运行时间增加则降低其优先级、进程等待时间增加则提高其优先级等等)
算法思想 :每个作业/进程都有各自的优先级,调度时选择优先级最高的作业/进程
- 可用于作业调度、进程调度,甚至I/O调度
- 有抢占式(当就绪队列中出现优先级高的进程,当前进程被挂起,调度优先级高的进程)和非抢占(当就绪队列中出现优先级高的进程,运行完当前进程,再选择优先级高的进程)两种
以下讨论基于UNIX优先级即数字越大优先级越小
非抢占式优先级算法
C和D在B执行时都到了,D优先级高先选择D执行;在D执行时到了,因为优先级低最后执行
平均周转时间:
(
3
+
7
+
8
+
14
+
12
)
/
5
=
8.8
(3+7+8+14+12)/5=8.8
(3+7+8+14+12)/5=8.8
平均一致性周转时间
(
1
+
1.17
+
3.5
+
1.6
+
6
)
/
5
=
2.654
(1+1.17+3.5+1.6+6)/5=2.654
(1+1.17+3.5+1.6+6)/5=2.654
抢占式优先级算法
平均周转时间:
(
14
+
11
+
14
+
5
+
12
)
/
5
=
11.2
(14+11+14+5+12)/5=11.2
(14+11+14+5+12)/5=11.2
平均归一化周转时间:
(
14
/
3
+
11
/
6
+
14
/
4
+
1
+
6
)
/
5
=
3.
(14/3+11/6+14/4+1+6)/5=3.
(14/3+11/6+14/4+1+6)/5=3.
多级反馈队列法
MFQ算法其实是RR算法和HPF算法的综合和发展
- 多级:表示有多个队列,每个队列优先级从高到低,同时优先级越高时间片越短
- 反馈:表示如果有新的进程加入优先级高的队列时,立刻停止当前正在运行的进程,转而去运行优先级高的队列,所以事抢占型算法
算法具体规则
- 设置了多个队列,赋予每个队列不同的优先级,每个队列优先级从高到低,同时优先级越高时间片越短
- 新的进程会被放入到第一级队列的末尾,按FCFS算法的原则排队等待被调度,如果在第一级队列规定的时间片内没有运行完毕,则将其转入第二级队列的末尾,依次类推,直至完成
- 当较高优先级的队列为空时,才调度较低优先级队列中的进程。如果进程运行时,有新的进程进入较高优先级队列时,则停止当前运行的进程并将其移入原队列的末尾,接着让较高优先级的进程运行
对于短作业可能可以在第一级队列很快被处理完。对于长作业,如果在第一级队列处理不完,可以移入下次队列等待被执行,虽然等待的时间变长了,但是运行时间也会更长了,所以该算法很好的兼顾了长短作业,同时有较好的响应时间。
多处理器和多核调度
多处理器系统分类
- 松耦合、分布式多处理器、集群
- 由一系列相对自治的系统组成,每个处理器有自己的内存和I/O通道。
- 专门功能的处理器
- 有一个通用的主处理器,专用处理器受主处理器的控制,并给主处理器提供服务。
- 显卡、手机上的基带等都属于这类
- 紧耦合多处理
- 由一系列共享同一个内存并在操作系统完全控制下的处理器组成。
同步粒度和进程
设计原理
把进程分配到处理器
- 静态分配和动态分配
- 静态分配:一个进程从开始到结束一直被分配到一个处理器 ,每个处理器维护一个短程队列,组调度
- 动态负载均衡:法一:进程进入公共队列,然后调度到任何一个可用的处理器中;法二:进程可以在不同处理器对应的队列之间转移
- 主从式、对等式
- 主从式:有主处理机和从处理机,OS的核心功能在特定处理器上运行,主处理器同时负责调度作业
- 缺点:主处理器是性能瓶颈,系统也会随主处理器boom
- 对等式:操作系统内核可以在任何一个处理器上运行,每个处理器从可用的进程池中进行自调度
- 缺点:处理器同步的难度,操作系统必须保证两个处理器不会选择一个进程
- 主从式:有主处理机和从处理机,OS的核心功能在特定处理器上运行,主处理器同时负责调度作业
在单个处理器上使用多道程序设计
- 传统多处理器处理粗粒度或无约束同步粒度,单处理器使用多道程序设计。
- 运行在多处理器系统中的中等粒度应用程序,更加关注如何能为应用提供更好的平均性能,单个处理器是否多道并不重要。
一个进程的实际分派
- 使用简单的调度方法会更有效,降低开销
线程调度
线程执行的概念和进程中的定义是不同的。一个单一的应用程序可以按一组线程来实现,这些线程可以在同一个地址空间中协作和并发地执行。
- 负载分配(不是平衡)
- 系统维护一个就绪线程的全局队列,每个处理器只要空闲就从队列中选择一个线程。
- 组调度
- 一组相关的线程基于一对一的原则,同时调度到一组处理器上运行。
- 专用处理器调度组
- 调度的一种极端形式,在一个应用程序执行期间,把一组处理器专门分配给这个应用程序。
- 动态调度
- 某些应用程序允许动态地改变进程中线程数目,需要动态调度。
- 操作系统负责分配处理器给作业,作业自行调度。
现代多核调度
目前基本上以多处理系统的方式来进行多核系统的调度。
- 通过负载均衡使得就绪线程均匀分布,保持处理器繁忙。
- 单个芯片上核比较少的情况下是可以的,但如果单个芯片上有很多核,该策略并不能很好的发挥多核的性能。
最小化访问片外存储器优先于最大化处理器利用率。
对局部缓存的利用。传统的缓存处理算法如LRU会导致线程间共用缓存的竞争,而解决其是CPU和操作系统界的前沿话题
实时调度
实时计算
实时运算(Real-time computing)是计算机科学中对受到“实时约束”的计算机硬件和计算机软件系统的研究,实时约束像是从事件发生到系统回应之间的最长时间限制。实时程序必须保证在严格的时间限制内响应。
系统的正确性不仅取决于计算的逻辑结果,还依赖于产生结果的时间
实时任务
实时的“硬度”
- 硬实时任务:必须满足最后期限
- 软实时任务 :有期望期限但不强制
实时的周期性
- 周期性任务:每隔周期T完成一次任务
- 非周期性任务
实时操作系统
实时操作系统(Real-time operating system, RTOS),又称即时操作系统,它会按照排序运行、管理系统资源,并为开发应用程序提供一致的基础。
实时操作系统与一般的操作系统相比,最大的特色就是“实时性”,如果有一个任务需要执行,实时操作系统会马上(在较短时间内)执行该任务,不会有较长的延时。这种特性保证了各个任务的及时执行。
要求
- 可确定性:按照固定、预先确定的时间或间隔进行操作
- 可响应性:为中断提供服务的时间
- 用户控制:允许用户细粒度地控制任务优先级,指定一些特性等
- 可靠性:避免性能损失或降低导致的灾难性后果
- 故障弱化操作:故障时尽可能多地保存其性能和数据的能力
特点
- 快速的进程或线程切换。
- 体积小(只具备最小限度的功能)。
- 迅速响应外部中断的能力。
- 通过诸如信号量、信号和时间之类的进程间通信工具,实现多任务处理。
- 使用特殊的顺序文件,可以快速存储数据。
- 基于优先级的抢占式调度。
- 最小化禁止中断的时间间隔。
- 用于使任务延迟一段固定的时间或暂停/恢复任务的原语。
- 特别的警报和超时设定。
实时调度算法
考虑的问题
- 一个系统是否执行可调度性分析;
- 如果执行,是静态的还是动态的;
- 分析结果自身是否根据在运行时分派的任务产生一个调度或计划。
根据实时任务的性质
- 硬实时调度算法
- 软实时调度算法
根据调度可行性分析时间不同
- 静态调度算法
- 动态调度算法。
按调度方式(抢占即不产生调度计划)
- 非抢占调度算法
- 抢占调度算法
常用的实时调度算法
-
静态表法
-
执行关于可行调度的静态分析。分析的结果是一个调度,它用于确定在运行时一个任务何时必须开始执行。
-
静态优先级抢占法
- 执行一个静态分析,但是没有制定调度,通过给任务制定优先级,使用传统的基于优先级的抢占式调度。
-
基于动态规划调度法
- 在运行时动态地确定可行性,可行性分析的结果是一个调度或规划,可用于确定何时分派这个任务。
-
动态尽力调度法
- 不执行可行性分析。系统试图满足所有的最后期限,并终止任何已经开始运行但错过最后期限的进程。
限期调度
实时应用程序通常并不关注绝对速度,它关注的是在最有价值的时间完成(或启动)任务。
- 限期调度:最早最后期限优先。
最后期限
- 启动最后期限:任务必须开始的时间。
- 完成最后期限:任务必须完成的时间。
限期调度是实时调度系统中确定调度可行性的主要方法
完成最后期限优先EDF(Earliest Deadline First)
根据任务的开始截止时间来确定任务的优先级。截止时间越早,其优先级越高。(开始截至时间为t:在t时刻之前该任务必须开始执行)
- 系统保持一个实时任务就绪队列
- 队列按各任务截止时间的早晚排序
- 调度程序总是选择就绪队列中的第一个任务,分配处理机使之投入运行。
新任务产生时,是否等当前程序执行完:
- 抢占式/非抢占式
可能会使作业错过,但可适用于软实时系统
例子:
启动最后期限优先
本例题是非抢占调度
最低松弛度优先LLF(Least Laxity First)
根据任务紧急(或松弛)的程度,来确定任务的优先级。任务的紧急程度越高(松弛度值越小),优先级就越高。
松弛度= 截止完成时间 – 还需执行时间 - 当前时间
可理解为当前时刻到完成截止时刻间的差距,随着时间的推进,这个差值逐渐变小,任务越来越紧迫。
假如在一个实时系统中,有两个周期性实时任务 A和 B,任务 A 要求每 20 ms 执行一次,执行时间为 10 ms;任务 B 只要求每 50 ms 执行一次,执行时间为 25 ms。由此可得知任务 A 和 B 每次必须完成的时间分别为:A1、A2、A3、…和 B1、B2、B3、…,见下图。为保证不遗漏任何一次截止时间,应采用最低松弛度优先的抢占调度策略。
A 和 B 任务每次必须完成的时间
在刚开始时(t1 = 0),A1 必须在 20 ms 时完成,而它本身运行又需 10 ms,可算出 A1 的松弛度为 10 ms;B1 必须在 50 ms 时完成,而它本身运行就需 25 ms,可算出 B1 的松弛度为 25 ms,故调度程序应先调度 A1 执行。在 t2 = 10 ms 时,A2 的松弛度可按下式算出:
类似地,可算出 B1 的松弛度为 15 ms,故调度程序应选择 B2 运行。在 t3 = 30 ms 时,A2 的松弛度已减为 0(即 40 - 10 - 30),而 B1 的松弛度为 15 ms(即 50 - 5 - 30),于是调度程序应抢占 B1的处理机而调度 A2运行。在 t4 = 40 ms 时,A3的松弛度为 10 ms(即 60 - 10 - 40),而 B1 的松弛度仅为 5 ms(即 50 - 5 - 40),故又应重新调度 B1 执行。在 t5 = 45 ms 时,B1执行完成,而此时 A3 的松弛度已减为 5 ms(即 60 - 10 - 45),而 B2 的松弛度为 30 ms(即 100 - 25 - 45),于是又应调度 A3 执行。在 t6 = 55 ms 时,任务 A 尚未进入第 4 周期,而任务 B 已进入第 2 周期,故再调度 B2 执行。在 t7 = 70 ms 时,A4 的松弛度已减至 0 ms(即 80 - 10 - 70),而 B2 的松弛度为 20 ms(即 100 - 10 - 70),故此时调度又应抢占 B2 的处理机而调度 A4 执行。下图为具有两个周期性实时任务的调度情况。
速率单调调度
- 适应于周期性任务调度
- 最短周期的任务具有最高优先级,次短周期的任务具有次高的优先级,以此类推。
- 当同时有多个任务可以被执行时,最短周期的任务被优先执行。
- 衡量周期调度算法有效性的标准:
- 是否能够保证满足所有硬最后期限
- 对于RMS,须满足:C1/T1+C2/T2+…+Cn/Tn≦n(21/n-1)
任务P1:C1=20;T1=100;U1=0.2
任务P2:C2=40;T2=150;U2=0.267
任务P3:C3=100;T3=350;U3=0.286
三个任务的总利用率为0.2+0.267+0.286=0.753
使用RMS,三个任务的可调度性上界根据公式计算为0.779,0.753<0.779,故所有的任务可以成功得到调度。
优先级反转
在任何优先级调度方案中,系统应该不停地执行具有最高优先级的任务。当系统内的环境迫使一个较高优先级的任务去等待一个较低优先级的任务时,优先级反转就会发生。
现代操作系统的调度
Linux
实时调度
负责Linux实时调度的三个类
-
SCHED_FIFO:先进先出实时线程
实时类的优先级(0-99)高于Normal类(100-139)。调度有如下的规则
- 除非有更高优先级的FIFO线程就绪、因等待事件阻塞、自愿放弃,否则不会系统中断
- 被中断后,放入与其优先级相关联的队列中
- 更高优先级,等待时间最长的线程优先执行
-
SCHED_RR:轮转实时线程
- 和FIFO类似,但是每个线程会和一个时间片关联,时间片用完,将会换更高优先级或者同级的其他线程执行
-
SCHED_NORMAL:其他非实时线程
- 仅当实时队列中无线程时,才会被调度
非实时调度
Linux 2.4的SCHED_NORMAL策略的调度随着中央处理器和程序数量的增加,表现并不好,有如下的缺点
- 多处理器仅使用一个运行队列,线程可能被调度到任何一个处理器上,造成缓存命中率低
- 运行队列锁,限制了调度的效率
- 不可抢占
在Linux 2.6中进行了改进,提出了完全公平的调度策略。会根据线程的占用CPU的时间排序,每次选择占用时间最短的线程执行。
利用红黑树的数据结构3,完全公平调度器还能实现睡眠公平,即保证当前不可运行的任务可以在它们需要处理器时获得一个公平的比例。
同时引入了组的概念,将一组任务当成一个任务进行调度。
另称高级调度或作业调度 ↩︎
也称内存调度 ↩︎
【数据结构】史上最好理解的红黑树讲解,让你彻底搞懂红黑树_小七mod的博客。红黑树是一种在插入或删除结点时都需要维持平衡的二叉查找树,并且每个结点都具有颜色属性:(1)、一个结点要么是红色的,要么是黑色的。(2)、根结点是黑色的。(3)、如果一个结点是红色的,那么它的子结点必须是黑色的,也就是说在沿着从根结点出发的任何路径上都不会出现两个连续的红色结点。(4)、从一个结点到一个NULL指针的每条路径上必须包含相同数目的黑色结点。Linux的CFS调度使用红黑树的原理详见:linux源码解读(十五):红黑树在内核的应用——CFS调度器 - 第七子007 - 博客园 (cnblogs.com) ↩︎