在多道程序系统中,进程的数量往往多于处理机的个数,进程争用处理机的情况就在所难免。 处理机调度是对处理机进行分配,就是从就绪队列中,按照一定的算法(公平、高效)选择一个进程并将处理机分配给它运行,以实现进程并发地执行。
处理机调度是多道程序操作系统的基础,它是操作系统设计的核心问题。
一个作业从提交开始直到完成,往往要经历以下三级调度,如图所示。
三级调度的联系
作业调度从外存的后备队列中选择一批作业进入内存,为它们建立进程,这些进程被送入就绪队列,进程调度从就绪队列中选出一个进程,并把其状态改为运行状态,把CPU分配给它 。中级调度是为了提高内存的利用率,系统将那些暂时不能运行的进程挂起来。当内存空间宽松时, 通过中级调度选择具备运行条件的进程,将其唤醒。
进程调度和切换程序是操作系统内核程序。当请求调度的事件发生后 ,才可能会运行进程调度程序,当调度了新的就绪进程后,才会去进行进程间的切换。理论上这三件事情应该顺序执行, 但在实际设计中,在操作系统内核程序运行时,如果某时发生了引起进程调度的因素,并不一定能够马上进行调度与切换。
现代操作系统 中,不能进行进程的调度与切换的情况有以下几种情况。
如果在上述过程中发生了引起调度的条件,并不能马上进行调度和切换,应设置系统的请求调度标志,直到上述过程结束后才进行相应的调度与切换。
应该进行进程调度与切换的情况有:
进程切换往往在调度完成后立刻发生,它要求保存原进程当前切换点的现场信息,恢复被调度进程的现场信息。现场切换时,操作系统内核将原进程的现场信息推入到当前进程的内核堆栈来保存它们,并更新堆栈指针。内核完成从新进程的内核栈中装入新进程的现场信息、更新当前运行进程空间指针、重设 PC 寄存器等相关工作之后,开始运行新的进程。
所谓进程调度方式是指当某一个进程正在处理机上执行时,若有某个更为重要或紧迫的进程需要处理,即有优先权更高的进程进入就绪队列,此时应如何分配处理机。
通常有以下两种进程调度方式:
1)非剥夺调度方式,又称非抢占方式。是指当一个进程正在处理机上执行时 ,即使有某个更为重要或紧迫的进程进入就绪队列,仍然让正在执行的进程继续执行,直到该进程完成或发生某种事件而进入阻塞状态时,才把处理机分配给更为重要或紧迫的进程。
在非剥夺调度方式下,一旦把 CPU 分配给一个进程,那么该进程就会保持 CPU 直到终止或转换到等待状态。这种方式的优点是实现简单、系统开销小,适用于大多数的批处理系统,但它不能用于分时系统和太多数的实时系统。
2)剥夺调度方式,又称抢占方式。是指当一个进程正在处理机上执行时,若有某个更为重要或紧迫的进程需要使用处理机,则立即暂停正在执行的进程,将处理机分配给这个更为重要或紧迫的进程。
采用剥夺式的调度,对提高系统吞吐率和响应效率都有明显的好处。但 “剥夺” 不是一种任意性行为,必须遵循一定的原则,主要有:优先权、短进程优先和时间片原则等。
在操作系统中存在多种调度算法,其中有的调度算法适用于作业调度,有的调度算法适用于进程调度,有的调度算法两者都适用。下面介绍几种常用的调度算法。
先来先服务 (FCFS)调度算法
FCFS 调度算法属于不可剥夺算法。 从表面上看 ,它对所有作业都是公平的,但若一个长作业先到达系统,就会使后面许多短作业等待很长时间,因此它不能作为分时系统和实时系统的主要调度策略。但它常被结合在其他调度策略中使用。例如,在使用优先级作为调度策略的系统中, 往往对多个具有相同优先级的进程按 FCFS 原则处理。
FCFS调度算法的特点是算法简单,但效率低;对长作业比较有利,但对短作业不利(相对SJF 和高响应比);有利于 CPU 繁忙型作业,而不利于I/O繁忙型作业。
短作业优先(SJF)调度算法
短作业(进程)优先调度算法是指对短作业 (进程) 优先调度的算法。 短作业优先(SJF) 调度算法是从后备队列中选择一个或若干个估计运行时间最短的作业,将它们调入内存运行。而短进程优先(SPF)调度算法,则是从就绪队列中选择一个估计运行时间最短的进程,将处理机分配给它,使之立即执行,直到完成或发生某事件而阻塞时,才释放处理机。
SJF 调度算法也存在不容忽视的缺点:
使用抢占式的短作业优先算法又称为最短剩余时间优先算法:每当有进程加入就绪队列时,如果新到达的进程剩余时间比当前运行的进程剩余时间更短,则由新进程抢占处理机,当前进程重新回到就绪队列。
高响应比优先调度算法
高响应比优先调度算法主要用于作业调度,该算法是对 FCFS 调度算法和 SJF 调度算法的一种综合平衡,同时考虑每个作业的等待时间和估计的运行时间。在每次进行作业调度时 ,先计算后备作业队列中每个作业的响应比,从中选出响应比最高的作业投入运行。
响应比的变化规体可描述为
根据公式可知:
时间片轮转调度算法
时间片轮转调度算法主要适用于分时系统。在这种算法中,系统将所有就绪进程到达时间的先后次序排成一个队列,进程调度程序总是选择就绪队列中第一个进程执行,即先来先服务的原则,但仅能运行一个时间片,如100ms。在使用完一个时间片后,即使进程并未完成其运行 , 它也必须释放出(被剥夺)处理机给下一个就绪的进程,而被剥夺的进程返回到就绪队列的末尾重新排队,等候再次运行。抢占式
在时间片轮转调度算法中,时间片的大小对系统性能的影响很大。如果时间片足够大,以至于所有进程都能在一个时间片内执行完毕,时间片轮转调度算法就退化为先来先服务调度算法。如果时间片很小,那么处理机将在进程间过于频繁切换,使处理机的开销加大,而真正用于运行用户进程的时间将减少。因此时间片的大小应选择适当 。
时间片的长短通常由以下因素确定:系统的响应时间、就绪队列中的进程数目和系统的处理能力。
优先级调度算法
优先级调度算法又称优先权调度算法,该算法既可以用于作业调度,也可以用于进程调度, 该算法中的优先级用来描述作业运行的紧迫程度。
在作业调度中,优先级调度算法每次从后备作业队列中选择优先级最高的一个或几个作业,将它们调入内存,分配必要的资源,创建进程并放入就绪队列。在进程调度中,优先级调度算法每次从就绪队列中选取优先级最高的进程,将处理机分配给它,使之投入运行 。 根据新的更高优先级进程能否抢占正在执行的进程,将该调度算法分为 :
而根据进程创建后其优先级是否可以改变,可以将进程优先级分为以下两种:
多级反馈队列调度算法(集合了前几种算法的优点 )
多级反馈队列调度算法是时间片轮转调度算法和优先级调度算法的综合和发展,如图所示。
通过动态调整进程优先级和时间片大小,多级反馈队列调度算法可以兼顾多方面的系统目标。例如,为提高系统吞吐量和缩短平均周转时间而照顾短进程;为获得较好的I/O设备利用率和缩短响应时间而照顾I/O型进程;同时,也不必事先估计进程的执行时间。
多级反馈队列调度算法的实现思想如下:
多级反馈队列的优势有以下几点。
本节的知识架构图如下:
在信号量机制中,每个要访问临界资源的进程都必须自备同步的PV操作,大量分散的同步操作会给系统管理带来麻烦,且容易因为同步操作不当而导致系统死锁。于是便产生了一种新的进程同步工具——管程(Monitors)。
管程(Monitors):是一个资源管理模块,其中包含了共享资源的数据结构,以及由对该共享数据结构实施操作的一组过程(方法)所组成的资源管理程序。
管程中包含条件变量,用于管理进程的阻塞和唤醒。其形式为 condition x;对它的操作仅有wait和signal。
x.wait:正在调用管程的进程因 x 条件需要被阻塞或挂起,则调用 x.wait 将自己插入到 x 条件的等待队列上,并释放管程,直到 x 条件变化。此时其它进程可以使用该管程。
x.signal:正在调用管程的进程发现 x 条件发生了变化,则调用 x.signal,重新启动一个因 x 条件而阻塞或挂起的进程。(与信号量的signal不同,没有s:=s+1的操作)
个人理解:
相对形象的比喻:假如一个管程叫ATM(取款机),其包含两个方法:存款和取款,不同的人代表不同的进程,但是ATM只允许一个人在一个时间段中进行操作,当一个人在使用时,其他的人只能wait。此外,一个人如果使用的时间太长也不行,所以需要一个条件变量来约束他。
比如一个人在操作ATM时突然接电话了,没法继续操作,把这个原因记为x,执行x.wait,让他离开ATM机,去接电话的队列中等待。等到打完电话,即调用了x.signal后,他就可以继续操作ATM了(一般令正在操作ATM的人操作完后,他才能重新进去)。
管程类似于Java中的类,管程中的“入口”就类似于Java中的方法(synchronized修饰),是一种对共享资源的一种封装。