目录
多级反馈队列算法的特点(Multi-level Feedback Queue)
一、进程调度的相关知识
(一)进程调度的目标
- 提高系统吞吐量
- 减少进程响应时间
- 确保公平性
- 资源利用率最大化
(二)进程状态与调度
- 进程状态转换
- 就绪态(Ready)
- 运行态(Running)
- 阻塞态(Blocked)
- 调度主要发生在就绪态和运行态之间的转换过程中。当一个运行态进程因时间片用完、等待I/O或其他事件而不能继续运行时,它会从运行态转换为阻塞态或者回到就绪态(如果是时间片用完的情况),此时需要调度程序选择一个新的就绪进程进入运行态。
- 队列管理
- 操作系统通常会维护多个队列来管理进程。
- 就绪队列:存放所有处于就绪态的进程。调度算法会根据一定的规则从这个队列中选择进程进入运行态。
- 阻塞队列:根据不同的阻塞原因(如等待不同的I/O设备)可能会有多个阻塞队列。当阻塞事件完成后,进程会从阻塞队列转移到就绪队列。
二、进程的调度算法
(三)先来先服务(FCFS)调度算法
- 周转时间和带权周转时间
- 周转时间(Turnaround Time):是指从进程提交(到达就绪队列)到进程完成的时间间隔。
- 带权周转时间(Weighted Turnaround Time):是周转时间与执行时间的比值,它反映了进程在系统中的相对等待和执行效率。
- 平均周转时间和平均带权周转时间
(四)短作业优先(SJF)调度算法
- 可抢占式和非抢占式SJF
- 非抢占式SJF:一旦一个进程开始运行,它就会一直运行直到完成,即使在运行过程中有更短的作业到达就绪队列。
- 可抢占式SJF:如果在一个进程运行过程中,有一个比它执行时间更短的进程到达就绪队列,那么当前运行进程会被抢占,更短的进程会立即开始运行
- SJF的最优性
- 在所有非抢占式调度算法中,SJF算法可以使平均周转时间最短。
(五)时间片轮转(RR)调度算法
- 时间片的选择
- 时间片的大小对系统性能有很大影响。
- 如果时间片过大,例如接近甚至大于最长进程的执行时间,那么RR算法就会退化成FCFS算法,长作业会一直占用CPU,短作业的响应时间会变长。
- 如果时间片过小,进程切换的开销就会占主导地位。因为每次切换进程都需要保存当前进程的上下文(如寄存器的值、程序计数器等),并加载下一个进程的上下文,过多的切换会浪费大量的CPU时间。
- 性能分析
- 设n为就绪队列中的进程数,q为时间片大小,对于一个给定的进程,它的周转时间T取决于它在队列中的位置和执行时间。如果进程的执行时间t≤q,那么它的周转时间T=t+(n−1)q(因为它最多需要等待(n−1)个时间片的其他进程执行完)。如果t>q,情况会更复杂,需要考虑进程被多次中断和重新调度的情况。
(六)优先级调度算法
- 静态优先级
- 静态优先级在进程创建时就确定,并且在进程的整个生命周期内保持不变。确定静态优先级的因素可能包括进程的类型(如系统进程优先级高于用户进程)、进程对资源的需求(如对内存需求小的进程优先级高)等。
- 缺点是缺乏灵活性,一旦确定可能会导致低优先级进程长时间得不到CPU资源,即出现“饥饿”现象。
- 动态优先级
- 动态优先级可以根据进程的运行状态进行调整。例如,一个进程等待的时间越长,它的优先级可以越高,这样可以避免进程的“饥饿”现象。一个进程占用CPU时间过长时,它的优先级可以降低,以便让其他进程有机会运行。这种算法需要更多的系统开销来维护优先级的动态调整,但可以提供更公平和高效的资源分配。
【题目】进程的调度算法的例题
1. [简答题] 设有4个作业J1、J2、J3、J4,它们的到达时间和计算时间见下表。若这4个作业在一台处理器上按单道方式运行,采用最高响应比优先调度算法,试写出各作业的执行顺序,各作业的周转时间,以及计算平均周转时间。要求写出计算过程。
作业 | 到达时间 | 计算时间 | 作业开始时间 | 作业结束时间 | 周转时间 |
J1 | 8:00 | 2h | |||
J2 | 8:30 | 40min | |||
J3 | 9:00 | 25min | |||
J4 | 9:30 | 30min |
作业 | 到达时间 | 计算时间 | 作业开始时间 | 作业结束时间 | 周转时间 |
---|---|---|---|---|---|
J1 | 8:00 | 2h(120min) | 8:00 | 10:00 | 120min |
J2 | 8:30 | 40min | 10:25 | 11:05 | 155min |
J3 | 9:00 | 25min | 10:00 | 10:25 | 85min |
J4 | 9:30 | 30min | 11:05 | 11:35 | 125min |
- 分析作业执行顺序
- 8:00时,只有J1到达,所以J1先执行。
- J1的计算时间为2h=120min,J1在8:00开始执行,10:00结束。
- 在10:00时,J2、J3、J4都已到达。
- 对于J2:到达时间为8:30,等待时间t2=10:00−8:30=90min,计算时间b2=40min,响应比R2=4090+40=40130=3.25。
- 对于J3:到达时间为9:00,等待时间t3=10:00−9:00=60min,计算时间b3=25min,响应比R3=2560+25=2585=3.4。
- 对于J4:到达时间为9:30,等待时间t4=10:00−9:30=30min,计算时间b4=30min,响应比R4=3030+30=2。
- 因为R3>R2>R4,所以下一个执行的作业是J3。
- J3在10:00开始执行,10:25结束。
- 在10:25时,J2和J4还在等待。
- 对于J2:到达时间为8:30,等待时间t2=10:25−8:30=115min,计算时间b2=40min,响应比R2=40115+40=40155=3.875。
- 对于J4:到达时间为9:30,等待时间t4=10:25−9:30=55min,计算时间b4=30min,响应比R4=3055+30=3085≈2.83。
- 因为R2>R4,所以下一个执行的作业是J2。
- J2在10:25开始执行,11:05结束。
- 最后执行J4,J4在11:05开始执行,11:35结束。
- 所以作业执行顺序为J1、J3、J2、J4。
- 计算各作业的周转时间
- J1:周转时间T1=10:00−8:00=2h=120min。
- J2:周转时间T2=11:05−8:30=2h35min=155min。
- J3:周转时间T3=10:25−9:00=1h25min=85min。
- J4:周转时间T4=11:35−9:30=2h5min=125min。
- 计算平均周转时间
- 平均周转时间T=4T1+T2+T3+T4=4120+155+85+125=4485=121.25min。
综上,作业执行顺序为J1、J3、J2、J4;J1的周转时间为120min,J2的周转时间为155min,J3的周转时间为85min,J4的周转时间为125min;平均周转时间为121.25min。
三、综合的调度算法:多级反馈队列算法
多级反馈队列算法的特点(Multi-level Feedback Queue)
- 多级反馈队列算法不属于单纯的先来先服务、短作业优先、时间片轮转或优先级调度算法中的任何一种,而是一种综合了这些算法思想的更为复杂和灵活的调度算法。它通过多个队列、不同的优先级、时间片设置以及反馈机制,能够在不同的系统负载和进程特性下,提供较好的调度性能。
-
结构特点
- 多级反馈队列调度算法是一种综合的调度算法。它设置了多个就绪队列,每个队列具有不同的优先级,优先级从高到低排列。例如,系统可以设置3个就绪队列,队列1优先级最高,队列3优先级最低。
- 新创建的进程首先进入最高优先级的队列。
-
时间片特点
- 不同优先级的队列通常有不同的时间片大小。一般来说,优先级越高的队列,时间片越小。例如,队列1的时间片可能是5ms,队列2的时间片可能是10ms,队列3的时间片可能是20ms。
-
进程在队列间的移动
- 当一个进程在高优先级队列中用完它的时间片后,它会被移动到下一个低一级优先级的队列中。例如,一个进程在队列1中时间片用完还未完成,就会被移动到队列2。
- 如果一个进程在低优先级队列中等待时间过长,它的优先级可能会被提升,重新进入高一级优先级的队列,这体现了反馈机制。
多级反馈队列的两个问题(10/28)
1. 饥饿问题
原因: 在MLFQ中,如果系统有大量交互型工作,它们会不断占用CPU,导致长工作永远无法得到CPU。这是因为交互型工作频繁地释放CPU以等待I/O操作,从而保持高优先级,而长时间计算密集型工作则逐渐被降级到低优先级队列。
解决方案: 为了缓解饥饿问题,可以周期性地提升所有工作的优先级,确保长工作也能定期获得CPU时间。这种方法通过重新将所有工作加入最高优先级队列,使得长工作有机会与其他高优先级工作轮转分享CPU。
例子: 系统中有三个队列,优先级从高到低分别是Q1、Q2和Q3。每隔一段时间(例如每100ms),系统将所有进程的优先级提升到Q1,这样即使长时间工作的进程被降级到Q3,也能在下一个周期内重新获得高优先级,从而避免饥饿。
2. 欺骗调度程序
原因: 某些用户可能会利用MLFQ的特性,通过在时间片用完之前主动释放CPU(例如调用无关的I/O操作),使进程保持在高优先级,从而占用更多的CPU时间。这种欺骗行为会导致不公平的资源分配,影响系统的公平性和效率。
解决方案: 为了防止欺骗行为,可以为每层队列提供更完善的CPU计时方式,记录一个进程在某一层中消耗的总时间,而不是仅在调度时重新计时。只要进程用完了自己的配额,就将其降到低一优先级的队列中去。这样,即使进程在时间片内主动释放CPU,也无法一直保持高优先级,从而避免欺骗行为的发生。
例子:一个进程在Q1中运行,时间片为20ms。如果进程在10ms时主动释放CPU,系统会记录它已经消耗了10ms的时间片,在消耗时间达到20ms时将其降级到Q2。这样,即使进程在Q1中频繁释放CPU,也无法一直保持在高优先级,从而防止了欺骗行为。
【题目】多级反馈队列算法(MLFQ)
例题:各进程到达就绪队列的时间、需要的运行时间如下表所示。使用多级反馈队列调度算法,分析进程运行的过程。
进程 | 到达时间 | 运行时间 |
---|---|---|
P1 | 0 | 8 |
P2 | 1 | 4 |
P3 | 5 | 1 |
相关队列信息:
-
设置多级就绪队列,各级队列优先级从高到低,时间片从小到大。
-
新进程到达时先进入第1级队列,按FCFS(先来先服务)原则排队等待被分配时间片。若用完时间片进程还未结束,则进程进入下一级队列队尾。如果此时已经在最下级的队列,则重新放回最下级队列队尾。
-
只有第k级队列为空时,才会为k+1级队头的进程分配时间片。
-
被抢占处理机的进程重新放回原队列队尾。
P1(1)->P2(1)->P1(2)- P2(1)->P3(1)->P2(2)- P1(4)->P1(1)
-
t=0时
-
进程P1首先到达,进入第1级队列并开始执行。按照假设的第1级队列时间片q1=1,P1执行1个时间片,此时可以表示为P1(1)。
-
-
t=1时
-
进程P2到达,进入第1级队列。由于P1的时间片用完且未完成,进入第2级队列队尾。此时第1级队列队首为P2,P2执行1个时间片,即P2(1)。
-
-
t=2时
-
P2时间片用完未完成,进入第2级队列队尾。此时第1级队列为空,第2级队列队首为P1(因为之前P1进入了第2级队列),P1执行2个时间片,即P1(2)。
-
-
t=4时
-
P2时间片未用完未完成,在进程P3到达时被抢P2被抢占(新进程到达时如果进入高级队列(这里P3进入第1级队列),只有当高级队列为空时才会为低级队列的进程分配时间片。所以如果P3到达进入第1级队列且第1级队列之前为空,那么P3开始执行),即P2(1)。
-
-
t=5时
-
进程P3到达,进入第1级队列。此时第2级队列还未执行完。由于第1级队列此时为空,P3开始执行1个时间片,即P3(1)。
-
P3执行完1个时间片后完成(因为P3总共需要运行时间为1)。此时第1级队列为空,第2级队列队首为P2(因为之前P2在第2级队列队首),P2执行2个时间片,即P2(2)。
-
-
后续
-
在P2执行完后,第2级队列队首为P1,P1执行4个时间片,即P1(4)。然后由于如时间片用完但未完成,P1再次执行1个时间片P1(1)。
-
*Linux对相关进程调度算法的体现(拓展)
- FCFS在Linux中的体现
- 在Linux的早期版本或者一些简单的任务调度场景中,可以找到类似先来先服务的思想。例如,在一些简单的批处理任务队列中,当没有复杂的优先级或者时间限制时,任务可能按照到达的先后顺序被处理。不过,现代Linux系统中这种纯粹的FCFS应用比较少见,因为它的效率在多任务、多用户环境下相对较低。
- SJF在Linux中的体现
- Linux中的CFS(Completely Fair Scheduler)调度器虽然不是严格意义上的SJF,但在一定程度上借鉴了类似的思想。CFS试图为每个进程提供公平的CPU时间份额,它通过虚拟运行时间(vruntime)的概念来衡量进程应该获得的CPU时间。从某种意义上说,运行时间较短的进程相对更容易获得更多的CPU时间,因为它的虚拟运行时间增长相对较慢,这类似于SJF优先处理短作业的思想。
- RR在Linux中的体现
- Linux中的分时系统(如桌面环境下的多任务处理)采用了类似时间片轮转的思想。Linux将CPU时间划分为很小的时间片,每个进程轮流使用这些时间片。例如,当用户同时打开多个终端窗口运行不同的程序时,这些程序会按照时间片轮转的方式共享CPU资源,使得每个程序都能得到一定的执行机会,从而实现多任务的并发执行。
- 优先级调度在Linux中的体现
- 进程可以被分配不同的优先级,实时进程具有更高的优先级,可以优先获得CPU资源。例如,在一些实时性要求较高的应用场景下,如音频/视频播放、工业控制系统等,相关的进程可以被设置为较高的优先级,以确保它们能够及时得到CPU的处理,避免出现卡顿或者失控等情况。同时,普通用户进程也有自己的优先级范围,系统可以根据进程的行为(如等待时间、占用资源情况等)动态调整其优先级。