目录

  • 第三章 处理机调度与死锁
    • 3.1处理机调度的层次
      • 3.1.1 高级调度
      • 3.1.2 低级调度
      • 3.1.3 中级调度
    • 3.2 调度队列模型和调度准则
      • 3.2.1 调度队列模型
      • 3.2.2 选择调度方式和调度算法的若干准则
    • 3.3 调度算法
      • 3.2.1 先来先服务和短作业(进程)优先调度算法
      • 3.3.2 高优先权优先调度算法
      • 3.3.3 基于时间片的轮转调度算法
    • 3.4 实时调度
      • 3.4.1 实现实时调度的基本条件
      • 3.4.2 实时调度算法的分类
      • 3.4.3 常用的集中实时调度算法
    • 3.5 产生死锁的原因和必要条件
      • 3.5.1 产生死锁的原因
      • 3.5.2 产生死锁的必要条件
      • 3.5.2 处理死锁的基本方法
    • 3.6 预防死锁的方法
      • 3.6.1 预防死锁
      • 3.6.2 系统安全状态
      • 3.6.3 利用银行家算法避免死锁
    • 3.7 死锁的检测与解除
      • 3.7.1 死锁的检测
      • 2.7.2 死锁的解除

第三章 处理机调度与死锁

3.1处理机调度的层次

   在多道程序环境下,主存中有着多个进程,其数目往往多于处理机数目。这就要求系统能按某种算法,动态地把处理机分配给就绪队列中的一个进程,使之执行。分配处理机
的任务是由处理机调度程序完成的。由于处理机是最重要的计算机资源,提高处理机的利
用率及改善系统性能(吞吐量、响应时间),在很大程度上取决于处理机调度性能的好坏,因
而,处理机调度便成为操作系统设计的中心问题之一。

3.1.1 高级调度

   高级调度又称为作业调度或长程调度,主要功能是:根据某种算法,把外存上处于后备队列中的那些作业调入内存

  1. 作业和作业步

  (1) 作业。作业是一个比程序更为广泛的概念,它不仅包含了通常的程序和数据, 而且还应配有一份作业说明书,系统根据该说明书来对程序的运行进行控制。在批处理系统中,是以作业为基本单位从外存调入内存的。
  (2) 作业步。通常,在作业运行期间,每个作业都必须经过若干个相对独立, 又相互关联的顺序加工步骤才能得到结果,我们把其中的每一个加工步骤称为一个作业步, 各作业步之间存在着相互联系,往往是把上一个作业步的输出作为下一个作业步的输入。
  (3)作业流。若干个作业进入系统后,被依次存放在外存上,这便形成了输入的作业流;在操作系统的控制下,逐个作业进行处理,于是便形成了处理作业流。

  1. 作业控制块 JCB

  进程控制块是作业在系统中存在的标志,其中保存了系统对作业进行管理和调度所需的全部信息。在 JCB 中所包含的内容因系统而异,通常应包含的内容有:作业标识、用户名称、用户帐户、作业类型(CPU 繁忙型、I/O 繁忙型、批量型、终端型)、作业状态、调度信息(优先级、作业已运行时间)、资源需求(预计运行时间、 要求内存大小、要求 I/O 设备的类型和数量等)、进入系统时间、开始处理时间、作业完成 时间、作业退出时间、资源使用情况等。
  每当作业进入系统时,系统便为每个作业建立一个 JCB,根据作业类型将它插入相应的后备队列中。作业调度程序依据一定的调度算法来调度它们,被调度到的作业将会装入
内存。在作业运行期间,系统就按照 JCB 中的信息对作业进行控制。当一个作业执行结束
进入完成状态时,系统负责回收分配给它的资源,撤消它的作业控制块。

  1. 作业调度

  作业调度的主要功能是根据作业控制块中的信息,审查系统能否满足用户作业的资源需求,以及按照一定的算法,从外存的后备队列中选取某些作业调入内存,并为它们创建
进程、分配必要的资源。然后再将新创建的进程插入就绪队列,准备执行。因此,有时也 把作业调度称为接纳调度。
  对用户而言,总希望自己作业的周转时间尽可能的少,最好周转时间就等于作业的执行时间。然而对系统来说,则希望作业的平均周转时间尽可能少,有利于提高 CPU 的利用
率和系统的吞吐量。为此,每个系统在选择作业调度算法时,既应考虑用户的要求,又能
确保系统具有较高的效率。在每次执行作业调度时,都须做出以下两个决定。
    1) 决定接纳多少个作业 作业调度每次要接纳多少个作业进入内存,取决于多道程序度, 即允许多少个作业同时在内存中运行。当内存中同时运行的作业数目太多时,可能会影响到系统的服务质量,多道程序度的确定应根据系统的规模和运行速度等情况做适当的折衷。
    2) 决定接纳哪些作业 应将哪些作业从外存调入内存,这将取决于所采用的调度算法。最简单的是先来先服务调度算法,这是指将最早进入外存的作业最先调入内存;较常用的一种算法是短作业优先调度算法,是将外存上最短的作业最先调入内存;另一种较常用的是基于作业优先级的调度算法,该算法是将外存上优先级最高的作业优先调入内存;比较好的一种算法是“响应比高者优先”的调度算法。
  在批处理系统中,作业进入系统后,总是先驻留在外存的后备队列上,因此需要有作业调度的过程,以便将它们分批地装入内存。然而在分时系统中,为了做到及时响应,用户通过键盘输入的命令或数据等都是被直接送入内存的,因而无需再配置上述的作业调度机制,但也需要有某些限制性措施来限制进入系统的用户数。

3.1.2 低级调度

  通常也把低级调度称为 进程调度或短程调度,它所调度的对象是进程(或内核级线程)。进程调度是最基本的一种调度,在多道批处理、分时和实时三种类型的 OS 中,都必须配置这级调度。

  1. 低级调度的功能

  (1) 保存处理机的现场信息。在进程调度进行调度时,首先需要保存当前进程的处理机的现场信息,如程序计数器、多个通用寄存器中的内容等,将它们送入该进程的进程控制块(PCB)中的相应单元。
  (2) 按某种算法选取进程。低级调度程序按某种算法如优先数算法、轮转法等,从就绪队列中选取一个进程,把它的状态改为运行状态,并准备把处理机分配给它。
  (3) 把处理器分配给进程。由分派程序把处理器分配给进程。此时需为选中的进程恢复处理机现场,即把选中进程的进程控制块内有关处理机现场的信息装入处理器相应的各个寄存器中,把处理器的控制权交给该进程,让它从取出的断点处开始继续运行。

  1. 进程调度中的三个基本机制

  (1) 排队器。为了提高进程调度的效率,应事先将系统中所有的就绪进程按照一定的方式排成一个或多个队列,以便调度程序能最快地找到它。
  (2) 分派器(分派程序)。分派器把由进程调度程序所选定的进程,从就绪队列中取出该进程,然后进行上下文切换,将处理机分配给它。
  (3) 上下文切换机制。当对处理机进行切换时,会发生两对上下文切换操作。在第一对上下文切换时,操作系统将保存当前进程的上下文,而装入分派程序的上下文,以便分派程序运行;在第二对上下文切换时,将移出分派程序,而把新选进程的 CPU 现场信息装入到处理机的各个相应寄存器中。
  上下文切换将花去不少的处理机时间,即使是现代计算机,每一次上下文切换大约需要花费几毫秒的时间,该时间大约可执行上千条指令。为此,现在已有通过硬件(采用两组或多组寄存器)的方法来减少上下文切换的时间。一组寄存器供处理机在系统态时使用,另一组寄存器供应用程序使用。在这种条件下的上下文切换只需改变指针,使其指向当前寄存器组即可。

  1. 进程调度方式

  (1)非抢占方式
    在采用这种调度方式时,一旦把处理机分配给某进程后,不管它要运行多长时间,都一直让它运行下去,决不会因为时钟中断等原因而抢占正在运行进程的处理机,也不允许其它进程抢占已经分配给它的处理机。直至该进程完成,自愿释放处理机,或发生某事件而被阻塞时,才再把处理机分配给其他进程。
    在采用非抢占调度方式时,可能引起进程调度的因素可归结为如下几个:
    (1) 正在执行的进程执行完毕,或因发生某事件而不能再继续执行;
    (2) 执行中的进程因提出 I/O 请求而暂停执行;
    (3) 在进程通信或同步过程中执行了某种原语操作,如 P 操作(wait 操作)、Block 原语、 Wakeup 原语等。 这种调度方式的优点是实现简单,系统开销小,适用于大多数的批处理系统环境。但 它难以满足紧急任务的要求——立即执行,因而可能造成难以预料的后果。显然,在要求 比较严格的实时系统中,不宜采用这种调度方式。

  (2)抢占方式(Preemptive Mode)
    这种调度方式允许调度程序根据某种原则去暂停某个正在执行的进程,将已分配给该进程的处理机重新分配给另一进程。抢占方式的优点是,可以防止一个长进程长时间占用处理机,能为大多数进程提供更公平的服务,特别是能满足对响应时间有着较严格要求的 实时任务的需求。但抢占方式比非抢占方式调度所需付出的开销较大。抢占调度方式是基于一定原则的,主要有如下几条:
      (1) 优先权原则。通常是对一些重要的和紧急的作业赋予较高的优先权。当这种作业到 达时,如果其优先权比正在执行进程的优先权高,便停止正在执行(当前)的进程,将处理机分配给优先权高的新到的进程,使之执行;或者说,允许优先权高的新到进程抢占当前进
