本文主要参考《计算机操作系统(第四版)》(西安电子科技大学出版社)以及清华大学操作系统公开课(向勇、陈渝),整理操作系统的基本概念,供自己复习查阅。
处理机调度
内存中进程的数目往往多于处理机的数目,这就要求操作系统按照某种算法把处理机动态地分配给处于就绪状态的某个进程,这就是处理机调度(Process Scheduling)。调度的实质就是一种资源分配。
调度层次
- 高级调度,又称作业调度,调度对象是作业,主要功能是决定将外存上处于后备队列的哪些作业调入内存、为它们创建进程分配资源,并将它们放入就绪队列。(高级调度主要存在于多道批处理系统。)
- 中级调度,又称内存调度,主要目的是提高内存利用率和系统吞吐量。该调度会把那些暂时无法运行的进程调到外存等待,此时被调进程的状态称为绪驻(挂起)状态;当它们符合继续运行的条件而且内存也有足够的空间时会被重新调入内存,此时为就绪状态,挂在就绪队列等待,中级调度实质上就是存储器管理中的对换Swap功能。
- 低级调度,又称进程调度,调度对象是进程或者内核级线程,该调度决定就绪队列中的哪个进程应获得处理机,并由分派程序把处理机分配给被选中的进程。进程调度是最基本的调度,即多道批处理、分时、实时系统,都应该配置这类调度。
调度算法的目标
调度算法的选择和设计取决于操作系统的类型,在批处理系统、分时系统和实时系统中,调度算法往往不同。
共同目标
- 提高资源利用率,尤其是提高CPU利用率,CPU利用率即CPU有效工作时间与CPU总运行时间(CPU有效工作时间与CPU空闲时间之和)的比值,故应尽可能使CPU处于忙碌状态;
- 保证公平性,即确保各进程都获得合理的CPU时间;
- 保证平衡性,即根据进程的需求合理地分配资源,尽可能让CPU和外部设备都能经常处于忙绿状态,保证系统资源使用的平衡性;
- 对于某些重要策略,即使会造成工作延迟也要强制准确执行(如安全策略)。
批处理系统的目标
-
平均周转时间短。周转时间即从作业提交到作业完成经过的时间。从用户角度,用户希望自己的作业周转时间最短,但计算机系统管理者总是希望平均周转时间最短。平均周转时间可以表示为: \(T={1\over n}\sum_{i=1}^n T_i\) 为了更好地描述调度的性能,往往采用带权周转时间,即周转时间$T_i$和运行时间$T_s$的比值。平均带权周转时间可以表示为: \(W={1\over n}\sum_{i=1}^n{T_i\over T_s}\)
-
系统吞吐量高,处理机利用率高,吞吐量即单位时间系统完成的作业数,显然长度短的作业更容易完成,而处理机利用率高则要求作业尽可能长。这两个目标是存在一定矛盾的,需要调度算法做出权衡。
分时系统的目标
- 响应时间快,即从用户输入提交一个请求直到得到处理结果为止的时间尽可能短。响应时间包含三部分:一是从输入请求信息直到其被传送至处理机的时间;二是处理机对请求的处理时间;三是把处理结果回传给用户的时间;
- 均衡性,即系统响应的快慢应与用户请求服务的复杂性相适应。
实时系统的目标
- 截止时间的保证。截止时间是指某任务必须开始或必须完成的最迟时间;
- 支持预测,在实时系统中很多请求都是可预测的,如视频的播放,对于可预测的请求可以采用提前处理加多缓冲提高实时性。
作业调度算法
类似地,每个作业也有一个对应的数据结构存储作业的各种运行时信息,这就是作业控制块(Job Control Block,JCB)。作业调度的主要任务是根据JCB中的信息监测资源是否能满足作业的需求,并按照一定的算法从外存后备队列中选取作业进入内存,故其又称接纳调度。每次调度都需决定:1.接纳多少作业;2.接纳哪些作业。
先来先服务算法
先来先服务(First-come First-served,FCFS)算法是最容易想到也是最容易实现的算法。它既可用于作业调度,又能用于进程调度。顾名思义,该算法按作业到达的时间次序进行调度,即等待时间为优先级评判的唯一标准。
短作业优先算法
由于实际情况中短作业往往占大多数,为了让短作业尽快执行,便有了短作业优先(Short Job First,SJF)算法。显然该算法按作业运行时间的长短进行调度。缺点是:
- 必须预知作业多运行时间;
- 对长作业不利;
- 无法实现人机交互;
- 无法优先处理紧迫作业。
优先级调度算法
事实上,前两种算法都不能优先处理紧迫程度高的作业,由此也就诞生了优先级调度算法(Priority-scheduling Algorithm,PSA),该算法的优先级基于作业的紧迫程度,紧迫程度由外部衡量。
高响应比优先调度算法
FCFS算法只考虑作业的等待时间,而SJF只考虑作业的运行时间,对优先级的解释都比较片面。高响应比优先调度(Highest Response Ratio Next)算法则综合考虑了这两点,其规定: \(优先权R_p={系统对作业的响应时间\over 要求服务时间}={等待时间+要求服务时间\over 要求服务时间}\) 当作业的等待时间相同时,要求服务时间越短,优先级越高,类似SJF;当要求服务时间相同时,等待时间越长,优先级越高,类似FCFS;对于长作业,其优先级也会随着等待时间慢慢提高,不至于最后执行。可见该算法实现了较好的平衡。但不可忽视的是,响应比是需要动态更新的,这无疑会增加系统开销。
进程调度算法
进程调度是操作系统中不可或缺的一级调度,也是对处理机性能影响最大的一种处理机调度。进程调度的主要任务是:保护处理机的现场信息;按某种算法选取进程;把处理机分配给进程。
调度方式
主要分为抢占方式和非抢占方式。
非抢占方式
非抢占方式(Nonpreemptive Mode)即一旦把处理机分配给某个进程,就让它一直运行直到其完成,不会因为任何原因去抢占当前正在运行进程的处理机。它的优点是实现简单,系统开销小,适用于批处理系统。
抢占方式
抢占方式(Preemptive Mode)即调度程序会根据某种原则去暂停某个正在执行的进程,把已分配给该进程的处理机重新分配给其他进程。采用抢占方式才能在分时系统实现人机交互,在实时系统满足实时任务的需求。抢占不是任意性行为,必须遵循一定的原则:
- 优先权优先,即允许优先级高的新进程抢占当前进程的处理机;
- 短进程优先,即允许新的短进程抢占当前长进程的处理机;
- 时间片原则,即各进程按时间片轮转运行,当正在执行的进程的一个时间片用完后便停止执行并重新调度。
轮转调度算法
在分时系统中最简单的也是最常用的,就是基于时间片的轮转(Round Robin,RR)调度算法。在这个算法中,系统把所有就绪进程按FCFS排成一就绪队列,并让队首进程轮流出队,把CPU分配给出队进程并让它执行一个时间片。系统可以设置每隔一定时间产生依次中断,以激活调度程序进行重新调度。
进程切换的时机有两个:一个时间片结束之前该进程就已经完成时,立即激活调度程序重新调度,启动一个新时间片;一个时间片用完时,计时器中断处理程序会被激活,此时若进程未完成,则会被送入就绪队列尾。
时间片的大小也是需要确定的一个重要参数。时间片过短则利于短作业,但也意味着会频繁地进行进程调度和进程上下文切换,增加系统开销。时间片过长,极端情况下每个进程都能在一个时间片内完成,RR算法也就退化成了FCFS算法。较可取的时间片长度是略长于一次典型交互所需的时间。
优先级调度算法
在时间片轮转调度算法中,其实隐含了一个假设:所有进程的紧迫程度相同。但实际情况肯定并非如此,为了满足实际情况,需要在调度算法中引入优先级,进而形成优先级调度算法。优先级调度又可以分为抢占式和非抢占式,抢占式常用于对实时性要求较高的系统中。优先级又可以分为静态优先级和动态优先级。
多队列调度算法
前述的各种调度算法均是基于一个就绪队列的,即进程(低级)调度算法是单一的,多队列调度算法能在一定程度上弥补这个缺点。多队列调度把就绪队列拆分为多个,把类型或性质不同的进程分配到不同的队列,不同的队列还可以采用不同的调度算法。
多级反馈队列调度算法
如果未指明进程长度,则短进程优先和基于进程长度的抢占式调度都无法实现。而多级反馈队列(Multilevel Feedback Queue)调度算法则无须事先知道各进程的执行用时,是目前公认的一种较好的进程调度算法。该算法大致实现如下:
- 设置多个就绪队列,队列的优先级依次降低,队列优先级越高,其对应的时间片越小。通常某队列的时间片大小是上一队列的两倍。
- 除最后一个队列外,每个队列都采用FCFS算法。新进程进入内存后首先进入第一个队列,按FCFS原则等待调度。若进程可以在一个时间片内完成则撤出,否则把它移入下一个队列队尾等待调度,以此类推。当进程被降至最后一个队列时,则采用RR算法运行。
- 调度时首先按队列优先级调度,即若要调度第i队列的进程,则要求第1~i-1队列都空闲。若某队列的某进程运行时有新的进程进入优先级更高的队列,则需立即把该进程放回队尾,并把处理机分配给新进程。
基于公平原则的调度算法
以上各种算法都只是保证优先运行,并没有考虑调度的公平性。常用的可保证公平性的算法有两种:保证调度算法和公平分享调度算法。保证调度算法会保证每个进程都获得同等的处理机时间。公平分享调度算法则会保证每个用户都获得同等的处理机时间。
实时调度算法
在实时系统中,实时调度必须能满足实时任务对截止时间的要求。为了实现实时调度,调度程序需要了解有关任务的信息:就绪时间、开始截止时间和完成截止时间、处理时间、资源要求、优先级等。
实时系统对处理机的要求也比较高,对于有N个处理机系统,假设有m个硬实时任务,第i个任务的处理时间为$C_i$,周期为$P_i$,则系统必须满足下面的条件才能调度这些任务: \(\sum_{i=1}^m {C_i\over P_i} \le N\)
调度方式
按调度方式可以把实时调度算法分为非抢占式和抢占式两类。
非抢占式调度算法
非抢占式又可以分为两类。其中非抢占式轮转调度则按队列轮转,任务完成则入队尾,该调度用于要求不太严格的实时系统;而非抢占式优先调度则允许某些进程具有较高的优先级,这些任务到达时可以直接入队首,该调度用于有一定要求的实时系统。
抢占式调度算法
基于抢占发生时间的不同又可以细分为两类:基于时钟中断的抢占(抢占等到下一时钟中断发生)和立即抢占(只要当前任务不处于临界区则立即抢断)。
最早截止时间优先算法
最早截止时间优先(Earliest Deadline First,EDF)即根据任务的截止时间确定优先级,截止时间越早,在队列的位置越靠前,调度程序总是选择队首进程执行。
最低松弛度优先算法
最低松弛度优先(Least Laxity First,LLF)则根据任务的紧急(松弛)程度确定优先级,紧急程度则根据必须完成时间、运行时间和当前时间综合考量。假设一个任务必须在时刻200ms时完成,而执行这个任务需要100ms,则这个任务在0时刻的紧急程度就是100ms,在100ms时刻的紧急程度为0(此时再不执行则无法按时完成)。松弛度的计算为: \(松弛度=必须完成时间-本身运行时间-当前时间\)