Operating System Concept 7th - 5.3 调度算法

5.3.3 优先级调度

最短作业优先算法是优先级算法的一种特殊情况。每个进程都有优先级,CPU会分配给优先级最高的进程。优先级相同的进程按先到先服务的顺序被调度。最短作业优先算法不过是一个优先级与下一次(预测的)所占用CPU的时间成反比的优先级算法。CPU占用时间越长,优先级越低。

注意到我们使用高优先级低优先级来讨论调度。优先级一般会用在某个固定范围内的数字表示,像07,或者04095。但是,对0是表示最高还是最低的优先级并没有统一的意见。一些系统用小的数字表示低优先级,另一些则使用小的数字表示高优先级。这个差异有时会把人搞糊涂。在这本书里,我们用小的数字表示高优先级。

(偷懒省略一个例子……)

优先级分内部优先级和外部优先级。内部优先级是使用某个或某些可测量的数值来计算出一个进程的优先级。比如,使用时间限制、内存需求、打开文件的数量、平均IO使用时间和平均CPU使用时间的比率等来计算优先级。外部优先级是由操作系统外部的标准所设定的,像进程的重要性、投入软件开发的资金类型和数目、项目出资方和其他一些(通常是政治)因素。

优先级调度可以是抢占式或非抢占式的。当一个进程到达就绪队列,它的优先级就会被拿去和正在运行的进程比较。如果新到进程的优先级比正在运行的进程高,抢占式的优先级调度算法就会把CPU抢过来给新到进程;非抢占式的优先级算法则是简单地把新到的进程放在就绪队列的队头。

优先级调度算法的一个主要问题是无限阻塞,或者叫挨饿。一个进程处于就绪状态,但正在等待被分配到CPU的时候称为阻塞。优先级调度算法有可能让一些优先级低的进程无限的阻塞下去。在一个重度负载的计算机系统中,络绎不绝的高优先级进程会让低优先级的进程无法得到CPU。一般来说,会出现两种情况其中的一种:要么进程最后还是被执行了(在系统负荷终于减轻的时候,例如在星期天的凌晨两点),要么系统最后崩溃丢失了所有未完成的进程(据说1973年麻省理工学院关闭一台IBM 7094的时候,他们发现一个在1967年就被提交的低优先级进程还从未被运行过)。

对于低优先级进程无限阻塞问题的一个解决方法是成长。所谓成长,就是逐渐提高系统中长时间等待进程的优先级。比方说优先级的范围取127(低)到0(高),我们将一个等待进程的优先级每15分钟提高1。到最后,就算是一个初始优先级为127的进程也会拥有最高优先级从而被执行。事实上,一个优先级为127的进程成长为一个优先级为0的进程不会花费超过32个小时。

 

5.3.4 循环调度

循环调度(RR)算法是特别为分时系统所设计的。它和先到先服务算法类似,但增加了抢占制度来切换进程。算法中定义了一个很小的时间单元,称为时间片。一个时间片一般为10100毫秒。就绪队列被看作是一个循环队列。CPU调度程序不断遍历就绪队列,按时间片的长短把CPU分配给每个进程。

要实现循环调度,我们还是把进程放到一个FIFO(先进先出)的队列中。新来的进程就添加到队尾。CPU调度程序选取队头的进程,把定时器设置为一个时间片后中断,然后就把进程分发到CPU

接着会发生下面两种情况之一。要么进程的CPU使用时间少于一个时间片。在这种情况下,进程自身会主动释放CPU,然后调度程序就会处理就绪队列中的下一个进程。否则如果当前运行进程的CPU使用时间长于一个时间片的话,计时器时间一到就会产生一个中断到操作系统。一个上下文转换被执行,进程就会被放到就绪队列的队尾,然后CPU调度程序就会选择就绪队列中的下一个进程。

循环调度算法下的平均等待时间通常比较长。

(偷懒省略一个例子……)

在循环调度算法中,没有进程会被分配到连续两个以上时间片的CPU(除非只有一个进程在运行)。如果一个进程的CPU使用时间超过了一个时间片,这个进程就会被抢占并被放回就绪队列中。因此循环调度算法是抢占式的。

