一、批处理系统中的调度
1、先来先服务调度
在所有算法中,最简单的是非抢占式的“先来先服务”算法,进程按照他们请求CPU的顺序使用CPU
这个算法的主要有点是易于理解并且便于使用,对于排队的进程而言也是公平的,在这个算法中,一个单链表记录了所有的就绪进程,十分易于实现
但是这个算法有一个明显的缺点,很有可能让CPU密集型进程或者IO密集型进程集中执行,这样,资源利用率会大幅下降,且短进程常常需要消耗大量的时间等待长进程的完成
2、最短作业优先
这个算法适用于运行时间可以预知的进程调度,例如,保险公司因为每天都做类似的工作,所以人们可以相当精确的预测处理1000个索赔的一批作业需要多少时间,由于最短作业优先运行,后续进程的等待时间就会是最短的,平均周转时间就会是最低的
但是,对于并非所有作业都是同时运行的情况,这个调度算法是不适用的,因为最短的作业可能还没有到达
3、最短剩余时间优先
对于并非所有作业都同时运行的情况,如果新到达的作业的运行时间低于当前运行程序的剩余时间,那么就先挂起当前进程,而运行该新进程
这个算法可以使得新的短进程得到良好的服务
与最短作业优先算法一样,只适用于运行时间可以提前掌握的情况
二、交互式系统中的调度
1、轮转调度
最古老、最简单、最公平并且使用最广泛的算法就是“轮转调度”算法
每个进程被分配一个时间段,称为“时间片”,即允许该进程在该时间段内运行,如果在时间片结束时,该进程仍在运行,将剥夺CPU分配给另一个就绪的进程,如果进程提前结束,那么调度程序会立即调度新的就绪进程
时间片轮转很容易实现,只要维护一张可运行进程列表,当一个进程用完他的时间片后,将其移到队列末尾即可,如图所示:
从一个进程切换到另一个进程需要处理很多事务:保存和装入寄存器值以及内存映像、更新各种表哥和列表、清除和重新调入内存高速缓存等,一般称为“进程切换”,有时也称为“上下文切换”,切换往往会耗费大量的CPU时间
因此,如果设置的时间片太短,会导致过多的进程切换降低CPU效率,而设置过长的时间片有会引起端的交互请求响应时间变长(极端的例子就是从抢占式调度算法变成了非抢占式调度算法),一般来说将时间片设置为20 - 50ms是比较合理的
2、优先级调度
轮转调度的隐含假设是:所有的进程同等重要
而事实上,进程常常是由优先级的,这就导致了优先级调度:每个进程都被赋予一个优先级,允许优先级最高的可运行进程先运行,例如在PC机上,交互式进程常常比后台进程要重要,因此被赋予更高的优先级
为了防止高优先级的进程无休止的执行下去,调度进程可以在每个时钟滴答降低当前进程的优先级,如果这个动作导致当前进程优先级低于某个进程,那么就进行进程切换
在UNIX中,有一条命令nice,可以允许用户自愿降低自己进程的优先级,但从未有人用过它
为达到某种目的,优先级可以由系统动态确定也是允许的
如果不偶尔对优先级进行调整,则的优先级进程很可能会产生饥饿现象
3、多级队列
由于设置常时间片比频繁进行进程切换要高效的多,但是长时间片又会影响到系统的响应时间,所以,分级赋予不同长度的时间片就是一个好的方法,如对于最高优先级的进程运行1个时间片,对于次高优先级的进程运行2个时间片,以此类推,每当一个进程用完分配的时间片后,他就被移到下一类
这样,随着进程优先级的不断降低,他的获得时间片数量增长的同时运行频度则会逐渐放慢,从而为短的交互进程让出CPU
对于那些刚开始运行很长一段时间后才开始进行交互的进程,如终端,为了防止其永远处于被惩罚状态,可以才去下面的策略:
只要终端上有回车键按下,则这个终端的所有进程就都被移动到最高优先级,这样做的原因是假设此时进程即将需要交互。但是盲目的使用这种方案可能会使得某些用户为了提高优先级而刻意使用回车,这当然是不希望看到的,而同时,后台进程也有可能永远都得不到运行
这样做常常可以讨好交互用户和进程,但却牺牲了后台进程
4、最短进程有限
交互式进程通常遵循下列模式:等待命令、执行命令、等待命令、执行命令 。。。不断反复
我们也可以把每个命令的执行看作是一个作业,通过优先运行最短作业来使得响应时间最短,这里的关键问题就是系统如何预测一个进程的期望运行时间
一个很有效的方法是根据进程过去的行为推测,有一种老化算法:
如最早的一次程序执行时间为T0,之后的一次执行时间为T1,再之后的一次为T2。。。,那么,就可以得到如下队列:
T0,T0/2+T1/2,T0/4+T1/4+T2/2,T0/8+T1/8+T2/4+T3/2,。。。
这样,先前的估计量的权值会越来越小,这种技术就被称为“老化”
5、保证调度
一种完全不同的调度算法是向用户作出明确的性能保证,然后去实现它
一种很实际并很容易实现的保证是:若用户工作时有n个用户登录,则用户将获得CPU处理能力的1/n,类似的,在一个有n个进程运行的单用户系统中,每个进程都获得1/n的CPU时间
这样看起来足够公平
6、彩票调度
保证调度很难实现,有另一个类似但是十分容易实现的调度算法就是“彩票调度”
彩票调度的基本思想是向进程提供各种系统资源(如CPU时间)的彩票,一旦需要作出一项调度决策时,就随机抽出一张彩票,拥有该彩票的进程获得该资源,比如系统可以掌握每秒50次的一种彩票,作为奖励,每个获奖者可以获得20ms的CPU时间
彩票调度是比较公平的,并且是反应迅速的,因为拥有较大份额彩票的进程会有更大的机会获得资源
对于阻塞程序,它可以把彩票还给系统,之后在阻塞结束后,系统再把彩票还给他,他就可以继续运行了
彩票调度可以用来解决其他方法很难解决的问题,比如一个视频服务器,在该服务器上若干进程正在向其用户提供视频流,每个视频流帧率都不同,假设他们分别是10、20和25帧/秒,如果给这些进程分别分配10、20和25张彩票,他们会自动地按照大致正确的比例划分CPU使用
7、公平分享制度
到目前为止的所有调度方法都有一个共同的缺陷,那就是并不关注进程的所有者,比如用户1启动了9个进程,用户2只启动了1个进程,那么用户1将获得90%的CPU
为了避免这个情况,某些系统在调度处理之前考虑谁拥有进程这一因素,每个用户分配到CPU时间的一部分,而调度程序以一种强制的方式选择进程
三、实时系统中的调度
实时系统是一种时间起着主导作用的系统
典型的,外部的一种或多种物理设备给了计算机一个刺激,而计算机必须在一个确定的时间范围内恰当的反应
比如CD播放器必须在非常短的时间内将驱动器中的位流转换为音乐,否则音乐听起来就会有异常
实时系统通常可以分为“硬实时”和“软实时”
硬实时指必须满足绝对的截止时间,而后者可以允许偶尔的错失截止时间
在这两种情形中,实时系统都是通过将程序划分为一组进程而实现的,其中每个进程的行为是可预测和提前预知的,这些进程一般寿命很短,并且极快的完成
实时系统的事件按照响应方式进一步分类为周期性事件和非周期性时间,一个系统可能要响应多个周期性事件流
实时系统的调度算法可以是静态的或者动态的,前者在系统开始运行前作出调度决策,后者在运行过程中进行调度决策,只有 在可以提前掌握所完成的工作以及必须满足截止时间等全部信息时,静态调度算法才能工作
下面代码转载自新浪微博。
操作系统系统调度算法。