写在前面:
这一部分开始第三章处理机相关内容的学习。处理机是最重要的计算机资源,在多道程序环境下,主存中有着多个进程,其数目往往多于处理机数目。要求系统能按某种算法,动态地把处理机分配给就绪队列中的一个进程,使之执行。分配处理机的任务是由处理机调度程序完成的。
处理机调度的层次:
在多道程序系统中,一个作业被提交后必须经过处理机调度后,方能获得处理机执行。对于批量型作业而言,通常需要经历作业调度(又称高级调度或长程调度)和进程调度(又称低级调度或短程调度)两个过程后方能获得处理机。对于终端型作业,则通常只需经过进程调度即可获得处理机。在较完善的操作系统中,为提高内存的利用率,往往还设置了中级调度(又称中程调度)。
高级调度
高级调度(High Level Scheduling)又称为作业调度或长程调度(LongTerm Scheduling),其主要功能是根据某种算法,把外存上处于后备队列中的那些作业调入内存,也就是说,它的调度对象是作业。作业在批处理系统中提及,批处理系统操作系统学习-1. 操作系统的目标和作用。
这里对作业的概念作简单的介绍。
- 作业(Job)。作业是一个比程序更为广泛的概念,它不仅包含了通常的程序和数据,而且还应配有一份作业说明书,系统根据该说明书来对程序的运行进行控制。在批处理系统中,是以作业为基本单位从外存调入内存的。
- 作业步(Job Step)。通常,在作业运行期间,每个作业都必须经过若干个相对独立,又相互关联的顺序加工步骤才能得到结果,我们把其中的每一个加工步骤称为一个作业步,各作业步之间存在着相互联系,往往是把上一个作业步的输出作为下一个作业步的输入。一个典型的作业可分成三个作业步:① “编译”作业步,通过执行编译程序对源程序进行编译,产生若干个目标程序段;② “连结装配”作业步,将“编译”作业步所产生的若干个目标程序段装配成可执行的目标程序;③ “运行”作业步,将可执行的目标程序读入内存并控制其运行。
- 作业流。若干个作业进入系统后,被依次存放在外存上,这便形成了输入的作业流;在操作系统的控制下,逐个作业进行处理,于是便形成了处理作业流
除此之外与作业相关内容还有作业控制块 JCB(Job Control Block)、作业调度。
- 作业控制块 JCB(Job Control Block):为了管理和调度作业,在多道批处理系统中为每个作业设置了一个作业控制块,如同进程控制块是进程在系统中存在的标志一样,它是作业在系统中存在的标志,其中保存了系统对作业进行管理和调度所需的全部信息。
- 作业调度:作业调度的主要功能是根据作业控制块中的信息,审查系统能否满足用户作业的资源需求,以及按照一定的算法,从外存的后备队列中选取某些作业调入内存,并为它们创建进程、分配必要的资源。然后再将新创建的进程插入就绪队列,准备执行。因此,有时也把作业调度称为接纳调度(Admission Scheduling)。
低级调度
低级调度 (Low Level Scheduling) 称为 进程调度或短程调度 (ShortTermScheduling),它所调度的对象是进程(或内核级线程)。进程调度是最基本的一种调度,在多道批处理、分时和实时三种类型的 OS 中,都必须配置这级调度。
1.低级调度的功能
低级调度用于决定就绪队列中的哪个进程(或内核级线程,为叙述方便,以后只写进程)应获得处理机,然后再由分派程序执行把处理机分配给该进程的具体操作。
低级调度的主要功能如下:
- 保存处理机的现场信息。在进程调度进行调度时,首先需要保存当前进程的处理机的现场信息,如程序计数器、多个通用寄存器中的内容等,将它们送入该进程的进程控制块(PCB)中的相应单元。
- 按某种算法选取进程。低级调度程序按某种算法如优先数算法、轮转法等,从就绪队列中选取一个进程,把它的状态改为运行状态,并准备把处理机分配给它。
- 把处理器分配给进程。由分派程序(Dispatcher)把处理器分配给进程。此时需为选中的进程恢复处理机现场,即把选中进程的进程控制块内有关处理机现场的信息装入处理器相应的各个寄存器中,把处理器的控制权交给该进程,让它从取出的断点处开始继续运行。
2.进程调度中的三个基本机制
- 排队器。为了提高进程调度的效率,应事先将系统中所有的就绪进程按照一定的方式排成一个或多个队列,以便调度程序能最快地找到它。
- 分派器(分派程序)。分派器把由进程调度程序所选定的进程,从就绪队列中取出该进程,然后进行上下文切换,将处理机分配给它。
- 上下文切换机制。当对处理机进行切换时,会发生两对上下文切换操作。在第一对上下文切换时,操作系统将保存当前进程的上下文,而装入分派程序的上下文,以便分派程序运行;在第二对上下文切换时,将移出分派程序,而把新选进程的 CPU 现场信息装入到处理机的各个相应寄存器中。
3.进程调度方式
(1)非抢占方式(Nonpreemptive Mode)。
在采用这种调度方式时,一旦把处理机分配给某进程后,不管它要运行多长时间,都一直让它运行下去,决不会因为时钟中断等原因而抢占正在运行进程的处理机,也不允许其它进程抢占已经分配给它的处理机。直至该进程完成,自愿释放处理机,或发生某事件而被阻时,才再把处理机分配给其他进程。
在采用非抢占调度方式时,可能引起进程调度的因素可归结为如下几个:
- 正在执行的进程执行完毕,或因发生某事件而不能再继续执行;
- 执行中的进程因提出 I/O 请求而暂停执行;
- 在进程通信或同步过程中执行了某种原语操作,如 P 操作(wait 操作)、Block 原语、Wakeup 原语等。
这种调度方式的优点是实现简单,系统开销小,适用于大多数的批处理系统环境。但它难以满足紧急任务的要求——立即执行,因而可能造成难以预料的后果。显然,在要求比较严格的实时系统中,不宜采用这种调度方式。
(2)抢占方式(Preemptive Mode)。
这种调度方式允许调度程序根据某种原则去暂停某个正在执行的进程,将已分配给该进程的处理机重新分配给另一进程。抢占方式的优点是,可以防止一个长进程长时间占用处理机,能为大多数进程提供更公平的服务,特别是能满足对响应时间有着较严格要求的实时任务的需求。但抢占方式比非抢占方式调度所需付出的开销较大。
抢占调度方式是基于一定原则的,主要有如下几条:
- 优先权原则。通常是对一些重要的和紧急的作业赋予较高的优先权。当这种作业到达时,如果其优先权比正在执行进程的优先权高,便停止正在执行(当前)的进程,将处理机分配给优先权高的新到的进程,使之执行;或者说,允许优先权高的新到进程抢占当前进程的处理机。
- 短作业(进程)优先原则。当新到达的作业(进程)比正在执行的作业(进程)明显的短时,将暂停当前长作业(进程)的执行,将处理机分配给新到的短作业(进程),使之优先执行;或者说,短作业(进程)可以抢占当前较长作业(进程)的处理机。
- 时间片原则。各进程按时间片轮流运行,当一个时间片用完后,便停止该进程的执行而重新进行调度。这种原则适用于分时系统、大多数的实时系统,以及要求较高的批处理系统
中级调度
中级调度(Intermediate Level Scheduling)又称中程调度(Medium-Term Scheduling)。引入中级调度的主要目的是为了提高内存利用率和系统吞吐量。为此,应使那些暂时不能运行的进程不再占用宝贵的内存资源,而将它们调至外存上去等待,把此时的进程状态称为就绪驻外存状态或挂起状态。当这些进程重又具备运行条件且内存又稍有空闲时,由中级调度来决定把外存上的那些又具备运行条件的就绪进程重新调入内存,并修改其状态为就绪状态,挂在就绪队列上等待进程调度。
中级调度实际上就是存储器管理中的对换功能,我们将在储存器管理中做详细阐述。
根据后面的学习,接触到了中级调度,中级调度其实就是进程对换操作,进程对换就是将内存中暂时不能运行的进程或者暂时不用的程序和数据调到外存上,以便整理出足够的内存空间供给已具备运行条件的进程或进程说需要的进程和数据调入内存。更多详细信息可参考:操作系统学习-18. 可重定位分区分配与对换。
三种调度方法小结
进程调度的运行频率最高,在分时系统中通常是 10~100 ms 便进行一次进程调度,因此把它称为短程调度。为避免进程调度占用太多的 CPU 时间,进程调度算法不宜太复杂。
作业调度往往是发生在一个(批)作业运行完毕,退出系统,而需要重新调入一个(批)作业进入内存时,故作业调度的周期较长,大约几分钟一次,因此把它称为长程调度。
由于其运行频率较低,故允许作业调度算法花费较多的时间。中级调度的运行频率基本上介于上述两种调度之间,因此把它称为中程调度。
仅有进程调度的调度队列模型
在分时系统中,通常仅设置了进程调度,用户键入的命令和数据都直接送入内存。对于命令,是由 OS 为之建立一个进程。系统可以把处于就绪状态的进程组织成栈、树或一个无序链表,至于到底采用其中哪种形式,则与 OS 类型和所采用的调度算法有关。例如,在分时系统中,常把就绪进程组织成 FIFO 队列形式。每当 OS 创建一个新进程时,便将它挂在就绪队列的末尾,然后按时间片轮转方式运行。
每个进程在执行时都可能出现以下三种情况:
- 任务在给定的时间片内已经完成,该进程便在释放处理机后进入完成状态;
- 任务在本次分得的时间片内尚未完成,OS 便将该任务再放入就绪队列的末尾;
- 在执行期间,进程因为某事件而被阻塞后,被 OS 放入阻塞队列。
图1. 仅具有进程调度的调度队列模型
具有高级和低级调度的调度队列模型
在批处理系统中,不仅需要进程调度,而且还需有作业调度,由后者按一定的作业调度算法,从外存的后备队列中选择一批作业调入内存,并为它们建立进程,送入就绪队列,然后才由进程调度按照一定的进程调度算法选择一个进程,把处理机分配给该进程。
该模型与上一模型的主要区别在于如下两个方面。
- 就绪队列的形式。在批处理系统中,最常用的是最高优先权优先调度算法,相应地,最常用的就绪队列形式是优先权队列。进程在进入优先级队列时,根据其优先权的高低,被插入具有相应优先权的位置上,这样,调度程序总是把处理机分配给就绪队列中的队首进程。在最高优先权优先的调度算法中,也可采用无序链表方式,即每次把新到的进程挂在链尾,而调度程序每次调度时,是依次比较该链中各进程的优先权,从中找出优先权最高的进程,将之从链中摘下,并把处理机分配给它。
- 设置多个阻塞队列。对于小型系统,可以只设置一个阻塞队列;但当系统较大时,若仍只有一个阻塞队列,其长度必然会很长,队列中的进程数可以达到数百个,这将严重影响对阻塞队列操作的效率。故在大、中型系统中通常都设置了若干个阻塞队列,每个队列对应于某一种进程阻塞事件。
图2. 具有高、低两级调度的调度队列模型
同时具有三级调度的调度队列模型
当在 OS 中引入中级调度后,人们可把进程的就绪状态分为内存就绪(表示进程在内存中就绪)和外存就绪(进程在外存中就绪)。类似地,也可把阻塞状态进一步分成内存阻塞和外存阻塞两种状态。在调出操作的作用下,可使进程状态由内存就绪转为外存就绪,由内存阻塞转为外存阻塞;在中级调度的作用下,又可使外存就绪转为内存就绪。
图3. 具有三级调度时的调度队列模型