程的处理机。
      (2) 短作业(进程)优先原则。当新到达的作业(进程)比正在执行的作业(进程)明显的短时,将暂停当前长作业(进程)的执行,将处理机分配给新到的短作业(进程),使之优先执行;或者说,短作业(进程)可以抢占当前较长作业(进程)的处理机。
      (3) 时间片原则。各进程按时间片轮流运行,当一个时间片用完后,便停止该进程的执行而重新进行调度。这种原则适用于分时系统、大多数的实时系统,以及要求较高的批处理系统。

3.1.3 中级调度

  中级调度又称中程调度。引入中级调度的主要目的是为了提高内存利用率和系统吞吐量。为此,应使那些暂时不能运行的进程不再占用宝贵的内存资源,而将它们调至外存上去等待,把此时的进程状态称为就绪驻外存状态或挂起状态。当这些进程重又具备运行条件且内存又稍有空闲时,由中级调度来决定把外存上的那些又具备运行条件的就绪进程重新调入内存,并修改其状态为就绪状态,挂在就绪队列上等待进程调度。中级调度实际上就是存储器管理中的对换功能。
  在上述三种调度中,进程调度的运行频率最高,在分时系统中通常是 10~100 ms 便进行一次进程调度,因此把它称为短程调度。为避免进程调度占用太多的 CPU 时间,进程调
度算法不宜太复杂。作业调度往往是发生在一个(批)作业运行完毕,退出系统,而需要重新调入一个(批)作业进入内存时,故作业调度的周期较长,大约几分钟一次,因此把它称为长程调度。由于其运行频率较低,故允许作业调度算法花费较多的时间。中级调度的运行频率基本上介于上述两种调度之间,因此把它称为中程调度。

3.2 调度队列模型和调度准则

3.2.1 调度队列模型

  前面所介绍的高级调度、低级调度以及中级调度,都将涉及到作业或进程的队列,由 此可以形成如下三种类型的调度队列模型。

  1. 仅有进程调度的调度队列模型

  在分时系统中,通常仅设置了进程调度,用户键入的命令和数据都直接送入内存。系统可以把处于就绪状态的进程组织成栈、树或一个无序链表,至于到底采用其中哪种形式,则与 OS 类型和所采用的调度算法有关。
  每个进程在执行时都可能出现以下三种情况:
  (1) 任务在给定的时间片内已经完成,该进程便在释放处理机后进入完成状态;   (2) 任务在本次分得的时间片内尚未完成,OS 便将该任务再放入就绪队列的末尾;
  (3) 在执行期间,进程因为某事件而被阻塞后,被 OS 放入阻塞队列。

          图 3-1 示出了仅具有进程调度的调度队列模型。

  1. 具有高级和低级调度的调度队列模型
      在批处理系统中,不仅需要进程调度,而且还需有作业调度,由后者按一定的作业调度算法,从外存的后备队列中选择一批作业调入内存,并为它们建立进程,送入就绪队列,然后才由进程调度按照一定的进程调度算法选择一个进程,把处理机分配给该进程。

图 3-2 示 出了具有高、低两级调度的调度队列模型。该模型与上一模型的主要区别在于如下两个方面。

  (1) 就绪队列的形式。在批处理系统中,最常用的是最高优先权优先调度算法,相应地, 最常用的就绪队列形式是优先权队列。进程在进入优先级队列时,根据其优先权的高低, 被插入具有相应优先权的位置上,这样,调度程序总是把处理机分配给就绪队列中的队首 进程。在最高优先权优先的调度算法中,也可采用无序链表方式,即每次把新到的进程挂在链尾,而调度程序每次调度时,是依次比较该链中各进程的优先权,从中找出优先权最高的进程,将之从链中摘下,并把处理机分配给它。显然,无序链表方式与优先权队列相 比,这种方式的调度效率较低。
  (2) 设置多个阻塞队列。对于小型系统,可以只设置一个阻塞队列;但当系统较大时, 若仍只有一个阻塞队列,其长度必然会很长,队列中的进程数可以达到数百个,这将严重影响对阻塞队列操作的效率。故在大、中型系统中通常都设置了若干个阻塞队列,每个队列对应于某一种进程阻塞事件。

  1. 同时具有三级调度的调度队列模型
      当在 OS 中引入中级调度后,人们可把进程的就绪状态分为内存就绪和外存就绪。类似地,也可把阻塞状态进一步分成内存阻塞和外存阻塞两种状态。在调出操作的作用下,可使进程状态由内存就绪转为外存就绪,由内存阻塞转为外存阻塞;在中级调度的作用下,又可使外存就绪转为内存就绪。
            图 3-3 示出了 具有三级调度的调度队列模型。

3.2.2 选择调度方式和调度算法的若干准则

  1. 面向用户的准则

  (1) 周转时间短。通常把周转时间的长短作为评价批处理系统的性能、选择作业调度方式与算法的重要准则之一。所谓周转时间,是指从作业被提交给系统开始,到作业完成为止的这段时间间隔(称为作业周转时间)。它包括四部分时间:
      作业在外存后备队列上等待 (作业)调度的时间,
      进程在就绪队列上等待进程调度的时间,
      进程在 CPU 上执行的时间,
      进程等待 I/O 操作完成的时间。
  其中的后三项在一个作业的整个处理过程中可能会发生多次。
  对每个用户而言,都希望自己作业的周转时间最短。但作为计算机系统的管理者,则总是希望能使平均周转时间最短,这不仅会有效地提高系统资源的利用率,而且还可使大多数用户都感到满意。
平均周转时间描述:

            
作业的周转时间 T 与系统为它提供服务的时间 T s 之比,即 W = T/Ts ,称为带权周转时间,
平均带权周转时间:

            
  (2) 响应时间快。常把响应时间的长短用来评价分时系统的性能,这是选择分时系统中进程调度算法的重要准则之一。所谓响应时间,是从用户通过键盘提交一个请求开始,直至系统首次产生响应为止的时间,或者说,直到屏幕上显示出结果为止的一段时间间隔。 它包括三部分时间:
        从键盘输入的请求信息传送到处理机的时间,
        处理机对请求信息进行处理的时间,
        将所形成的响应信息回送到终端显示器的时间。
  (3) 截止时间的保证。这是评价实时系统性能的重要指标,因而是选择实时调度算法的 重要准则。所谓截止时间,是指某任务必须开始执行的最迟时间,或必须完成的最迟时间。 对于严格的实时系统,其调度方式和调度算法必须能保证这一点,否则将可能造成难以预 料的后果。
  (4) 优先权准则。在批处理、分时和实时系统中选择调度算法时,都可遵循优先权准则, 以便让某些紧急的作业能得到及时处理。在要求较严格的场合,往往还须选择抢占式调度 方式,才能保证紧急作业得到及时处理。

  1. 面向系统的准则

  (1) 系统吞吐量高。这是用于评价批处理系统性能的另一个重要指标,因而是选择批处理作业调度的重要准则。由于吞吐量是指在单位时间内系统所完成的作业数,因而它与批处理作业的平均长度具有密切关系。对于大型作业,一般吞吐量约为每小时一道作业;对于中、小型作业,其吞吐量则可能达到数十道作业之多。作业调度的方式和算法对吞吐量的大小也将产生较大影响。事实上,对于同一批作业,若采用了较好的调度方式和算法, 则可显著地提高系统的吞吐量。
  (2) 处理机利用率好。对于大、中型多用户系统,由于 CPU 价格十分昂贵,致使处理机的利用率成为衡量系统性能的十分重要的指标;而调度方式和算法对处理机的利用率起 着十分重要的作用。在实际系统中,CPU 的利用率一般在 40%(系统负荷较轻)到 90%之间。 在大、中型系统中,在选择调度方式和算法时,应考虑到这一准则。但对于单用户微机或 某些实时系统,则此准则就不那么重要了。
  (3) 各类资源的平衡利用。在大、中型系统中,不仅要使处理机的利用率高,而且还应能有效地利用其它各类资源,如内存、外存和 I/O 设备等。选择适当的调度方式和算法可以保持系统中各类资源都处于忙碌状态。 但对于微型机和某些实时系统而言,该准则并不 重要。

3.3 调度算法

