操作系统:进程的短程调度
我们之前在进程的调度,创建和终止这篇文章中已经讲过了进程调度的类型,在这一节中我们深入探讨一下短程调度。
短程调度的概念
短程调度,也常被称为 CPU 调度 或 低级调度,是操作系统中负责决定就绪队列中的哪个进程/线程将接下来获得CPU使用权的机制。
抢占式调度和非抢占式调度
短程调度又分为抢占式调度和非抢占式调度:
-
非抢占式调度
-
定义:一旦进程获得CPU,除非它主动释放(如因等待I/O而阻塞、或任务完成),否则将一直运行下去。
-
核心:进程自行决定何时放弃CPU。
-
-
抢占式调度
-
定义:操作系统可以强制中断当前正在运行的进程,收回CPU并将其分配给其他进程。
-
核心:操作系统主动决定何时收回CPU。
-
进程调度发生的时机:
1.进程从运行态转换为阻塞态
2.进程从运行态转换为等待态
3.进程从阻塞态转换为就绪态
4.进程终止
只有在情况1和情况4下发生的调度才是非抢占式调度,而其他情况都是抢占式调度。
调度器和分发器
调度器 - 决策大脑
调度器是操作系统内核中负责实现调度算法的软件模块。
1. 核心职责
在需要重新分配CPU时(调度时机),从就绪队列中所有处于就绪状态的进程/线程里,根据预设的调度算法,选择出一个最合适的来接管CPU。
2. 调度时机(何时被调用?)
运行 → 等待:进程主动发起I/O请求,自我阻塞。
运行 → 终止:进程执行完毕。
运行 → 就绪:(抢占) 时间片用完,或有更高优先级进程变为就绪。
等待 → 就绪:(抢占) 进程等待的I/O完成,中断处理程序将其唤醒为就绪状态。
3. 关键属性
算法依赖:它的行为完全由所采用的调度算法决定(如FCFS、SJF、优先级调度、RR轮转、多级反馈队列等)。
目标导向:它的设计目标是为了优化某些调度准则,如:
公平性:确保每个进程都能获得CPU时间。
高吞吐量:单位时间内完成尽可能多的工作。
低延迟:快速响应交互式请求。
短周转时间:让批处理作业尽快完成。
分发器 - 执行四肢
分发器是操作系统内核中负责执行进程/线程切换的底层软件模块。
1. 核心职责
在调度器做出选择之后,分发器负责完成从当前运行进程到被选中进程之间的实际、物理的切换操作。这个过程就是上下文切换。
2. 具体工作流程(极其关键)
分发器必须按严格的顺序完成以下步骤:
切换上下文
保存:将当前运行进程的“执行现场”(包括程序计数器、CPU寄存器、程序状态字等)保存到它的进程控制块中。
加载:将下一个要运行进程的PCB中保存的“执行现场”重新加载到CPU的相应寄存器中。
本质:相当于为旧进程“存档”,为新进程“读档”。
切换到用户模式
操作系统内核(包括分发器自身)运行在权限极高的内核态。
用户进程运行在权限受限的用户态。
在跳转到用户进程代码前,必须将CPU从内核态切换回用户态,以保证系统安全。
跳转到正确位置
将程序计数器设置为新进程被中断时(或开始执行时)的指令地址。
至此,CPU正式开始执行新进程的代码。
3. 关键属性与性能指标
速度至上:分发器代码必须高度优化,因为它本身就是一种系统开销。
硬件相关:其实现严重依赖于特定CPU架构的上下文切换指令。
性能指标:分发延迟
定义:从停止一个进程到启动另一个进程所花费的总时间。
构成 = 上下文切换时间 + 分发器代码执行时间。
目标:最小化分发延迟,让CPU更多时间执行有用的用户工作,而非浪费在切换工作上。
调度评价标准
1. CPU利用率
-
定义:CPU用于执行有效工作(而非空闲等待)的时间占总时间的百分比。
-
银行比喻:柜员忙于处理客户业务的时间占全天工作时间的比例。 如果柜员在发呆或等客户,利用率就下降了。
-
公式:
CPU利用率 = (CPU忙碌时间 / 总统计时间) * 100%
-
目标:最大化。我们希望这个昂贵的资源(柜员/CPU)尽可能别闲着。
-
重要性:最基础的指标。低的CPU利用率意味着资源浪费。
2. 吞吐量
-
定义:单位时间内系统完成的工作量。 在CPU调度中,特指单位时间内完成的进程数量。
-
银行比喻:一小时(或一天)内,柜员总共服务了多少位客户。
-
公式:
吞吐量 = 完成的进程数 / 总时间
-
目标:最大化。我们希望系统在单位时间内完成的任务越多越好。
-
重要性:衡量系统整体效率和处理能力的核心指标,尤其在批处理系统中。
3. 等待时间
-
定义:进程在就绪队列中等待,即它已经准备好运行,但还没有获得CPU使用权所花费的总时间。
-
银行比喻:一位顾客在排队区坐着等待,直到他走到柜台前的那一刻,所花费的累计时间。 (不包括他在柜台办理业务的时间,也不包括他中途去填表等非排队时间)。
-
重要洞察:CPU调度算法只能影响进程的等待时间,而无法改变进程实际需要的CPU运行时间(业务办理时间)和I/O时间(填表时间)。
-
目标:最小化。
-
重要性:直接反映了调度算法的公平性和效率。一个好的算法应该让进程的“无效”等待时间尽可能短。
4. 周转时间
-
定义:从一个进程进入系统(提交)开始,到该进程彻底完成并离开系统为止,所经历的总时间。
-
银行比喻:一位顾客从他踏进银行开始排队,到他办完所有业务离开银行所花费的总时间。
-
公式:
周转时间 = 进程完成时间 - 进程提交时间
,或者周转时间=等待时间+服务时间
,等待时间如上,服务时间:进程在CPU上实际运行的总时间。也可以理解为进程完成任务所需要的总CPU时间。 -
目标:最小化。对于用户来说,他希望从提交任务到拿到结果的时间越短越好。
-
重要性:从单个进程(顾客) 的角度衡量系统效率的关键指标。它包含了所有等待时间和执行时间。
5. 响应时间
-
定义:在交互式系统中,从用户提交请求到系统首次产生响应(而不是输出最终结果)的时间间隔。
-
银行比喻:顾客举手向大堂经理提出一个简单问题(比如“哪里取表格?”),从他举手开始,到大堂经理回过头对他说“在那边”的第一个瞬间,这之间的时间。 这不是指经理详细解答完问题的时间。
-
目标:最小化。
-
重要性:对于交互式系统(如桌面操作系统、在线系统)而言,这是最重要的指标。它决定了用户感觉系统是“敏捷”还是“卡顿”。
6.响应比
- 响应比=(等待时间+服务时间)/服务时间
- 衡量作业调度紧迫性的指标,综合考虑等待时间和服务时间。
指标 | 主要考虑角度 | 说明 |
---|---|---|
1. CPU利用率 | 系统角度 | 衡量系统资源(CPU)的利用效率。 |
2. 吞吐量 | 系统角度 | 衡量系统在单位时间内的工作能力。 |
3. 等待时间 | 用户角度 | 用户关心进程在就绪队列中浪费的时间。 |
4. 周转时间 | 用户角度 | 用户从提交作业到获得最终结果所需的总时间。 |
5. 响应时间 | 用户角度 | 交互式用户收到系统首次反馈的时间,直接影响体验。 |
6. 响应比 | 综合角度 | 同时考虑了用户的等待时间和系统的执行效率。 |
需要说明的是,一般带有“平均”二字的性能指标,一般都是从系统角度考虑的。
调度算法
先来先服务(FCFS)
1. 核心策略
-
政策:最先请求CPU的进程,最先被分配CPU。
-
中文名:先来先服务(First Come, First Served)。
-
本质:这是一种 “排队” 思想,类似于日常生活中在超市收银台排队。
2. 调度类型
-
非抢占式:一旦某个进程获得CPU,它就会一直运行,直到它完成或主动放弃(如等待I/O)。操作系统不会中途强行打断它。
3. 实现机制
-
使用一个 FIFO队列。
-
新到达的进程被加入到队尾。
-
当需要调度时,从队首取出一个进程来执行。
-
4.举例
假设有3个进程,先后到达的顺序分别是p1,p2,p3,Burst Time表示它们的服务时间,现在要计算他们的平均等待时间:
这里为了方便分析,我们可以引入甘特图的概念:
在进程调度的上下文中,甘特图是一种条形图,它展示了不同进程随时间在CPU上执行的情况。每个条形代表一个进程,并且其长度表示该进程占用CPU的时间段。通过这种方式,甘特图能够清晰地显示:
- 哪个进程正在使用CPU
- 每个进程何时开始执行以及何时结束
- 进程在就绪队列中的等待时间
- CPU空闲时段(如果有)
对应的甘特图:
p1一来就被运行了,他的等待时间是0,等到p1运行完以后,p2才开始运行,p2的等待时间是24秒,p2运行完以后,p3才开始运行,等待时间是24+3=27秒,他们的平均等待时间:(0+24+27)/3=17秒。
上面的例子我们可以看到,:尽管P2和P3都是很短的任务,但它们不得不等待前面那个漫长的P1任务完成。这导致了极长的平均等待时间,如果交换他们先后到达的顺序,会发生怎样的变化:
进程 | 服务时间 |
---|---|
P2 | 3 |
P3 | 3 |
P1 | 24 |
对应的甘特图:
结合甘特图我们可以算出平均等待时间:(0+3+6)/3=3,明显比17要短得多。
优先级调度
核心思想:为每个进程分配一个优先级数值,CPU总是分配给当前就绪队列中优先级最高的进程。
优先级的确定可以基于哪些?
- 作业对用户造成的开销或成本
- 作业对用户的重要性
- 作业的年龄:进程如果长时间没有被调度,也就是进程等太久了,自动提高优先级(防止饿死)
- 最近占用的 CPU 时间,用得多可能要限制一下
调度方式:
-
可抢占式:当一个新的、优先级更高的进程到达就绪队列时,它会立即抢占当前正在运行的进程。
-
非抢占式:进程一旦开始运行,就会一直运行到完成或主动放弃CPU,无视新来的高优先级进程。
静态优先级和动态优先级
静态优先级
定义:进程在创建时被赋予一个优先级,并且在整个生命周期内固定不变。
确定依据:
进程类型:操作系统内核进程通常比用户进程优先级高。
资源需求:预期运行时间短(接下来将要讲的SJF的思想)、占用内存少的进程可能被赋予高优先级。
用户类别:付费越多的用户(VIP用户),其进程优先级可能越高。
优点:
实现简单,系统开销小。
缺点:
可能产生严重的“饥饿”现象:低优先级进程可能因为始终有高优先级进程存在而永远得不到执行。
不够灵活,无法根据系统运行时的状态进行调整。
动态优先级
定义:进程的优先级在运行过程中可以根据预设规则动态调整。
调整依据(核心思想:根据系统状态和进程行为进行奖励或惩罚):
等待时间 - 老化
规则:随着进程在就绪队列中等待时间的增长,逐步提高其优先级。
目的:解决“饥饿”问题,保证所有进程最终都能获得服务。这是静态优先级转向动态优先级最关键的一步。
CPU使用历史
规则:如果一个进程频繁放弃CPU去进行I/O操作(可推断为交互式进程),则提高其优先级。
规则:如果一个进程持续长时间占用CPU(可推断为计算密集型进程),则降低其优先级。
目的:奖励交互式进程,以提升系统响应速度,改善用户体验。
优点:
公平性好,有效防止“饥饿”。
响应性好,能更好地适应变化的系统负载和进程行为。
缺点:
实现复杂,系统需要定期计算和调整优先级,带来额外开销。
最短作业优先(SJF)
1. 核心策略
-
策略:将每个进程与其下一个CPU区段的长度关联起来,使用这些长度来调度时间最短的进程。
-
目标:最小化系统的平均等待时间。
2. 理论基础
-
SJF是最优的:在所有进程同时可运行(或已知到达时间和服务时间)的前提下,SJF能给出最小的平均等待时间。
-
直观理解:让短任务尽快完成,就像让排队结账时让只买一件商品的人先走,可以减少很多人的等待时间。
二、两种调度模式
SJF有两种实现方案,PPT中清晰地展示了它们:
模式一:非抢占式SJF
-
规则:一旦CPU分配给一个进程,该进程就不能被抢占,直到它完成其当前的CPU区段。
-
特点:在进程完成时才进行调度决策,选择下一个预计服务时间最短的就绪进程。
模式二:抢占式SJF
-
规则:如果一个新进程到达,其CPU区段长度小于当前执行进程的剩余时间,则立即抢占当前进程。
-
别名:最短剩余时间优先。
三、举例
进程 | 到达时间 | 服务时间 |
---|---|---|
P1 | 0 | 7 |
P2 | 2 | 4 |
P3 | 4 | 1 |
P4 | 5 | 4 |
如果是非抢占式SJF,我们来画一下对应的甘特图:
所以平均等待时间是(0+6+3+7)/4=4
如果是抢占式调度:
最后得到平均等待时间:(9+1+0+2)/4=3
我们也可以用表格的形式来解决上面的例子,我们就以非抢占式SJF为例来画一下表格:
甘特图和表格法我们至少需要掌握其中一种。
✅ SJF 是一种特殊的优先级调度
SJF = Shortest Job First(最短作业优先)
- 它的“优先级”是根据预测的下一次 CPU 使用时间来定的。
- 预测越短 → 优先级越高 → 先执行
✅ 举个例子:
- 进程 A 需要 5ms
- 进程 B 需要 10ms → A 优先执行,因为它“短”
⚠️ 问题:Starvation(饥饿)
低优先级的进程可能永远得不到执行!
为什么?
- 如果一直有短任务进来,长任务就会一直等。
- 就像食堂里总有人插队,你站了好久还没轮到……
✅ 解决方案:Aging(老化)
随着时间推移,等待越久的进程,优先级自动升高!
👉 类比:你在排队买票,排了1小时没人理你,售票员说:“这位朋友,请先买!”(给你加了个优先级)
这样就不会有人“饿死”了。
为了解决“饥饿”的问题,我们可以使用高响应比优先调度算法来决定进程的调度。
还是同样的例子,如果是非抢占式调度,请完善以下表格:
作业 | 到达时间 | 服务时间 | 开始时间 | 结束时间 | 周转时间 | |
P1 | 0 | |||||
P2 | 2 | |||||
P3 | 4 | |||||
P4 | 5 |
进程 | 到达时间 | 服务时间 |
---|---|---|
P1 | 0 | 7 |
P2 | 2 | 4 |
P3 | 4 | 1 |
P4 | 5 | 4 |
现在我们要计算每个进程的响应比来决定哪个进程优先调度:
在0时刻,只有进程P1,所以进程P1优先被调度,得到进程P1的开始时间是0,结束时间是7;
P1执行完以后,P4,P2,P3都已经到达,此时需要计算他们各自的响应比来决定进程的优先级:P2的等待时间:5,服务时间:4,响应比:(4+5)/4=2.25
P3的等待时间:3,服务时间:1,响应比:(3+1)/1=4
P4的等待时间:2,服务时间:4,响应比:(2+4)/4=1.5
所以先执行P3,P3执行完以后,到达时刻8,此时还需要计算P2,P4的响应比来确定优先级:P2的等待时间:6,服务时间:4,响应比:(4+6)/4=2.5
P4的等待时间:3,服务时间:4,响应比:(3+4)/4=1.75
所以先调用P2,等到P2执行完以后,到达时刻12,此时只剩下P4了,直接运行即可。
作业 | 到达时间 | 服务时间 | 开始时间 | 结束时间 | 周转时间 | |
P1 | 0 | 7 | 0 | 7 | 7 | |
P2 | 2 | 4 | 8 | 12 | 10 | |
P3 | 4 | 1 | 7 | 8 | 4 | |
P4 | 5 | 4 | 12 | 16 | 11 |
轮转调度/时间片轮转调度(Round Robin)
轮转调度 是专门为分时操作系统设计的,旨在在多个交互式用户之间公平地共享CPU。
核心思想:
-
将CPU的执行时间划分为一个个很小的时间片。
-
每个进程被分配一个时间片,在其时间内运行。
-
当时间片用完时,即使进程没有运行完成,也会被强制剥夺CPU,并排到就绪队列的末尾。
-
然后,调度程序选择就绪队列中的下一个进程,并将CPU分配给它。
这就像一个循环队列,进程在其中轮流执行,因此得名“轮转”。
RR 算法机制
关键参数:时间片
-
大小:通常为 10 毫秒到 100 毫秒,时间片
q
应设置得让 70-80% 的进程能在一个时间片内完成其CPU执行并阻塞(例如,进行I/O操作)。 -
时间片大小的影响至关重要:
-
时间片过大:
-
退化为先来先服务(FCFS) 算法。
-
响应时间变长,交互性变差。
-
-
时间片过小:
-
上下文切换的频率变得非常高。
-
大量的系统开销被浪费在进程切换上,而不是执行用户任务上,导致系统吞吐量下降。
-
因此,时间片的大小必须远大于一次上下文切换所需的时间,否则系统效率会极低。
-
-
比如:有 n 个进程在就绪队列中,时间片为 q
-
每个进程能获得的CPU时间:每个进程最多能获得
1/n
的CPU时间,并且是以最多为 q 的时间块的形式获得的。 -
最大等待时间:没有任何一个进程需要等待超过
(n-1)*q
个时间单位。-
解释:一个进程在最坏情况下,需要等待它前面的 (n-1) 个进程都运行完一个时间片后,才能再次运行。所以最大等待时间是
(n-1)*q
。 -
意义:这保证了响应时间的上限,对于交互式系统至关重要。
-
-
数据结构
-
使用一个先来先服务的就绪队列。
-
新到达的进程被加到队列的末尾。
调度方式
-
绝对是抢占式的。由时钟中断来触发抢占。
-
当时钟中断发生时,正在运行的进程计数器被清零,如果时间片用完,它就被送回就绪队列末尾。
RR 的优缺点
优点
-
公平性:每个进程都能定期获得CPU时间,不会出现“饥饿”现象。
-
响应性好:对于交互式用户,每隔
(n-1) * q
时间(n是就绪进程数,q是时间片)就能获得一次响应,保证了用户操作的流畅体验。 -
易于实现:调度逻辑简单。
缺点
-
平均周转时间较长:对于批处理作业,特别是长作业,由于需要多个时间片才能完成,其周转时间通常比SJF等算法要长。
-
性能依赖于时间片大小:如果时间片设置不当,会严重影响系统性能。
-
对I/O密集型进程不友好:如果一个进程在时间片内频繁进行I/O操作并阻塞,那么它每次被唤醒后都需要在就绪队列末尾重新排队等待,这可能会增加其响应时间。某些系统会对此进行优化(如虚拟轮转)。
举例:以下4各进程几乎同时到达,试计算RR算法下的平均周转时间和响应时间,以及SJF算法下的平均周转时间和响应时间。
图中已经给出了RR算法下的甘特图,我们可以结合甘特图来画一下对应的表格·:
作业 | 服务时间 | 开始时间 | 结束时间 | 周转时间 | 响应时间 |
P1 | 53 | 0 | 134 | 134 | 0 |
P2 | 17 | 20 | 37 | 37 | 20 |
P3 | 68 | 37 | 162 | 162 | 37 |
P4 | 24 | 57 | 121 | 121 | 57 |
由上可以得到RR算法的平均周转时间:(134+37+162+121)/4=113.5
平均响应时间:(0+20+37+57)/4=28.5
结合之前的学习,我们也可以得到SJF算法的平均周转时间:(17 + 41 + 94 + 162) / 4= 78.5
平均响应时间:(0 + 17 + 41 + 94) / 4 = 152 / 4 = 38
一般来说,RR算法有最好响应时间 ,SJF有最好周转时间。
多级队列和多级反馈队列
为什么需要多级?
在早期的操作系统中(如单道批处理系统),通常使用先来先服务(FCFS) 或短作业优先(SJF) 等算法。但这些算法在面对复杂的、多样化的进程环境时(如有交互式进程,也有后台计算进程),显得力不从心。
-
交互式进程(如用户打字):要求响应时间快,希望采用时间片轮转(RR)。
-
后台批处理进程(如科学计算):不需要及时响应,但希望周转时间短,可以采用FCFS或SJF。
如果将所有进程放在同一个队列中用同一种算法调度,很难同时满足这两类进程的需求。于是,产生了分级的思想。
多级队列
核心思想:将就绪队列分割成多个独立的子队列,每个队列具有不同的
-
不同的优先级
-
不同的调度算法
-
固定的进程分类
进程根据其自身类型(如系统进程、交互式进程、批处理进程)在创建时被永久地分配到某个队列中。
工作流程与规则
-
队列划分:通常将队列分为前台(交互)队列和后台(批处理)队列。
-
前台队列:优先级高,采用RR算法(保证响应速度)。
-
后台队列:优先级低,采用FCFS算法(减少调度开销)。
-
-
队列间调度:
-
固定优先级抢占式:只要高优先级队列中有进程,就优先运行该队列中的进程。只有当高优先级队列为空时,才运行低优先级队列中的进程。
-
时间片划分:为每个队列分配一定的CPU时间比例。例如,80%的CPU时间给前台RR队列,20%给后台FCFS队列。
-
示例
假设有三个队列:
-
系统进程队列(优先级最高,RR算法)
-
交互式进程队列(优先级中,RR算法)
-
批处理进程队列(优先级最低,FCFS算法)
调度过程:只要系统进程队列或交互式进程队列有进程,CPU就会优先为它们服务。只有当它们都为空时,批处理进程才能得到执行。
优缺点
-
优点:
-
简单直观,易于实现。
-
能够将不同类型的进程区分对待。
-
-
缺点:
-
不灵活:进程一旦被分配到某个队列,就永远无法改变。如果一个批处理进程实际上是短作业,它也无法被提升优先级。
-
可能产生饥饿:如果高优先级队列中持续有进程到达,低优先级队列的进程可能永远得不到执行。
-
多级反馈队列调度
MLFQ是为了解决多级队列调度“不灵活”和“可能饥饿”的问题而设计的。它是实际操作系统中最为著名的调度算法之一(例如,Unix、Windows等都用其变体)。
设计目标
-
优化周转时间:短作业应该优先执行(像SJF)。
-
优化响应时间:交互式进程应该能快速获得CPU(像RR)。
-
即使不知道进程的类型(是短作业还是长作业)和运行时间,也能高效工作。
关键参数
一个多级反馈队列调度器由以下参数定义:
-
队列数量。
-
每个队列的调度算法(通常队列优先级越高,时间片越短)。
-
决定何时提升进程优先级的方法(通常基于等待时间,即“老化”)。
-
决定何时降低进程优先级的方法(通常是在进程用完其当前队列的时间片时)。
-
决定新进程最初进入哪个队列的方法(通常进入最高优先级队列)
核心思想
-
同样设立多个优先级不同的队列。
-
但进程可以在队列之间移动。
-
核心规则:通过观察进程的历史行为来动态调整其优先级。
工作流程与规则(经典版本)
-
队列设置:
-
设有N个队列(Q0, Q1, Q2, ..., QN-1)。
-
队列优先级从高到低(Q0最高,QN-1最低)。
-
每个队列分配的时间片大小不同:优先级越高的队列,时间片越小(例如Q0=8ms,Q1=16ms,Q2=32ms...)。这保证了短作业能快速完成一轮执行,而长作业可以获得更长的时间片以减少上下文切换。
-
-
新进程到达:
-
一个新进程首先进入最高优先级队列(Q0)。
-
-
进程调度:
-
CPU总是从最高优先级且非空的队列中选取进程来执行。
-
对于同一个队列内的进程,通常采用RR算法。
-
-
进程在队列间移动的规则(关键!):
-
规则1:如果一个进程在时间片用完之前主动放弃CPU(如进行I/O操作)
-
这表明它可能是一个交互式进程。它保持在其当前优先级队列中不变。因为它“表现良好”,没有用完整个时间片。
-
-
规则2:如果一个进程用完了整个时间片仍然没有结束
-
这表明它可能是一个计算密集型的长进程。操作系统会降低其优先级,将其移动到低一级的队列中。
-
-
规则3(防止饥饿):经过一段时间S后,将所有进程都重新拉回最高优先级队列
-
这个规则是为了防止长作业在低优先级队列中饥饿。同时,这也给了长作业一个机会,如果它在此期间变成了交互式进程,它就可以留在高优先级队列。
-
-
示例场景
-
短作业:进入Q0,在第一个小时间片内就执行完毕。周转时间极短,如SJF。
-
交互式进程(如文本编辑器):在Q0中,每次敲击键盘后,它用一小部分时间片处理输入后就进行I/O(等待下一次输入),因此它会一直留在高优先级的Q0,响应速度很快。
-
长作业(如视频编码):
-
首次进入Q0,用完时间片后被降到Q1。
-
在Q1用完更大的时间片后,被降到Q2。
-
... 最终会在最低优先级队列中以FCFS方式运行,偶尔会被规则3重置回Q0。
-
多级反馈队列示例详解
系统参数:
-
Q0:最高优先级,时间片 = 8毫秒,使用RR调度。
-
Q1:中优先级,时间片 = 16毫秒,使用RR调度。
-
Q2:最低优先级,使用FCFS调度。
调度规则:
-
新进程到达:进入最高优先级队列 Q0。
-
在Q0中:
-
进程获得 8ms 的时间片。
-
如果它在 8ms 内完成,则离开系统。
-
如果它未完成,但用完了8ms的时间片,说明它可能是CPU密集型进程,将其降低优先级,移到 Q1 的末尾。
-
-
在Q1中:
-
进程获得 16ms 的时间片。
-
如果它在 16ms 内完成,则离开系统。
-
如果它未完成,但用完了16ms的时间片,说明它很可能是一个长CPU密集型进程,将其再次降低优先级,移到 Q2 的末尾。
-
-
在Q2中:
-
进程按 FCFS 规则运行。由于这是最低队列,进程会一直运行直到完成(或被I/O阻塞)。
-
工作原理解析:
-
奖励I/O密集型(交互式)进程:
-
这类进程通常CPU执行期很短(如键盘输入、鼠标点击),在Q0的8ms时间片内就足以完成并进行I/O操作。因此,它们大部分时间都在高优先级队列中被快速处理,响应时间极佳。
-
-
惩罚CPU密集型进程:
-
这类进程需要很长的CPU时间。它们会很快地用光高优先级队列的时间片,被逐步踢到低优先级队列。
-
虽然它们的响应时间变差,但它们在低优先级队列中获得更长的时间片,这减少了上下文切换的开销,有利于提高系统吞吐量。
-
-
实现“老化”:
-
为了防止Q2中的长作业完全饿死,系统可以定期将Q2中等待时间过长的进程重新提升到Q1甚至Q0。幻灯片中明确指出:"Aging can be implemented this way"。
-
优缺点
-
优点:
-
自适应性强:无需预先知道进程的运行时间,通过反馈机制自动识别进程行为(短作业/交互式/长作业)。
-
能同时兼顾多种类型进程的需求,是多种调度算法优点的集大成者。
-
被证明在实际应用中非常有效。
-
-
缺点:
-
算法复杂,实现开销较大。
-
需要精心设置参数(如队列数量、每个队列的时间片大小、提升优先级的时间间隔S),这些参数会显著影响性能。
-
总结
特性 | 多级队列 | 多级反馈队列 |
---|---|---|
核心思想 | 按进程类型静态分到固定队列 | 根据进程行为动态在队列间移动 |
灵活性 | 低 | 高 |
进程移动 | 不允许 | 允许(升级和降级) |
防饥饿机制 | 通常没有,或很弱 | 有(周期性地提升所有进程优先级) |
复杂度 | 低 | 高 |
适用场景 | 进程类型固定且已知的系统 | 通用操作系统(如Unix, Windows) |
对短作业优化 | 仅当它被分在高优先级队列 | 非常好(自动提升短作业优先级) |