文章目录
前言知识
CPU调度
处理机调度分为三个级别:高级(作业)调度、中级(内存)调度、低级(进程)调度。一进程在 CPU 上的一次连续执行过程称为该进程的一个 CPU 周期。一个 CPU周期是由进程自我终止的。一个进程通常有若干个长短不等的 CPU 周期。 CPU调度处理是从就绪队列中选择进程并为之分配CPU的问题。
进程调度方式包括抢占方式和非抢占方式两种。在抢占方式下,系统可强行夺走现行进程占用的 CPU,即强行分割现行进程的当前 CPU 周期。在非抢占方式下,系统不能分割当前的CPU 周期,只在一个 CPU 周期执行完后才能重新调度。 基本的调度原则是:尽量提高系统吞吐量,均衡利用资源,对所有作业给予公平服务,对高优先级作业或进程给予优先服务。
CPU调度程序
每当CPU空闲时,操作就必须从就绪队列中选择一个进程来执行。进程选择由短期调度程序(short-term scheduler)或CPU调度程序执行。调度程序从内核中选择一个能够执行的进程,并为之分配CPU。就绪队列不必是先进先出(FIFO)队列。就绪队列可实现为FIFO队列,优先队列,树或简单的无序链表。不过从概念上来说,就绪队列内的所有进程都要排队以等待在CPU上运行。队列中的记录通常为进程控制块(PCB)。
调度准则
不同的CPU调度算法具有不同的属性,且可能对某些进程更为有利。为了比较CPU调度算法,分析员提出了许多准则,这些准则包括如下:
CPU使用率
:需要使CPU尽可能忙。从概念上讲,CPU使用率0%-100%。对于真实系统,它应从40%(轻负荷系统)~90%(重负荷系统)
系统吞吐量
:如果CPU忙于执行进程,那么就有工作在完成。一种测量工作量的方法称为吞吐量,它指一个时间单元内所完成进程的数量。对于长进程,吞吐量可能为每小时一个进程;对于短进程,吞吐量可能为每秒10个进程。
周转时间
:从一个特定进程的角度来看,一个重要准则是运行该进程需要多长时间。从进程提交到进程完成的时间称为周转时间。周转时间为所有时间段之和,包括等待进入内存,在就绪队列中等待,在CPU上执行和I/O执行。
等待时间
:CPU调度算法并不影响进程运行和执行I/O的时间;它只影响进程在就绪队列中等待所花的时间。等待时间为在就绪队列中等待所花费时间之和。
响应时间
:对于交互系统,周转时间并不是最佳准则。通常,进程能相当早就产生输出,并继续计算新结果同时输出以前的结果给用户。因此,响应时间是从提交请求到产生第一响应的时间。这种时间称为响应时间,是从开始响应所需的时间,而不是输出响应所需要的时间。周转时间通常受输出设备速度的限制。
想要得到一个满足所有用户和系统要求的调度算法几乎是不可能的。设计调度程序,一方面要满足特定系统用户的要求(如某些实时和交互进程快速响应要求),另一方面需要考虑系统整体效率(如减少整个系统进程平均周转时间),同时还要考虑调度算法的开销。
调度算法
在操作系统中存在多种调度算法,其中有的调度算法适用于作业调度,有的调度算法适用于进程调度,有的调度算法两者都适用,下面我们来了解几种常用的调度算法:
一、先来先服务调度(First Come First Served,FCFS)
先来先服务调度是最简单的CPU调度算法,其实现过程容易,可采用 FIFO 队列管理。 该调度算法既可以用于作业调度也可以用于进程调度。在作业调度中,算法每次从后备队列中选择最先进入该队列的一个或多个作业,将它们调入内存,分配必要的资源,创建进程并放入就绪队列。
在进程调度中,FCFS每次从就绪队列中选择最先进入该队列的线程,将CPU分配给它,使之投入运行,知道完成或因某种原因而阻塞时才释放CPU。采用FCFS策略的平均等待时间通常不是最小的,且如果进程CPU区间时间变化很大,平均等待时间也会变化很大。
FCFS调度算法是非抢占式的。一旦CPU被分配给了一个进程,该进程会保持CPU直到释放CPU为止,即程序终止或是请求I/O。FCFS算法对于分时系统(每个用户需要定时地得到一定的CPU时间)是特别麻烦的。允许一个进程保持CPU时间过长将是个严重错误。
FCFS算法的特点市算法简单,但效率低下,对长作业比较有利,但对短作业不利(相比SJF和高响应比),有利于CPU繁忙型作业;而不利于I/O繁忙型作业。
二、最短作业优先调度(Shortest Job First,SJF)
短作业(进程)优先调度算法是指对短作业(进程)优先调度的算法。这一算法是从后备队列中选择一个或若干个估计运行时间最短的作业,将它们调入内存运行。而短进程优先(SPF)则是从就绪队列中选择一个估计运行时间最短的进程,将CPU分配给它,使之立即执行,直到完成或发生某事件而阻塞时,才释放CPU。
这一算法将每个进程与其下一个CPU区间段相关联。当CPU为空闲时,它会赋给具有最短CPU区间的进程。如果两个进程具有相同长度,那么可以使用FCFS调度来处理。一个更为适当的表示是最短下一个CPU区间的算法,这是因为调度检查进程的下一个CPU区间的长度,而不是其总长度。
SJF算法的平均等待时间、平均周转时间最少。该算法对短作业或短进程最为有利,它可获得最短的平均周转时间。但它忽略等待时间的长短,对长作业不利,特别是在抢占方式下,可能会使长作业无限延迟。对于抢占式 SJF 进程调度,还需要考虑是按最短原则还是按剩余最短原则抢占。 理论上该方法在等待时间方面是最优的,但实际上无法预测下一个 CPU 瞬时段的长度。
SJF调度算法可证明为最佳的,这是因为对于给定的一组进程,SJF算法的平均等待时间最小。通过将最短进程移到长进程之前,短进程等待时间的减少大于长进程等待时间的增加。因而,平均等待时间减少了。
SJF算法的真正困难是如何知道下一个CPU区间的长度。对于批处理系统的长期(作业)调度,可以将用户提交作业时所指定的进程时间极限作为长度。SJF调度经常用于长期调度。
虽然SJF算法最佳,但是它不能在短期CPU调度层次上加以实现。因为没有办法知道下一个CPU区间的长度。一种方法是近似SJF调度。虽然不知道下一个CPU区间的长度,但是可以预测它。认为下一个CPU区间的长度与以前的相似。因此,通过计算下一个CPU区间长度近似值,能选择具有最短预测CPU区间的进程来进行。
三、优先级调度(Highest Privilege First,HPF)
HPF是让具有高优先级的作业或进程获得优先服务。优先级通常用一个整型的优先数表示。优先级的设置可采用静态的或动态的两种方式。动态设置优先级可使调度更为灵活,使调度性能得到改善。HPF 调度可以是抢占式的或非抢占式的。
优先级调度可通过内部或外部方式来定义。内部定义优先级使用一些测量数据以计算进程优先级。例如,时间极限,内存要求,打开文件的数量和平均I/O区间与平均CPU区间之比都可以用于计算优先级。外部优先级是通过操作系统之外的准则来定义的,如进程重要性,用于支付使用计算机的费用类型和数量,赞助工作的单位,其他因素。
优先级调度可以是抢占或者非抢占的。当一个进程到达就绪队列时,其有优先级与当前运行进程的优先级相比较。如果新到达进程的优先级高于当前运行进程的优先级,那么抢占优先级调度算法会抢占CPU。而非抢占优先级调度算法只是将新进程加到就绪队列的头部。
优先级调度算法的一个主要问题是无穷阻塞(indefinite blocking)或饥饿(starvation)。
可以运行但缺乏CPU的进程可认为是阻塞的,它在等待CPU。优先级调度算法会使某个低优先级进程无穷等待CPU。通常,会发生两种情况,要么进程最终能运行,在系统最后为轻负荷时,要么系统最终崩溃并失去所有未完成的低优先级进程。
低优先级进程无穷等待问题的解决之一是老化(aging)。老化是一种技术,以逐渐增加在系统中等待很长世间的进程的优先级。
四、高响应比优先调度(Highest Response Ratio Next,HRRN)
HRRN最高响应比优先调度算法。该算法的好处是考虑了进程的等待时间,既优待了短作业,又不忽略先来者。它是非抢占式的调度算法。 该算法主要用于作业调度,是对FCFS和SJF的一种综合平衡,同时考虑每个作业的等待时间和估计运行时间。每次进行作业调度时,先计算后备作业中每个作业的响应比,从中选出响应比最高的作业投入运行。
响应比的变化规律可描述为:
响
应
比
R
p
=
等
待
时
间
+
要
求
服
务
时
间
要
求
服
务
时
间
响应比R_p=\frac{等待时间+要求服务时间}{要求服务时间}
响应比Rp=要求服务时间等待时间+要求服务时间
根据公式可知:
- 当作业的等待时间相同时,则要求服务时间越短,其响应比越高,有利于短作业。
- 当要求服务时间相同时,作业的响应比由其等待时间决定,等待时间越长,其响应比越高,因而它实现的是先来先服务。
- 对于长作业,作业的响应比可以随等待时间的增加而提高,当其等待时间足够长时,其响应比便可以升到很高,从而可以获得CPu资源。克服“饥饿”状态,兼顾了长作业。
五、轮转法调度(Round Robin,RR)
RR调度算法主要适用于分时系统。在这种算法中,系统将所有的就绪进程按到达时间的先后顺序排成一个队列,进程调度程序总是选择就绪队列中的第一个进程执行,即先来先服务原则。
RR调度算法每个作业给予一个运行时间片,若一个作业在规定的时间片内未运行完,则挂起该作业并调度另一作业(继续)运行。当所有的作业都运行完分配的一个时间片后,第一个作业才再次得到运行的机会。RR 算法性能依赖于时间片的大小,时间片过大则退化为 FCFS算法,时间片过小时则称为“处理机共享” 。该算法是抢占性算法。 RR调度算法是专门为分时系统设计的。它类似于FCFS调度,但是增加了抢占以切换进程。定义了一个较小时间单元,称为时间片(time quantum,or time slice)。时间片通常为10-100ms。将就绪队列作为循环队列。CPU调度程序循环就绪队列,为每个进程分配一个时间片的CPU。
为了实现RR调度,将就绪队列保存为进程的FIFO队列。新进程增加到就绪队列的尾部。CPU调度程序从就绪队列中选择第一个进程,设置定时器在一个时间片之后中断,再分派该进程。
接下来将可能发生两种情况。进程可能只需要小于时间片的CPU区间。对于这种情况,进程本身自动释放CPU。调度程序接着处理就绪队列的下一个进程。否则,如果当前运行进程的CPU区间比时间片长,定时器会中断并产生操作系统中断,然后进程上下文切换,将进程加入到就绪队列的尾部,接着CPU调度程序会选择就绪队列中的下一个进程。
对于RR调度算法,队列中没有进程被分配超过一个时间片的CPU时间(除非它是唯一可运行的进程)。如果进程的CPU区间超过一个时间片,那么该进程会被抢占,而被放回到就绪队列。RR调度算法是可抢占的。
RR算法的性能很大程序上依赖于时间片的大小。在极端的情况下,如果时间片非常大,那么RR算法与FCFS算法一样。如果时间片很小,那么RR算法称为处理器共享,n个进程对于用户都有它自己的处理器,速度为真正处理器的1/n,那么CPU将在进程间过于频繁切换,使CPU的开销增大,而真正用于运行用户进程的时间将减少。时间片的大长短通常由以下因素确定:系统响应时间、就绪队列中的进程数和系统的处理能力。
六、多级队列调度
多级队列调度算法(multilevel queue scheduling)将就绪队列分成多个独立队列。根据进程的属性,如内存大小、进程优先级、进程类型,一个进程被永久地分配到一个队列中。每个队列都有自己的调度算法。例如,前台进程和后台进程可处于不同队列。前台队列可能采用RR算法调度,而后台队列可能采用FCFS算法调度。
另外,队列之间必须有调度,通常采用固定优先级抢占调度。每个队列与更低层队列相对有绝对优先级。例如,只有系统进程、交互进程和交互编辑进程队列都为空,批处理队列内的进程才可运行。如果在一个批处理进程运行时有一个交互进程进入就绪队列,那么该批处理进程会被抢占。
另一种可能是在队列之间划分时间片。每个队列都有一定的CPU时间,这可用于调度队列内的进程。例如,对于前台-后台队列的例子,前台队列可以有80%的CPU时间用于在进程之间进行RR调度,而后台队列可以有20%的CPU时间采用FCFS算法调度进程。
七、多级反馈队列调度
多级反馈队列调度算法是时间片轮转调度算法和优先级调度算法的综合发展,通过动态调整进程优先级和时间片大小,多级反馈队列调度算法可以兼顾多方面的系统目标。例如:为提高系统吞吐量和缩短平均周转时间而照顾短进程;为获得较好的I/O设备利用率和缩短响应时间而照顾I/O型进程;同时,也不必实现估计进程的执行时间。
多级反馈队列调度算法的实现思想如下:
- 应设置多个就绪队列,并为各个队列赋予不同的优先级,第1级队列的优先级最高,第2级队列次之,其余队列的优先级逐次降低。
- 赋予各个队列中进程执行时间片的大小也各不相同,在优先级越高的队列中,每个进程的运行时间片就越小。
- 当一个新进程进入内存后,首先将它放入第一级队列的末尾,按照FCFS原则排队等待调度。当轮到该进程执行时,如果它能在改时间片内完成,便可准备撤离系统;如果它在一个时间片结束时尚未完成,调度程序便将该进程转入第2级队列的末尾,再同样按FCFS原则等待调度执行…在第n级队列后,便按照时间片轮转的方式运行。
- 仅当第1级队列为空时,调度程序才调度第2级队列中的进程运行;仅当第 1 ∼ ( i − 1 ) 1\sim(i-1) 1∼(i−1)级队列均为空时,才会第哦啊都第 i i i级队列中的进程运行。如果处理器正在执行第 i i i级队列中的某进程时,又有新进程进入优先级较高的队列(第 1 ∼ ( i − 1 ) 1\sim(i-1) 1∼(i−1)中的任何一个队列),则此时新进程将抢占正在执行进程的处理器资源,即由调度程序把正在运行的进程放回到第 i i i级队列的末尾,把处理器资源分配给新到的更高优先级的进程。
多级反馈队列的优势如下:
- 终端型作业用户:短作业优先。
- 短批处理作业用户:周转时间优先。
- 长批处理作业用户:经过前面几个队列得到部分执行,不会长期得不到处理。
通常在使用多级队列调度算法时,进程进入系统时被永久地分配到一个队列。例如,如果前台进程和后台进程分别有独立队列,进程并不从队列转移到另一个队列,这是因为进程并不改变前台或后台性质。这种设置的优点是低调度开销,缺点是不够灵活。与之相反多级反馈队列调度算法(multilevel feedback queue scheduling algorithm)允许进程在队列之间移动。主要思想是根据不同CPU区间的特点以区分进程。如果进程使用过多的CPU时间,那么它会被转移到更低优先级队列。这种方案将I/O约束和交互进程留在更高优先级队列。此外,在较低优先级队列中等待时间过长的进程会被转移到更高优先级队列。这种形式的老化阻止了饥饿的发生。
参考资料:
1、《王道操作系统2019》
2、CPU调度算法总结