3.2.1 先来先服务和短作业(进程)优先调度算法

  1. 先来先服务调度算法 FCSF

  先来先服务(FCFS)调度算法是一种最简单的调度算法,该算法既可用于作业调度,也可用于进程调度。当在作业调度中采用该算法时,每次调度都是从后备作业队列中选择一个或多个最先进入该队列的作业,将它们调入内存,为它们分配资源、创建进程,然后放入就绪队列。在进程调度中采用 FCFS 算法时,则每次调度是从就绪队列中选择一个最先进入该队列的进程,为之分配处理机,使之投入运行。该进程一直运行到完成或发生某事件 而阻塞后才放弃处理机。

  FCFS 算法比较有利于长作业(进程),而不利于短作业(进程)

  下表列出了 A、B、C、 D 四个作业分别到达系统的时间、要求服务的时间、开始执行的时间及各自的完成时间, 并计算出各自的周转时间和带权周转时间。

  从表上可以看出,其中短作业 C 的带权周转时间竞高达 100,这是不能容忍的;而长作业 D 的带权周转时间仅为 1.99。据此可知,FCFS 调度算法有利于 CPU 繁忙型的作业,而不利于 I/O 繁忙型的作业(进程)。CPU 繁忙型作业是指该类作业需要大量的 CPU 时间进行 计算,而很少请求 I/O。通常的科学计算便属于 CPU 繁忙型作业。I/O 繁忙型作业是指 CPU 进行处理时需频繁地请求 I/O。目前的大多数事务处理都属于 I/O 繁忙型作业。
  在此,我们通过一个例子来说明采用 FCFS 调度算法时的调度性能。
  
  图 3-4(a)示出有五个进程 A、B、C、D、E,它们到达的时间分别是 0、1、2、3 和 4,所要求的服务时间分别 是 4、3、5、2 和 4,其完成时间分别是 4、7、12、14 和 18。从每个进程的完成时间中减 去其到达时间,即得到其周转时间,进而可以算出每个进程的带权周转时间。

  1. 短作业(进程)优先调度算法SJ§F

  短作业(进程)优先调度算法 SJ§F,是指对短作业或短进程优先调度的算法。它们可以分别用于作业调度和进程调度。短作业优先(SJF)的调度算法是从后备队列中选择一个或若干个估计运行时间最短的作业,将它们调入内存运行。而短进程优先(SPF)调度算法则是从 就绪队列中选出一个估计运行时间最短的进程,将处理机分配给它,使它立即执行并一直 执行到完成,或发生某事件而被阻塞放弃处理机时再重新调度。
  为了和 FCFS 调度算法进行比较,我们仍利用 FCFS 算法中所使用的实例,并改用 SJ§F 算法重新调度,再进行性能分析。由图 3-4 中的(a)和(b)可以看出,采用 SJ§F 算法后,不 论是平均周转时间还是平均带权周转时间,都有较明显的改善,尤其是对短作业 D,其周 转时间由原来的(用 FCFS 算法时)11 降为 3;而平均带权周转时间是从 5.5 降到 1.5。这说明 SJF 调度算法能有效地降低作业的平均等待时间,提高系统吞吐量。
SJ§F 调度算法也存在不容忽视的缺点:
  (1) 该算法对长作业不利,如作业 C 的周转时间由 10 增至 16,其带权周转时间由 2 增 至 3.1。更严重的是,如果有一长作业(进程)进入系统的后备队列(就绪队列),由于调度程序 总是优先调度那些(即使是后进来的)短作业(进程),将导致长作业(进程)长期不被调度。
  (2) 该算法完全未考虑作业的紧迫程度,因而不能保证紧迫性作业(进程)会被及时处理。
  (3) 由于作业(进程)的长短只是根据用户所提供的估计执行时间而定的,而用户又可能 会有意或无意地缩短其作业的估计运行时间,致使该算法不一定能真正做到短作业优先 调度。

3.3.2 高优先权优先调度算法

  1. 优先权调度算法的类型
      为了照顾紧迫型作业,使之在进入系统后便获得优先处理,引入了最高优先权优先(FPF) 调度算法。此算法常被用于批处理系统中,作为作业调度算法,也作为多种操作系统中的 进程调度算法,还可用于实时系统中。当把该算法用于作业调度时,系统将从后备队列中 选择若干个优先权最高的作业装入内存。当用于进程调度时,该算法是把处理机分配给就 绪队列中优先权最高的进程,这时,又可进一步把该算法分成如下两种。

  1)非抢占式优先权算法
  在这种方式下,系统一旦把处理机分配给就绪队列中优先权最高的进程后,该进程便 一直执行下去,直至完成;或因发生某事件使该进程放弃处理机时,系统方可再将处理机 重新分配给另一优先权最高的进程。这种调度算法主要用于批处理系统中;也可用于某些 对实时性要求不严的实时系统中。

  2)抢占式优先权调度算法
  在这种方式下,系统同样是把处理机分配给优先权最高的进程,使之执行。但在其执行期间,只要又出现了另一个其优先权更高的进程,进程调度程序就立即停止当前进程(原 优先权最高的进程)的执行,重新将处理机分配给新到的优先权最高的进程。这种抢占式的优先权调度算法能更好地满足紧迫作业的要求,故而常用于要求比较严格的实时系统中,以及对性能要求 较高的批处理和分时系统中。

  1. 优先权类型

  1)静态优先权
  静态优先权是在创建进程时确定的,且在进程的整个运行期间保持不变。一般地,优先权是利用某一范围内的一个整数来表示的,有的系统用“0”表示最高优先权,当数值愈大时, 其优先权愈低;而有的系统恰恰相反。
  确定进程优先权的依据有如下三个方面:
    (1) 进程类型。通常,系统进程(如接收进程、对换进程、磁盘 I/O 进程)的优先权高于 一般用户进程的优先权。
    (2) 进程对资源的需求。如进程的估计执行时间及内存需要量的多少,对这些要求少的进程应赋予较高的优先权。
    (3) 用户要求。这是由用户进程的紧迫程度及用户所付费用的多少来确定优先权的。 静态优先权法简单易行,系统开销小,但不够精确,很可能出现优先权低的作业(进程) 长期没有被调度的情况。因此,仅在要求不高的系统中才使用静态优先权。

  2)动态优先权
  动态优先权是指在创建进程时所赋予的优先权,是可以随进程的推进或随其等待时间 的增加而改变的,以便获得更好的调度性能。若所有的就绪进程具有各不相同的优先权初值,那么,对于优先权初值低的进程,在等待了足够的时间后,其优先权便可能升为最高,从而可以获得处理机。当采用抢 占式优先权调度算法时,如果再规定当前进程的优先权以速率 b 下降,则可防止一个长作 业长期地垄断处理机。

  1. 高响应比优先调度算法

  在批处理系统中,短作业优先算法是一种比较好的算法,其主要的不足之处是长作业的运行得不到保证。如果我们能为每个作业引入前面所述的动态优先权,并使作业的优先 级随着等待时间的增加而以速率 a 提高,则长作业在等待一定的时间后,必然有机会分配到处理机。该优先权的变化规律可描述为:
      
  由于等待时间与服务时间之和就是系统对该作业的响应时间,故该优先权又相当于响 应比 RP 。据此,又可表示为:

由上式可以看出:
  (1) 如果作业的等待时间相同,则要求服务的时间愈短,其优先权愈高,因而该算法有利于短作业。
  (2) 当要求服务的时间相同时,作业的优先权决定于其等待时间,等待时间愈长,其优先权愈高,因而它实现的是先来先服务。
  (3) 对于长作业,作业的优先级可以随等待时间的增加而提高,当其等待时间足够长时, 其优先级便可升到很高,从而也可获得处理机。 简言之,该算法既照顾了短作业,又考虑了作业到达的先后次序,不会使长作业长期 得不到服务。因此,该算法实现了一种较好的折衷。当然,在利用该算法时,每要进行调度之前,都须先做响应比的计算,这会增加系统开销。