如果就绪队列里有n个进程,有q个时间片,那么每个进程就在总共q个时间片中获得n分之一的CPU。每个进程在等到它的下一个时间片之前,一定不会等待超过(n-1)*q个时间单元。假设现在有五个进程,每个时间片的大小为20毫秒,那么每个进程每隔100毫秒就能得到20毫秒的CPU

循环调度算法的性能很大程度上取决于时间片的大小。如果时间片非常的大,那么循环调度算法就变成了先到先服务算法。如果时间片非常的小(比如1毫秒),循环调度算法就被称为处理器共享。理论上,它让n个进程看上去好像各自拥有一个CPU,每个CPU的速度相当于真实CPUn分之一。CDC公司的硬件中曾使用这种方法让一组硬件和十组寄存器实现了十个外围处理器。硬件依次执行每组寄存器中的下一条指令,这样就让一个快速的CPU变成了十个慢速的CPU(实际上,因为处理器的速度比内存快,而每一条指令又要引用内存,所以这些虚拟的CPU不会比十个真实的CPU慢太多)。

在软件中,我们还需要考虑上下文转换对循环调度的性能影响。假设我们现在只有一个进程,它占10个时间单元。如果一个时间片的大小是12个时间单元,那么进程可以在一个时间片之内完成,没有多余的开销。但是如果时间片的大小是6个时间单元,进程就需要两个时间片,那么就需要一次上下文转换。如果时间片占1个时间单元的话,那么就要进行9次上下文转换,相应地就降低了程序的执行速度。

因此,考虑到上下文转换的时间,我们想要把时间片定得大一些。如果上下文转换的时间大约是时间片的百分之十,那么就会有大概百分之十的CPU时间花在上下文转换。实际上,大多数现代操作系统的时间片为10100毫秒不等,而上下文转换需要的时间一般少于10微秒,所以上下文转换的时间只占时间片的很小一部分。

进程执行周期的长短也是取决于时间片的大小。一组进程的平均执行周期也不一定会随着时间片大小的增加而改善。一般说来,如果大多数进程在一个时间片内完成了对CPU的占用,平均周期可以有所缩短。例如,假设有三个进程各自要占用10个时间单元,时间片为1个时间单元,那么平均执行周期为29。但是如果时间片为10,平均执行周期就会降为20。如果算上上下文转换的时间,那么时间片越小,需要上下文转换的次数就越多,平均执行周期也就越长。

虽然时间片应该相对上下文转换的时间来说较大,但也不应该太大。如果时间片太大的话,循环调度算法就降格成了先来先服务算法。按照实践经验,时间片应该大于百分之八十的单次CPU使用时间。

 

5.3.5 多级队列调度

有些情况下进程可以很容易分为不同的组别,人们为此创造了另一种调度算法。例如一个很常见的分类就是前台(交互)进程和后台(批量)进程。因为这两种类型的进程对响应时间有不同的要求,所以可能对调度有不同的需求。另外,前台进程的优先级(外部定义的)往往会高于后台进程。

多级别队列算法把就绪队列分成了几个单独的队列。一般根据进程的某个属性(像占用内存的大小、进程优先级或进程类型等)把进程分配到相应的队列中。每个队列都拥有自己的调度算法。比方说,前台进程和后台进程使用单独的队列,可能前台进程使用的是循环调度算法,而后台进程使用的是先到先服务算法。

另外,队列之间也必须要有调度,通常是使用固定优先级的抢占式调度。例如前台进程队列比后台进程队列更有可能拥有绝对优先级。

让我们来看一个多级队列调度的例子,例子中有五个队列,在下面按优先级由高到低的顺序分别列举出来:

1、  系统进程

2、  交互进程

3、  交互的编辑进程

4、  批量进程

5、  学生进程

每个队列对优先级比自己低的队列都拥有绝对优先级。比方说,只有在系统进程、交互进程和交互的编辑进程队列都为空的时候,批量进程队列里的进程才能得以运行。如果一个批量进程正在运行的时候,就绪队列中来了一个交互的编辑进程,那么批量进程就会被抢占。

队列间也可以使用分时调度,这样的话每个队列会得到固定份额的CPU时间,用来调度在队列里面不同的进程。比如在前后台进程队列的例子中,前台进程队列可以得到百分之八十的CPU时间来使用循环调度处理它的进程,而后台进程就只有百分之二十的CPU时间来实现它的先来先服务调度。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值