|
|
先来先服务算法(First Come First Served,FCFS),也叫做先进先出算法(First In First Out,FIFO),是最简单的一种调度算法。顾名思义,先来先服务的基本思想就是按照任务到达的先后次序来进行调度(如下图所示)。它是一种不可抢占的调度方式,如果当前任务占用着CPU在运行,那么就要一直等到它执行完毕或者因为某种原因被阻塞,才会让出CPU给其他的任务。另外,对于一个被阻塞的任务,当它被唤醒之后,就把它放在就绪队列的末尾,重新开始排队。
|
|
|
|
|
先来先服务算法的最大优点就是简单,易于理解也易于实现。它的缺点也很明显:一批任务的平均周转时间取决于各个任务到达的顺序,如果短任务位于长任务之后,那么将增大平均周转时间。
|
|
|
|
为了改进FCFS算法,减少平均周转时间,人们又提出了短作业优先算法(Shortest Job First,SJF)。SJF算法的基本思路是:各个任务在开始执行前,必须事先预计好它的执行时间,然后调度算法将根据这些预计时间,从中选择用时较短的任务优先执行。SJF算法有两种实现方案:
|
|
|
.不可抢占方式:当前任务正在运行的时候,即使来了一个比它更短的任务,也不会被打断,只有当它运行完毕或者是被阻塞时,才会让出CPU,进行新的调度。
|
|
|
.可抢占方式:如果一个新的短任务到来了,而且它的运行时间要小于当前正在运行的任务的剩余时间,那么这个新任务就会抢占CPU去运行。这种方法,也称为最短剩余时间优先算法(Shortest Remaining Time First,SRTF)。
|
|
|
不可抢占的SJF算法如下图所示,由于任务T3的执行时间最短,所以首先被调度运行,其次是T1和T2。
|
|
|
|
|
可以证明,对于一批同时到达的任务,采用SJF算法将得到一个最小的平均周转时间。例如,假设有四个任务A、B、C、D,它们的运行时间分别是a、b、c和d,假设它们的到达时间是差不多的,调度顺序为A、B、C、D。那么任务A的周转时间为a,B的周转时间为a+b,C的周转时间为a+b+c,D的周转时间为a+b+c+d,因此,最后的平均周转时间为(4a+3b+2c+d)/4,从这个式子来看,显然,只有当a
|
|
|
|
时间片轮转算法(Round Robin,RR)的基本思路是:把系统当中的所有就绪任务按照先来先服务的原则,排成一个队列。然后,在每次调度的时候,把处理器分派给队列当中的第一个任务,让它去执行一小段CPU时间,或者叫时间片。当这个时间片结束的时候,如果任务还没有执行完的话,将会发生时钟中断,在时钟中断里面,调度器将会暂停当前任务的执行,并把它送到就绪队列的末尾,然后执行当前的队首任务。反之,如果一个任务在它的时间片用完之前就已经运行结束了或者是被阻塞了,那么它就会立即让出CPU给其他的任务。
|
|
|
|
.公平性:各个就绪任务平均地分配CPU的使用时间。例如,假设有n个就绪任务,那么每个任务将得到1/n的CPU时间。
|
|
|
.活动性:每个就绪任务都能一直保持着活动性,假设时间片的大小为q,那么每个任务最多等待(n-1)q这么长的时间,就能再次得到CPU去运行。
|
|
|
在采用时间片轮转算法时,时间片的大小q要适当选择,如果选择不当,将影响到系统的性能和效率。
|
|
|
.如果q太大,每个任务都在一个时间片内完成,这就失去了轮转法的意义,退化为先来先服务算法了,这就使各个任务的响应时间变长。
|
|
|
.如果q太小,每个任务就需要更多的时间片才能运行完,这就使任务之间的切换次数增加,从而增大了系统的管理开销,降低了CPU的使用效率。
|
|
|
因此,如何来选择一个合适的q值,既不能太大,也不能太小,这是时间片轮转法的最大问题。一般来说,这个值选在20~50ms是比较合适的。
|
|
|
|
优先级调度算法的基本思路是:给每一个任务都设置一个优先级,然后在任务调度的时候,在所有处于就绪状态的任务中选择优先级最高的那个任务去运行。例如,短作业优先算法其实也是一个优先级算法,每个任务的优先级就是它的运行时间,运行时间越短,优先级越高。
|
|
|
优先级算法可以分为两种:可抢占方式和不可抢占方式。它们的区别在于:当一个任务正在运行的时候,如果这时来了一个新的任务,其优先级更高,那么在这种情形下,是立即抢占CPU去运行新任务,还是等当前任务运行完了再说。
|
|
|
在任务优先级的确定方式上,可以分为静态方式和动态方式两种。
|
|
|
.静态优先级方式:在创建任务的时候就确定任务的优先级,并且一直保持不变直到任务结束。优先级的确定可以依据任务的类型或重要性,例如,系统任务的优先级要高于用户任务,实时任务的优先级要高于非实时任务。静态优先级方式有一个很大的缺点:高优先级的任务会一直占用着CPU运行,而那些低优先级的任务可能会长时间地得不到CPU,一直处于“饥饿”状态。
|
|
|
.动态优先级方式:在创建任务的时候确定任务的优先级,但是该优先级可以在任务的运行过程中动态改变,以便获得更好的调度性能。例如,为了防止静态优先级方式中出现的“饥饿”现象,系统可以根据任务占用CPU的运行时间和它在就绪队列中的等待时间来不断地调整它的优先级。这样,即便是一个优先级比较低的任务,如果它在就绪队列中的等待时间足够长,那么它的优先级就会不断提高,最终可以被调度执行。
|
|
|
在优先级算法中,高优先级的任务将抢占低优先级的任务。对于优先级相同的任务,通常的做法是把任务按照不同的优先级进行分组,然后在不同组的任务之间使用优先级算法,而在同一组的各个任务之间使用时间片轮转法。
|
|
|
采用优先级调度算法,还有一个问题就是可能会发生优先级反转的现象。在理想情况下,当高优先级任务处于就绪状态后,会立即抢占低优先级任务而得到执行。但在实际系统当中,在各个任务之间往往需要用到各种共享资源,如I/O设备、信号量、邮箱等等。在这种情形下,可能会出现高优先级任务被低优先级任务阻塞,等待它释放资源,而低优先级任务又在等待中等优先级任务的现象,这种现象称为“优先级反转”。
|
|
|