3.3.3 基于时间片的轮转调度算法

  1. 时间片轮转法

  1)基本原理
  在早期的时间片轮转法中,系统将所有的就绪进程按先来先服务的原则排成一个队列, 每次调度时,把 CPU 分配给队首进程,并令其执行一个时间片。时间片的大小从几 ms 到几百 ms。当执行的时间片用完时,由一个计时器发出时钟中断请求,调度程序便据此信号 来停止该进程的执行,并将它送往就绪队列的末尾;然后,再把处理机分配给就绪队列中新的队首进程,同时也让它执行一个时间片。这样就可以保证就绪队列中的所有进程在一 给定的时间内均能获得一时间片的处理机执行时间。换言之,系统能在给定的时间内响应 所有用户的请求。

  2)时间片大小的确定
  在时间片轮转算法中,时间片的大小对系统性能有很大的影响,如选择很小的时间片将有利于短作业,因为它能较快地完成,但会频繁地发生中断、进程上下文的切换,从而 增加系统的开销;反之,如选择太长的时间片,使得每个进程都能在一个时间片内完成, 时间片轮转算法便退化为 FCFS 算法,无法满足交互式用户的需求。
  一个较为可取的大小是, 时间片略大于一次典型的交互所需要的时间。这样可使大多数进程在一个时间片内完成。

    图 3-5 示出了时间片分别为 q=1 和 q=4 时,A、B、C、D、E 五个进程的运行情况,而 图 3-6为 q=1和 q=4时各进程的平均周转时间和带权平均周转时间。图中的 RR(Round Robin) 表示轮转调度算法。

  1. 多级反馈队列调度算法
      前面介绍的各种用作进程调度的算法都有一定的局限性。如短进程优先的调度算法, 仅照顾了短进程而忽略了长进程,而且如果并未指明进程的长度,则短进程优先和基于进程 长度的抢占式调度算法都将无法使用。而多级反馈队列调度算法则不必事先知道各种进程所 需的执行时间,而且还可以满足各种类型进程的需要,因而它是目前被公认的一种较好的进 程调度算法。在采用多级反馈队列调度算法的系统中,调度算法的实施过程如下所述。

  (1) 应设置多个就绪队列,并为各个队列赋予不同的优先级。第一个队列的优先级最高, 第二个队列次之,其余各队列的优先权逐个降低。该算法赋予各个队列中进程执行时间片 的大小也各不相同,在优先权愈高的队列中,为每个进程所规定的执行时间片就愈小。例 如,第二个队列的时间片要比第一个队列的时间片长一倍,……,第 i+1 个队列的时间片要 比第 i 个队列的时间片长一倍。图 3-7 是多级反馈队列算法的示意。
  (2) 当一个新进程进入内存后,首先将它放入第一队列的末尾,按 FCFS 原则排队等待调度。当轮到该进程执行时,如它能在该时间片内完成,便可准备撤离系统;如果它在一 个时间片结束时尚未完成,调度程序便将该进程转入第二队列的末尾,再同样地按 FCFS 原则等待调度执行;如果它在第二队列中运行一个时间片后仍未完成,再依次将它放入第 三队列,……,如此下去,当一个长作业(进程)从第一队列依次降到第 n 队列后,在第 n 队列中便采取按时间片轮转的方式运行。
  (3) 仅当第一队列空闲时,调度程序才调度第二队列中的进程运行;仅当第 1~(i-1)队列均空时,才会调度第 i 队列中的进程运行。如果处理机正在第 i 队列中为某进程服务时, 又有新进程进入优先权较高的队列(第 1~(i-1)中的任何一个队列),则此时新进程将抢占正 在运行进程的处理机,即由调度程序把正在运行的进程放回到第 i 队列的末尾,把处理机分配给新到的高优先权进程。

  1. 多级反馈队列调度算法的性能
    多级反馈队列调度算法具有较好的性能,能很好地满足各种类型用户的需要。

(1) 终端型作业用户。由于终端型作业用户所提交的作业大多属于交互型作业,作业通常较小,系统只要能使这些作业(进程)在第一队列所规定的时间片内完成,便可使终端型作 业用户都感到满意。

(2) 短批处理作业用户。对于很短的批处理型作业,开始时像终端型作业一样,如果仅在第一队列中执行一个时间片即可完成,便可获得与终端型作业一样的响应时间。对于稍长的作业,通常也只需在第二队列和第三队列各执行一个时间片即可完成,其周转时间仍然较短。

(3) 长批处理作业用户。对于长作业,它将依次在第 1,2,…,n 个队列中运行,然后再按轮转方式运行,用户不必担心其作业长期得不到处理。

3.4 实时调度

  由于在实时系统中都存在着若干个实时进程或任务,它们用来反应或控制某个(些)外部 事件,往往带有某种程度的紧迫性,因而对实时系统中的调度提出了某些特殊要求。前面所介绍的多种调度算法并不能很好地满足实时系统对调度的要求,为此,需要引入一种新的调度,即实时调度。

3.4.1 实现实时调度的基本条件

  1. 提供必要的信息
      为了实现实时调度,系统应向调度程序提供有关任务的下述一些信息:

  (1) 就绪时间。这是该任务成为就绪状态的起始时间,在周期任务的情况下,它就是事 先预知的一串时间序列;而在非周期任务的情况下,它也可能是预知的。
  (2) 开始截止时间和完成截止时间。对于典型的实时应用,只须知道开始截止时间,或 者知道完成截止时间。
  (3) 处理时间。这是指一个任务从开始执行直至完成所需的时间。在某些情况下,该时间也是系统提供的。
  (4) 资源要求。这是指任务执行时所需的一组资源。
  (5) 优先级。如果某任务的开始截止时间已经错过,就会引起故障,则应为该任务赋予 “绝对”优先级;如果开始截止时间的推迟对任务的继续运行无重大影响,则可为该任务 赋予“相对”优先级,供调度程序参考。

  1. 系统处理能力强

  在实时系统中,通常都有着多个实时任务。若处理机的处理能力不够强,则有可能因处理机忙不过来而使某些实时任务不能得到及时处理,从而导致发生难以预料的后果。假 定系统中有 m 个周期性的硬实时任务,它们的处理时间可表示为 Ci ,周期时间表示为 Pi , 则在单处理机情况下,必须满足下面的限制条件:

  系统才是可调度的。假如系统中有 6 个硬实时任务,它们的周期时间都是 50 ms,而每次的处理时间为 10 ms,则不难算出,此时是不能满足上式的,因而系统是不可调度的。 解决的方法是提高系统的处理能力,其途径有二:其一仍是采用单处理机系统,但须 增强其处理能力,以显著地减少对每一个任务的处理时间;其二是采用多处理机系统。假 定系统中的处理机数为 N,则应将上述的限制条件改为:

  上述的限制条件并未考虑到任务的切换时间,包括执行调度算法和进行任务切换,以及消息的传递时间等开销,因此,当利用上述限制条件来确定系统是否可调度时,还应适当地留有余地。

  1. 采用抢占式调度机制

  在含有硬实时任务的实时系统中,广泛采用抢占机制。当一个优先权更高的任务到达时,允许将当前任务暂时挂起,而令高优先权任务立即投入运行,这样便可满足该硬实时 任务对截止时间的要求。但这种调度机制比较复杂。

  对于一些小型实时系统,如果能预知任务的开始截止时间,则对实时任务的调度可采用非抢占调度机制,以简化调度程序和对任务调度时所花费的系统开销。但在设计这种调 度机制时,应使所有的实时任务都比较小,并在执行完关键性程序和临界区后,能及时地将自己阻塞起来, 以便释放出处理机, 供调度程序去调度那种开始截止时间即将到达的任务。

  1. 具有快速切换机制
      为保证要求较高的硬实时任务能及时运行,在实时系统中还应具有快速切换机制,以 保证能进行任务的快速切换。该机制应具有如下两方面的能力:

  (1) 对外部中断的快速响应能力。为使在紧迫的外部事件请求中断时系统能及时响应,要求系统具有快速硬件中断机构,还应使禁止中断的时间间隔尽量短,以免耽误时机(其它 紧迫任务)。
  (2) 快速的任务分派能力。在完成任务调度后,便应进行任务切换。为了提高分派程序 进行任务切换时的速度,应使系统中的每个运行功能单位适当地小,以减少任务切换的时 间开销。

3.4.2 实时调度算法的分类

  1. 非抢占式调度算法

  1) 非抢占式轮转调度算法
  该算法常用于工业生产的群控系统中,由一台计算机控制若干个相同的(或类似的)对象,为每一个被控对象建立一个实时任务,并将它们排成一个轮转队列。调度程序每次选择队列中的第一个任务投入运行。当该任务完成后,便把它挂在轮转队列的末尾,等待下次调度运行,而调度程序再选择下一个(队首)任务运行。这种调度算法可获得数秒至数十秒的响应时间,可用于要求不太严格的实时控制系统中。

  2) 非抢占式优先调度算法
  如果在实时系统中存在着要求较为严格(响应时间为数百毫秒)的任务,则可采用非抢占式优先调度算法为这些任务赋予较高的优先级。当这些实时任务到达时,把它们安排在就 绪队列的队首,等待当前任务自我终止或运行完成后才能被调度执行。这种调度算法在做了精心的处理后,有可能获得仅为数秒至数百毫秒级的响应时间,因而可用于有一定要求的实时控制系统中。

  1. 抢占式调度算法

  1) 基于时钟中断的抢占式优先权调度算法
  在某实时任务到达后,如果该任务的优先级高于当前任务的优先级,这时并不立即抢 占当前任务的处理机,而是等到时钟中断到来时,调度程序才剥夺当前任务的执行,将处 理机分配给新到的高优先权任务。这种调度算法能获得较好的响应效果,其调度延迟可降 为几十毫秒至几毫秒。因此,此算法可用于大多数的实时系统中。

  2) 立即抢占的优先权调度算法
  在这种调度策略中,要求操作系统具有快速响应外部事件中断的能力。一旦出现外部中断,只要当前任务未处于临界区,便立即剥夺当前任务的执行,把处理机分配给请求中 断的紧迫任务。这种算法能获得非常快的响应,可把调度延迟降低到几毫秒至 100 微秒, 甚至更低。

  图 3-8 中的(a)、(b)、©、(d)分别示出了采用非抢占式轮转调度算法、非抢占式优先权 调度算法、基于时钟中断抢占的优先权调度算法和立即抢占的优先权调度算法四种情况的 调度时间。

3.4.3 常用的集中实时调度算法

  1. 最早截止时间优先即 **EDF ** 算法
      该算法是根据任务的开始截止时间来确定任务的优先级。截止时间愈早,其优先级愈高。该算法要求在系统中保持一个实时任务就绪队列,该队列按各任务截止时间的早晚排 序;当然,具有最早截止时间的任务排在队列的最前面。调度程序在选择任务时,总是选择就绪队列中的第一个任务,为之分配处理机,使之投入运行。最早截止时间优先算法既可用于抢占式调度,也可用于非抢占式调度方式中。

  1) 非抢占式调度方式用于非周期实时任务

      图 3-9 示出了将该算法用于非抢占调度方式之例。

  该例中具有四个非周期任务,它们先后到达。系统首先调度任务 1 执行,在任务 1 执行期间,任务 2、3 又先后到达。由于任务 3 的开始截止时间早于任务 2,故系统在任务 1 后将调度任务 3 执行。在此期间又到达作业 4,其开始截止时间仍是早于任务 2 的,故在任务 3 执行完后,系统又调度任务 4 执行,最后才调度任务 2 执行。  2) 抢占式调度方式用于周期实时任务 图 3-10 示出了将最早截止时间优先算法用于抢占调度方式之例。在该例中有两个周期性任务,任务 A 的周期时间为 20 ms,每个周期的处理时间为 10 ms;任务 B 的周期时间为 50 ms,每个周期的处理时间为 25 ms。
  图中的第一行示出了两个任务的到达时间、最后期限和执行时间图。其中任务 A 的到达时间为 0、20、40、…;任务 A 的最后期限为 20、40、 60、…;任务 B 的到达时间为 0、50、100、…;任务 B 的最后期限为 50、100、150、…(注: 单位皆为 ms)。
为了说明通常的优先级调度不能适用于实时系统,该图特增加了第二和第三行。在第 二行中假定任务 A 具有较高的优先级,所以在 t = 0 ms 时,先调度 A1 执行,在 A1 完成后 (t = 10 ms)才调度 B1 执行;在 t = 20 ms 时,调度 A2 执行;在 t = 30 ms 时,A2 完成,又调 度 B1 执行;在 t = 40 ms 时,调度 A3 执行;在 t = 50 ms 时,虽然 A3 已完成,但 B1 已错过了它的最后期限,这说明了利用通常的优先级调度已经失败。第三行与第二行类似,只 是假定任务 B 具有较高的优先级。
  第四行是采用最早截止时间优先算法的时间图。在 t = 0 时,A1 和 B1 同时到达,由于 A1 的截止时间比 B1 早,故调度 A1 执行;在 t = 10 时,A1 完成,又调度 B1 执行;在 t = 20 时,A2 到达,由于 A2 的截止时间比 B2 早,B1 被中断而调度 A2 执行;在 t = 30 时,A2 完成,又重新调度 B1 执行;在 t = 40 时,A3 又到达,但 B1 的截止时间要比 A3 早,仍应 让 B1 继续执行直到完成(t = 45),然后再调度 A3 执行;在 t = 55 时,A3 完成,又调度 B2 执行。在该例中利用最早截止时间优先算法可以满足系统的要求。

  1. 最低松弛度优先即LLF算法

  该算法是根据任务紧急(或松弛)的程度,来确定任务的优先级。任务的紧急程度愈高, 为该任务所赋予的优先级就愈高,以使之优先执行。例如,一个任务在 200 ms 时必须完成, 而它本身所需的运行时间就有 100 ms,因此,调度程序必须在 100 ms 之前调度执行,该任 务的紧急程度(松弛程度)为 100 ms。又如,另一任务在 400 ms 时必须完成,它本身需要运 行 150 ms,则其松弛程度为 250 ms。在实现该算法时要求系统中有一个按松弛度排序的实 时任务就绪队列,松弛度最低的任务排在队列最前面,调度程序总是选择就绪队列中的队 首任务执行。
  该算法主要用于可抢占调度方式中。假如在一个实时系统中,有两个周期性实时任务 A 和 B,任务 A 要求每 20 ms 执行一次,执行时间为 10 ms;任务 B 只要求每 50 ms 执行一 次,执行时间为 25 ms。由此可得知任务 A 和 B 每次必须完成的时间分别为:A1 、A2 、A3 、… 和 B1 、B2 、B3 、…,见图 3-11。为保证不遗漏任何一次截止时间,应采用最低松弛度优先 的抢占调度策略。
  在刚开始时(t 1 = 0),A 1 必须在 20 ms 时完成,而它本身运行又需 10 ms,可算出 A 1 的 松弛度为 10 ms;B 1 必须在 50 ms 时完成,而它本身运行就需 25 ms,可算出 B 1 的松弛度 为 25 ms,故调度程序应先调度 A 1 执行。在 t 2 = 10 ms 时,A 2 的松弛度可按下式算出:

    A 2 的松弛度 = 必须完成时间 - 其本身的运行时间 - 当前时间 = 40 ms-10 ms-10 ms = 20 ms

  类似地,可算出 B 1 的松弛度为 15 ms,故调度程序应选择 B 2 运行。在 t 3 = 30 ms 时, A 2 的松弛度已减为 0(即 40 - 10 - 30),而 B 1 的松弛度为 15 ms(即 50 - 5 - 30),于是调度程 序应抢占 B 1 的处理机而调度 A 2 运行。在 t 4 = 40 ms 时,A 3 的松弛度为 10 ms(即 60 - 10 - 40), 而 B 1 的松弛度仅为 5 ms(即 50 - 5 - 40),故又应重新调度 B 1 执行。在 t 5 = 45 ms 时,B1 执行完成,而此时 A 3 的松弛度已减为 5 ms(即 60 - 10 - 45),而 B 2 的松弛度为 30 ms (即 100 - 25 - 45),于是又应调度 A 3 执行。在 t 6 = 55 ms 时,任务 A 尚未进入第 4 周期,而任务 B 已进入第 2 周期,故再调度 B 2 执行。在 t 7 = 70 ms 时,A 4 的松弛度已减至 0 ms (即 80 - 10 - 70),而 B 2 的松弛度为 20 ms(即 100 - 10 - 70),故此时调度又应抢占 B 2 的处 理机而调度 A4 执行。图 3-12 示出了具有两个周期性实时任务的调度情况。

3.5 产生死锁的原因和必要条件

3.5.1 产生死锁的原因

  (1) 竞争资源。当系统中供多个进程共享的资源如打印机、公用队列等,其数目不足以 满足诸进程的需要时,会引起诸进程对资源的竞争而产生死锁。

  (2) 进程间推进顺序非法。进程在运行过程中,请求和释放资源的顺序不当,也同样会 导致产生进程死锁。

  1. 竞争资源引起进程死锁

  1) 可剥夺和非剥夺性资源
  可把系统中的资源分成两类,一类是可剥夺性资源,是指某进程在获得这类资源后, 该资源可以再被其他进程或系统剥夺。甚至可将一个进程从内存调出到外存上。可见,CPU 和主存均属于可剥夺性资源。另一类资源是不可剥夺性资源,当系统把这类资源分配给某 进程后,再不能强行收回,只能在进程用完后自行释放,如磁带机、打印机等。

  2) 竞争非剥夺性资源
  在系统中所配置的非剥夺性资源,由于它们的数量不能满足诸进程运行的需要,会使进程在运行过程中,因争夺这些资源而陷入僵局。
    例如,系统中只有一台打印机 R 1 和一台 磁带机 R2 ,可供进程 P 1 和 P 2 共享。假定 P 1 已占用了打印机 R1 ,P 2 已占用了磁带机 R2 。此 时,若 P 2 继续要求打印机,P 2 将阻塞;P 1 若又要求磁带机,P 1 也将阻塞。于是,在 P 1 与P 2 之间便形成了僵局,两个进程都在等待对方释 放出自己所需的资源。但它们又都因不能继续获 得自己所需的资源而不能继续推进,从而也不能 释放出自己已占有的资源,以致进入死锁状态。
    为便于说明,我们用方块代表资源,用圆圈代表进程,见图 3-13 所示。当箭头从进程指向资源 时,表示进程请求资源;当箭头从资源指向进程 时,表示该资源已被分配给该进程。从中可以看出,这时在 P1 、P 2 及 R 1 和 R 2 之间已经形成了一 个环路,说明已进入死锁状态。
  3) 竞争临时性资源
  上述的打印机资源属于可顺序重复使用型资源,称为永久性资源。还有一种是所谓的临时性资源,这是指由一个进程产生,被另一进程使用一短暂时间后便无用的资源,故也 称之为消耗性资源,它也可能引起死锁。
      图 3-14 示出了在进程之间通信时形成死锁的情况。 图中 S1 、S 2 和 S 3 是临时性资源。进程 P 1 产生消息 S1 ,又要求从 P 3 接收消息 S3 ;进程 P3 产生消息 S3 ,又要求从进程 P 2 接收其所产生的消 息 S2 ;进程 P 2 产生消息 S2 ,又需要接收进程 P 1 P1 所产生的消息 S1 。如果消息通信按下述顺序进行:

P1 : …Release(S1 ); Reqaest(S3 ); …P2 : …Release(S2 ); Request(S1 ); …P3 : …Release(S3 ); Request(S2 ); …
并不可能发生死锁,但若改成下述的运行顺序: P1 : …Request(S3 ); Release(S1 ); …P2 : …Request(S1 ); Release(S2 ); …P3 : …Request(S2 ); Release(S3 );… 则可能发生死锁。

  1. 进程推进顺序不当引起死锁

  1) 进程推进顺序合法

在进程 P 1 和 P 2 并发执行时,如果按下述顺序推进:P1 :Request(R1 );Request(R2 );P1 :Releast(R1 );Release(R2 );P2 :Request(R2 );Request(R1 );P2 :Release(R2 );Release(R1 );两个进程便可顺利完成。

图 3-15 中的曲线①示出了这一情况。类似地,若按曲线②和 ③所示的顺序推进,两进程也可顺利完成。我们称这种不会引起进程死锁的推进顺序是合 法的。
  2) 进程推进顺序非法若并发进程 P 1 和 P 2 按曲线④所示的顺序推进,它们将进入不安全区 D 内。此时 P 1 保 持了资源 R1 ,P 2 保持了资源 R2 ,系统处于不安全状态。因为这时两进程再向前推进,便可 能发生死锁。例如,当 P 1 运行到 P1 :Request(R2 )时,将因 R 2 已被 P 2 占用而阻塞;当 P 2 运 行到 P2 :Request(R1 )时,也将因 R 1 已被 P 1 占用而阻塞,于是发生了进程死锁。

3.5.2 产生死锁的必要条件

  (1) 互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求该资源,则请求者只能等待,直至占有该资源 的进程用毕释放。

  (2) 请求和保持条件:指进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源又已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。

  (3) 不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。

  (4) 环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0 ,P1 ,P2 ,…,Pn }中的 P 0 正在等待一个 P1 占用的资源;P1 正在等待 P 2 占用的资源,……, Pn 正在等待已被 P 0 占用的资源。

3.5.2 处理死锁的基本方法

  (1) 预防死锁。该方法是通过设置某些限制 条件,去破坏产生死锁的四个必要条件中的一个或几个条件,来预防发生死锁。预防死锁是一种较易实现的方法,已被广泛使用。但由于所施加的限制条件往往太严格,因而可能会导致系统资源利用率和系统吞吐量降低。
  (2) 避免死锁。该方法同样是属于事先预防的策略,但它并不须事先采取各种限制措施 去破坏产生死锁的四个必要条件,而是在资源的动态分配过程中,用某种方法去防止系统 进入不安全状态,从而避免发生死锁。这种方法只需事先施加较弱的限制条件,便可获得 较高的资源利用率及系统吞吐量,但在实现上有一定的难度。目前在较完善的系统中常用 此方法来避免发生死锁。
  (3) 检测死锁。这种方法并不须事先采取任何限制性措施,也不必检查系统是否已经进入不安全区,而是允许系统在运行过程中发生死锁。但可通过系统所设置的检测机构,及时地检测出死锁的发生,并精确地确定与死锁有关的进程和资源; 然后,采取适当措施, 从系统中将已发生的死锁清除掉。
  (4) 解除死锁。这是与检测死锁相配套的一种措施。当检测到系统中已发生死锁时,须将进程从死锁状态中解脱出来。常用的实施方法是撤消或挂起一些进程,以便回收一些资源,再将这些资源分配给已处于阻塞状态的进程,使之转为就绪状态,以继续运行。死锁 的检测和解除措施有可能使系统获得较好的资源利用率和吞吐量,但在实现上难度也最大。

3.6 预防死锁的方法

3.6.1 预防死锁

  1. 摒弃“请求和保持”条件

  在采用这种方法时,系统规定所有进程在开始运行之前,都必须一次性地申请其在整个运行过程所需的全部资源。此时,若系统有足够的资源分配给某进程,便可把其需要的 所有资源分配给该进程,这样,该进程在整个运行期间便不会再提出资源要求,从而摒弃 了请求条件。但在分配资源时,只要有一种资源不能满足某进程的要求,即使其它所需的各资源都空闲,也不分配给该进程,而让该进程等待。由于在该进程的等待期间,它并未占有任何资源,因而也摒弃了保持条件,从而可以避免发生死锁。
  这种预防死锁的方法其优点是简单、易于实现且很安全。但其缺点却也极其明显:首先表现为资源被严重浪费,因为一个进程是一次性地获得其整个运行过程所需的全部资源 的,且独占资源,其中可能有些资源很少使用,甚至在整个运行期间都未使用,这就严重地恶化了系统资源的利用率;其次是使进程延迟运行,仅当进程在获得了其所需的全部资源后,才能开始运行,但可能因有些资源已长期被其它进程占用而致使等待该资源的进程 迟迟不能运行。

  1. 摒弃 “不剥夺” 条件
      在采用这种方法时系统规定,进程是逐个地提出对资源的要求的。当一个已经保持了某些资源的进程,再提出新的资源请求而不能立即得到满足时,必须释放它已经保持了的所有资源,待以后需要时再重新申请。这意味着某一进程已经占有的资源,在运行过程中会被暂时地释放掉,也可认为是被剥夺了,从而摒弃了“不剥夺”条件。
      这种预防死锁的方法实现起来比较复杂且要付出很大的代价。因为一个资源在使用一 段时间后,它的被迫释放可能会造成前段工作的失效,即使是采取了某些防范措施,也还会使进程前后两次运行的信息不连续,此外,这种策略还可能因为反复地申请和释放资源,致使进程的执行被无限地推迟,这不仅延长了进程的周转时间, 而且也增加了系统开销,降低了系统吞吐量。

  2. 摒弃 “环路等待” 条件
      这种方法中规定,系统将所有资源按类型进行线性排队,并赋予不同的序号。例如, 令输入机的序号为 1,打印机的序号为 2,磁带机为 3,磁盘为 4。所有进程对资源的请求 必须严格按照资源序号递增的次序提出,这样,在所形成的资源分配图中,不可能再出现 环路,因而摒弃了“环路等待”条件。事实上,在采用这种策略时,总有一个进程占据了较高序号的资源,此后它继续申请的资源必然是空闲的,因而进程可以一直向前推进。
      这种预防死锁的策略与前两种策略比较,其资源利用率和系统吞吐量都有较明显的改善。但也存在下述严重问题:
      首先是为系统中各类资源所分配(确定)的序号必须相对稳定,这就限制了新类型设备的增加。
      其次,尽管在为资源的类型分配序号时,已经考虑到大多数作业在实际使用这些资源时的顺序,但也经常会发生这种情况:即作业(进程)使用各类资源的顺序与系统规定的顺序 不同,造成对资源的浪费。
      第三,为方便用户,系统对用户在编程时所施加的限制条件应尽量少。然而这种按规定次序申请的方法,必然会限制用户简单、自主地编程。

3.6.2 系统安全状态

  在该方法中把系统的状态分为安全状 态和不安全状态,只要能使系统始终都处于安全状态,便可避免发生死锁。

  1. 安全状态

  在避免死锁的方法中,允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次资源分配的安全性。若此次分配不会导致系统进入不安全状态,则将资源分配给 进程;否则,令进程等待。
  所谓安全状态,是指系统能按某种进程顺序(P1 ,P2 ,…,Pn )(称〈P1 ,P2 ,…,Pn 〉序列为安全序列),来为每个进程 P i 分配其所需资源,直至满足每个进程对资源的最大需求, 使每个进程都可顺利地完成。如果系统无法找到这样一个安全序列,则称系统处于不安全 状态。
  虽然并非所有的不安全状态都必然会转为死锁状态,但当系统进入不安全状态后,便有可能进而进入死锁状态;反之,只要系统处于安全状态,系统便可避免进入死锁状态。 因此,避免死锁的实质在于:系统在进行资源分配时,如何使系统不进入不安全状态。

  1. 安全状态之例

  我们通过一个例子来说明安全性。假定系统中有三个进程 P1 、P 2 和 P3 ,共有 12 台磁带 机。进程 P 1 总共要求 10 台磁带机,P 2 和 P 3 分别要求 4 台和 9 台。假设在 T 0 时刻,进程 P1 、 P 2 和 P 3 已分别获得 5 台、2 台和 2 台磁带机,尚有 3 台空闲未分配,如下表所示:
  经分析发现,在 T 0 时刻系统是安全的,因为这时存在一个安全序列〈P2 ,P1 ,P3 〉,即 只要系统按此进程序列分配资源,就能使每个进程都顺利完成。例如,将剩余的磁带机取 2 台分配给 P2 ,使之继续运行,待 P 2 完成,便可释放出 4 台磁带机,于是可用资源增至 5 台; 以后再将这些全部分配给进程 P1 ,使之运行,待 P 1 完成后,将释放出 10 台磁带机,P 3 便 能获得足够的资源,从而使 P1 、P2 、P 3 每个进程都能顺利完成。

  1. 由安全状态向不安全状态的转换
      如果不按照安全序列分配资源,则系统可能会由安全状态进入不安全状态。例如,在 T 0 时刻以后,P 3 又请求 1 台磁带机,若此时系统把剩余 3 台中的 1 台分配给 P3 ,则系统便 进入不安全状态。因为此时也无法再找到一个安全序列,例如,把其余的 2 台分配给 P2 , 这样,在 P 2 完成后只能释放出 4 台,既不能满足 P 1 尚需 5 台的要求,也不能满足 P 3 尚需 6 台的要求,致使它们都无法推进到完成,彼此都在等待对方释放资源,即陷入僵局,结果 导致死锁。类似地,如果我们将剩余的 2 台磁带机先分配给 P 1 或 P3 ,也同样都无法使它们 推进到完成,因此,从给 P 3 分配了第 3 台磁带机开始,系统便又进入了不安全状态。由此 可见,在 P 3 请求资源时,尽管系统中尚有可用的磁带机,但却不能分配给它,必须让 P 3 一 直等待到 P 1 和 P 2 完成,释放出资源后再将足够的资源分配给 P3 ,它才能顺利完成。

3.6.3 利用银行家算法避免死锁

  1. 银行家算法中的数据结构

  (1) 可利用资源向量 Available。这是一个含有 m 个元素的数组,其中的每一个元素代表一类可利用的资源数目,其初始值是系统中所配置的该类全部可用资源的数目,其数值 随该类资源的分配和回收而动态地改变。如果 Available[j]=K,则表示系统中现有 R j 类资源 K 个。

  (2) 最大需求矩阵 Max。这是一个 n×m 的矩阵,它定义了系统中 n 个进程中的每一个 进程对 m 类资源的最大需求。如果 Max[i,j]=K,则表示进程 i 需要 R j 类资源的最大数目为 K。

  (3) 分配矩阵 Allocation。这也是一个 n×m 的矩阵,它定义了系统中每一类资源当前已分配给每一进程的资源数。如果 Allocation[i,j]=K,则表示进程 i 当前已分得 R j 类资源的数 目为 K。

  (4) 需求矩阵 Need。这也是一个 n×m 的矩阵,用以表示每一个进程尚需的各类资源数。 如果 Need[i,j]=K,则表示进程 i 还需要 R j 类资源 K 个,方能完成其任务。 上述三个矩阵间存在下述关系:
        Need[i, j]=Max[i, j]-Allocation[i, j]

  1. 银行家算法
      设 Request i 是进程 P i 的请求向量,如果 Requesti [j]=K,表示进程 P i 需要 K 个 R j 类型 的资源。当 P i 发出资源请求后,系统按下述步骤进行检查:

  (1) 如果 Request i [j]≤Need[i,j],便转向步骤(2);否则认为出错,因为它所需要的资源 数已超过它所宣布的最大值。
  (2) 如果 Requesti [j]≤Available[j],便转向步骤(3);否则,表示尚无足够资源,P i 须 等待。
  (3) 系统试探着把资源分配给进程 Pi ,并修改下面数据结构中的数值:
    Available[j]:= Available[j]-Requesti [j];
    Allocation[i,j]:= Allocation[i,j]+Requesti [j];
    Need[i,j]:= Need[i,j]-Requesti [j];
  (4) 系统执行安全性算法,检查此次资源分配后系统是否处于安全状态。若安全,才正 式将资源分配给进程 Pi ,以完成本次分配;否则,将本次的试探分配作废,恢复原来的资 源分配状态,让进程 P i 等待。

  1. 安全性算法
    系统所执行的安全性算法可描述如下:

(1) 设置两个向量:
    ① 工作向量 Work,它表示系统可提供给进程继续运行所需的各类资源数目,它含有 m 个元素,在执行安全算法开始时,Work:=Available。
    ② Finish, 它表示系统是否有足够的资源分配给进程,使之运行完成。 开始时先做 Finish[i]:=false;当有足够资源分配给进程时,再令 Finish[i]:=true。
  (2) 从进程集合中找到一个能满足下述条件的进程:
    ① Finish[i]=false;
    ② Need[i,j]≤Work[j];若找到,执行步骤(3),否则,执行步骤(4)。
  (3) 当进程 P i 获得资源后,可顺利执行,直至完成,并释放出分配给它的资源,故应 执行: Work[j]:= Work[j]+Allocation[i,j]; Finish[i]:=true; go to step 2;
  (4) 如果所有进程的 Finish[i]=true 都满足,则表示系统处于安全状态;否则,系统处于不安全状态。

  1. 银行家算法之例

  假定系统中有五个进程{P0 ,P1 ,P2 ,P3 ,P4 }和三类资源{A,B,C},各种资源的数量 分别为 10、5、7,在 T 0 时刻的资源分配情况如图 3-16 所示。
(1) T 0 时刻的安全性:利用安全性算法对 T 0 时刻的资源分配情况进行分析(见图 3-17 所 示)可知,在 T 0 时刻存在着一个安全序列{P1 ,P3 ,P4 ,P2 ,P0 },故系统是安全的。
(2) P 1 请求资源:P 1 发出请求向量 Request1 (1,0,2),系统按银行家算法进行检查:
   ① Request1 (1,0,2)≤Need1 (1,2,2)
  ② Request1 (1,0,2)≤Available1 (3,3,2)
  ③ 系统先假定可为 P 1 分配资源,并修改 Available,Allocation 1 和 Need 1 向量,由此形 成的资源变化情况如图 3-16 中的圆括号所示。
  由所进行的安全性检查得知,可以找到一个安全序列{P1 ,P3 ,P4 ,P2 ,P0 }。因此,系 统是安全的,可以立即将 P 1 所申请的资源分配给它。

  (3) P 4 请求资源:P 4 发出请求向量 Request4 (3,3,0),系统按银行家算法进行检查:
    ① Request4 (3,3,0)≤Need4 (4,3,1);
    ② Request4 (3,3,0)≤Available(2,3,0),让 P 4 等待。

  (4) P 0 请求资源:P 0 发出请求向量 Requst0 (0,2,0),系统按银行家算法进行检查:
    ① Request0 (0,2,0)≤Need0 (7,4,3);
    ② Request0 (0,2,0)≤Available(2,3,0); ③ 系统暂时先假定可为 P 0 分配资源,并修改有关数据,如图 3-19 所示。
(5) 进行安全性检查:可用资源 Available(2,1,0)已不能满足任何进程的需要,故系统进入不安全状态,此时系统不分配资源。
  如果在银行家算法中,把 P 0 发出的请求向量改为 Request0 (0,1,0),系统是否能将资源分配给它,请读者考虑。

3.7 死锁的检测与解除

3.7.1 死锁的检测

(1) 保存有关资源的请求和分配信息;

(2) 提供一种算法,以利用这些信息来检测系统是否已进入死锁状态。

  1. 资源分配图
      系统死锁可利用资源分配图来描述。该图是由一组结点 N 和一组边 E 所组成的一个对 偶 G=(N1 E),它具有下述形式的定义和限制:

  (1) 把 N 分为两个互斥的子集,即一组进程结点 P={p1 , p2 ,…,pn }和一组资源结 点 R={r1 ,r2 ,…,rn },N=P∪R。在图 3-20 所示的例子中,P={p1 ,p2 },R={r1 ,r2 }, N={r1 ,r2 }∪{p1 ,p2 }。

  (2) 凡属于 E 中的一个边 e∈E,都连接着 P 中的一个结点和 R 中的一个结点,e={pi ,rj } 是资源请求边,由进程 p i 指向资源 rj ,它表示进程 p i 请求一个单位的 r j 资源。e={rj ,pi }是 资源分配边,由资源 r j 指向进程 pi ,它表示把一个单位的资源 r j 分配给进程 pi 。图 3-13 中 示出了两个请求边和两个分配边,即 E={(p1 ,r2 ),(r2 ,p2 ),(p2 ,r1 ),(r1 ,p1 )}。
  我们用圆圈代表一个进程,用方框代表一类资源。由于一种类型的资源可能有多个,我们用方框中的一个点代表一类资源中的一个资源。此时,请求边是由进程指向方框中的 rj ,而分配边则应始于方框中的一个点。图 3-20 示出了一个资源 分配图。图中,p 1 进程已经分得了两个 r 1 资源, 并又请求一个 r 2 资源;p 2 进程分得了一个 r 1 和一 个 r 2资源,并又请求 r 1资源。          

  1. 死锁定理

  (1) 在资源分配图中,找出一个既不阻塞又非独立的进程结点 Pi 。在顺利的情况下,Pi 可获得所需资源而继续运行,直至运行完毕,再释放其所占有的全部资源,这相当于消去 p i 所求的请求边和分配边,使之成为孤立的结点。在图 3-21(a)中,将 p 1 的两个分配边和一 个请求边消去,便形成图(b)所示的情况。
  (2) p 1 释放资源后,便可使 p 2 获得资源而继续运行,直至 p 2 完成后又释放出它所占有 的全部资源,形成图©所示的情况。
  (3) 在进行一系列的简化后,若能消去图中所有的边,使所有的进程结点都成为孤立结点,则称该图是可完全简化的;若不能通过任何过程使该图完全简化,则称该图是不可完 全简化的。

  对于较复杂的资源分配图,可能有多个既未阻塞,又非孤立的进程结点,不同的简化顺序是否会得到不同的简化图?有关文献已经证明,所有的简化顺序,都将得到相同的不 可简化图。同样可以证明:S 为死锁状态的充分条件是:当且仅当 S 状态的资源分配图是不可完全简化的。该充分条件被称为死锁定理。

2.7.2 死锁的解除

当发现有进程死锁时,便应立即把它们从死锁状态中解脱出来。常采用解除死锁的两种方法是:

(1) 剥夺资源。从其它进程剥夺足够数量的资源给死锁进程,以解除死锁状态。

(2) 撤消进程。最简单的撤消进程的方法是使全部死锁进程都夭折掉;稍微温和一点的方法是按照某种顺序逐个地撤消进程,直至有足够的资源可用,使死锁状态消除为止。 在出现死锁时,可采用各种策略来撤消进程。 例如, 为解除死锁状态所需撤消的进 程数目最小;或者,撤消进程所付出的代价最小等。一种付出最小代价的方法如图 3-22 所示。

假定在死锁状态时,有死锁进程 P1 ,P2 ,…,Pk 。首先,撤消进程 P1 ,使系统状态由 S→U1 ,付出的代价为 CU1 ,然后,仍然从 S 状态中撤消进程 P2 ,使状态由 S→U2 ,其代价 为 CU2 ,…,如此下去可得到状态 U1 ,U2 ,…,Un 。若此时系统仍处于死锁状态,需再进 一步撤消进程,如此下去,直至解除死锁状态为止。这种方法为解除死锁状态可能付出的 代价将是 k(k-1)(k-2)…/2C。显然,所花费的代价很大,因此,这是一种很不实际的方法。

一个比较有效的方法是对死锁状态 S 做如下处理:从死锁状态 S 中先撤消一个死锁进 程 P1 ,使系统状态由 S 演变成 U1 ,将 P 1 记入被撤消进程的集合 d(T)中,并把所付出的代价 C 1 加入到 rc(T)中;对死锁进程 P2 、P 3 等重复上述过程,得到状态 U1 ,U2 ,…,Ui ,Un , 然后,再按撤消进程时所花费代价的大小,把它插入到由 S 状态所演变的新状态的队列 L 中。显然,队列 L 中的第一个状态 U 1 是由 S 状态花最小代价撤消一个进程所演变成的状态。 在撤消一个进程后,若系统仍处于死锁状态,则再从 U 1 状态按照上述处理方式再依次地撤 消一个进程,得到 U 1 ′ , U ′ 2 , U ′ 3 ,…, U ′ k 状态,再从 U ′ 状态中选取一个代价最小的 U ′ j , 如此下去,直到死锁状态解除为止。为把系统从死锁状态中解脱出来,所花费的代价可表示为:

R(S) min = min{CUi } + min{CUj } + min{CUk } + …

======第三章处理机调度与死锁======相关推荐

  1. 第三章 处理机调度与死锁

    第三章 处理机调度与死锁 3.1 处理机调度的层次和调度算法的目标 3.1.1 处理机调度的层次 3.1 处理机调度的层次和调度算法的目标 3.1.1 处理机调度的层次

  2. 三、处理机调度与死锁

      上一章介绍的进程主要从概念出发,但程序执行终归是动态的.进程如何参与程序的动态执行过程呢?在多道程序下,进程的数量远大于处理机的数量.那如何对进程进行安排(处于就绪状态的进程有好多,选哪些进程给处 ...

  3. 进程调度(第三章 处理调度与死锁)

    多道程序环境下,主存中进程数目往往多于处理机数目.要求系统通过某种算法动态的将就绪队列中的进程分配给处理机执行. 3.1 处理机调度的层次 批量型作业:作业调度(高级调度.长程调度)+进程调度(低级调 ...

  4. 操作系统学习笔记 第三章:处理机调度与死锁(王道考研)

    本文章基于网课: 2019 王道考研 操作系统 考试复习推荐资料:操作系统复习总结 - 百度文库 (baidu.com) 需要相关电子书的可以关注我的公众号BaretH后台回复操作系统 第一章:操作系 ...

  5. 【操作系统】处理机调度与死锁(三)

    [操作系统]处理机调度与死锁(三) 一.前言 二.处理机调度的层次 2.1 高级调度 2.2 低级调度 2.3 中级调度 三.调度队列模型和调度准则 3.1 仅有进程调度的调度队列模型 3.2 具有高 ...

  6. 操作系统 综合应用题知识点更新【章节考试重点(进程同步、处理机调度与死锁、存储管理、设备管理、文件管理)】

    知识点 目录 第二章:进程同步 第三章:处理机调度与死锁 第四.五章:存储管理 第六章:设备管理 第七.八章:文件管理 第二章:进程同步 (1) 前驱图 (2) 互斥同步都有的 第三章:处理机调度与死 ...

  7. 【408预推免复习】操作系统之处理机调度与死锁

    [408&预推免复习]操作系统之处理机调度与死锁 文章目录 1 作业调度和进程调度 2 实时调度和死锁概述 3 预防死锁和避免死锁 1 作业调度和进程调度 什么是处理机调度? 处理机调度:如何 ...

  8. 操作系统基本概念梳理(3)---处理机调度与死锁

    处理机调度与死锁 一.处理机调度 在多道程序中,调度的实质是一种资源分配,处理机调度是依据某种算法对处理机资源进行分配. 1.处理机调度的层次 1).高级调度:  高级调度又称作业调度.其主要功能是根 ...

  9. 【学习笔记】第二章——处理机调度的概念、层次、时机、切换过程 调度方式、调度算法的指标

    文章目录 一. 概念 & 层次 1. 高级调度(作业调度) 2. 中级调度(内存调度) 挂起态 & 七状态模型 3. 低级调度(进程调度) 4. 三种调度的对比联系 && ...

最新文章

  1. 2022-2028年中国微机电系统(MEMS)行业投资分析及前景预测报告
  2. 使用ntpdate校正linux系统的时间
  3. linux ppp拨号 socket,请问GPRS模块ppp拨号不成功是什么原因
  4. 用这种方式,我每次都是朋友圈里第一个预见AI科技趋势的人
  5. RhinoMock入门(7)——Do,With和Record-playback
  6. ubuntu mysql5.6 编译安装_Ubuntu14.04编译安装mysql5.6.26
  7. 实时数据处理插件开发flume+kafka+storm:flume
  8. Python中键映射多个值的方法:defaultdict
  9. CF Gym102059 H. Fractions
  10. 别的AI还在打游戏,这个AI已经当上“超级马里奥”游戏策划了|GECCO最佳论文
  11. 自己的HTML5 播放器
  12. 我真是个懒人,。。。
  13. Noise,Error,wighted pocket Algorithm
  14. 国产Linux下的录屏软件
  15. 二叉树的前中后序遍历(非递归实现)
  16. SAXReader简单实例分析
  17. threejs:流光效果封装
  18. HackTheBox - Brainfuck Write Up
  19. HALCON学习-下载、安装
  20. COleDateTime获取对象的time_t

热门文章

  1. Tensorflow实现线性回归
  2. Dart基础-运算符
  3. 哌甲酯药行业调研报告 - 市场现状分析与发展前景预测
  4. 中国水龙头市场趋势报告、技术动态创新及市场预测
  5. 2021年中国独立眼科超声系统市场趋势报告、技术动态创新及2027年市场预测
  6. 服务 23 年,苹果宣布停止 macOS Server
  7. TikTok 与 Oracle 的交易将开创两个危险的先例
  8. Java 8 八年不倒、IntelliJ IDEA 力压 Eclipse,2022 年 Java 开发者都在用什么?
  9. 为什么要用SpringCloud alibaba作为微服务开发框架?
  10. 10 个内存引发的大坑,你能躲开几个?