操作系统---处理机调度与死锁

处理机调度的层次

高级调度(High Level Scheduling)

  • 高级调度(作业调度或长程调度)
    在多道批处理系统中,作业是用户提交给系统的一项相对独立的工作。操作员把用户提交的作业通过相应的输入设备输入到磁盘存储器,并保存在一个后备作业队列中,再由作业调度程序将其从外存调入内存。作业调度往往是发生在一个(批)作业运行完毕,退出系统,而需要重新调入一个(批)作业进入内存时,故作业调度的周期较长。

  • 作业运行的三个阶段和三种状态:
    作业从进入系统到运行结束,通常需要经历收容、运行和完成三个阶段,相应的作业也就有“后备状态”、“运行状态”和“完成状态”。

  • 作业(Job):
    作业是一个比程序更为广泛的概念,它不仅包含了通常的程序数据,而且还应配有一份作业说明书。系统根据该说明书来对程序的运行进行控制,在批处理系统中,是以作业为基本单位从外存调入内存的。

  • 作业步(Job Step):
    通常,在作业运行期间,每个作业都必须经过若干个相对独立又相互关联的顺序加工步骤才能得到结果,把其中的每一个加工步骤称为一个作业步,各作业步之间存在着相互联系,往往是把上一个作业步的输出作为下一个作业步的输入。

  • 作业流:
    若干个作业进入系统后,被依次存放在外存上,这便形成了输入的作业流,在操作系统的控制下,逐个作业进行处理,于是便形成了处理作业流。

  • 作业控制块 JCB(Job Control Block)
    为了管理和调度作业,在多道批处理系统中为每个作业设置了一个作业控制块,它是作业在系统中存在的标志,其中保存了系统对作业进行管理和调度所需的全部信息。每当作业进入系统时,系统便为每个作业建立一个 JCB,根据作业类型将它插入相应的后备队列中,作业调度程序依据一定的调度算法来调度它们,被调度到的作业将会装入内存。在作业运行期间,系统就按照 JCB 中的信息对作业进行控制,当一个作业执行结束进入完成状态时,系统负责回收分配给它的资源,撤消它的作业控制块。

    内容:作业标识、用户名称、用户帐户、作业类型(CPU 繁忙型、I/O 繁忙型、批量型、终端型)、作业状态、调度信息(优先级、作业已运行时间)、资源需求(预计运行时间、 要求内存大小、要求 I/O 设备的类型和数量等)、进入系统时间、开始处理时间、作业完成时间、作业退出时间、资源使用情况等。

  • 作业调度的主要任务:
    根据JCB中的信息,检查系统中的资源能否满足作业对资源的需求。按照一定的调度算法,从外存的后备队列中选取某些作业调入内存,并为它们创建进程、分配必要的资源,将新创建的进程排在就绪队列上等待调度

    决定接纳多少个作业
    取决于多道程序度(Degree of Multiprogramming), 即允许多少个作业同时在内存中运行。当内存中同时运行的作业数目太多时,可能会影响到系统的服务质量,如果在内存中同时运行作业的数量太少时, 又会导致系统的资源利用率和系统吞吐量太低。

    决定接纳哪些作业
    应将哪些作业从外存调入内存,这将取决于所采用的调度算法,在批处理系统中,作业进入系统后,总是先驻留在外存的后备队列上,因此需要有作业调度的过程,以便将它们分批地装入内存,在分时系统中,用户通过键盘输入的命令或数据等都是被直接送入内存的,因而无需再配置上述的作业调度机制,但也需要有某些限制性措施来限制进入系统的用户数。即,如果系统尚未饱和,将接纳所有授权用户,否则,将拒绝接纳,在实时系统中通常也不需要作业调度

低级调度(Low Level Scheduling)

  • 进程调度是最基本的一种调度,在多道批处理、分时和实时三种类型的 OS 中,都必须配置这级调度。决定就绪队列中的哪个进程应获得处理机,然后再由分派程序把处理机分配给该进程。由于低级调度算法的频繁使用,要求在实现时做到高效。常采用非抢占(非剥夺)方式和抢占(剥夺)方式两种。

  • 保存处理机的现场信息:在进程调度进行调度时,首先需要保存当前进程的处理机的现场信息。如程序计数器、多个通用寄存器中的内容等,将它们送入该进程PCB中的相应单元

    按某种算法选取进程:低级调度程序按某种算法从就绪队列中选取一个进程,把它的状态改为运行状态,并准备把处理机分配给它。

    把处理器分配给进程:由分派程序(Dispatcher)把处理器分配给进程,此时需为选中的进程恢复处理机现场,即把选中进程的进程控制块内有关处理机现场的信息装入处理器相应的各个寄存器中,把处理器的控制权交给该进程,让它从取出的断点处开始继续运行。

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

    排队器:为了提高进程调度的效率,应事先将系统中所有的就绪进程按照一定的方式排成一个或多个队列。

    分派器(分派程序):分派器把由进程调度程序所选定的进程,从就绪队列中取出该进程,然后进行上下文切换,将处理机分配给它。

    上下文切换机制:在第一对上下文切换时,操作系统将保存当前进程的上下文,而装入分派程序的上下文,以便分派程序运行。在第二对上下文切换时,将移出分派程序,而把新选进程的 CPU 现场信息装入到处理机的各个相应寄存器中。上下文切换将花去不少的处理机时间,为此,现在已有通过硬件(采用两组或多组寄存器)的方法来减少上下文切换的时间,一组寄存器供处理机在系统态时使用,另一组寄存器供应用程序使用,在这种条件下的上下文切换只需改变指针,使其指向当前寄存器组即可。

  • 进程调度方式
    非抢占方式(Nonpreemptive Mode)
    在采用这种调度方式时,一旦把处理机分配给某进程后,不管它要运行多长时间,都一直让它运行下去,决不会因为时钟中断等原因而抢占正在运行进程的处理机,也不允许其它进程抢占已经分配给它的处理机,直至该进程完成,自愿释放处理机,或发生某事件而被阻塞时,才再把处理机分配给其他进程。实现简单,系统开销小,适用于大多数的批处理系统环境,它难以满足紧急任务的要求

    可能引起进程调度的因素
    正在执行的进程执行完毕,或因发生某事件而不能再继续执行,执行中的进程因提出 I/O 请求而暂停执行,在进程通信或同步过程中执行了某种原语操作,如 P 操作(wait 操作)、Block 原语、 Wakeup 原语等。

    抢占方式(Preemptive Mode)
    这种调度方式允许调度程序根据某种原则去暂停某个正在执行的进程,将已分配给该进程的处理机重新分配给另一进程。可以防止一个长进程长时间占用处理机,能为大多数进程提供更公平的服务,特别是能满足对响应时间有着较严格要求的实时任务的需求,开销较大。

    原则
    优先权优先原则:通常是对一些重要的和紧急的作业赋予较高的优先权。当这种作业到达时,如果其优先权比正在执行进程的优先权高,便停止正在执行(当前)的进程,将处理机分配给优先权高的新到的进程,使之执行。

    短作业(进程)优先原则:当新到达的作业(进程)比正在执行的作业(进程)明显的短时,将暂停当前长作业(进程)的执行,将处理机分配给新到的短作业(进程),使之优先执行,或者说,短作业(进程)可以抢占当前较长作业(进程)的处理机。

    时间片原则:进程按时间片轮流运行,当一个时间片用完后,便停止该进程的执行而重新进行调度。这种原则适用于分时系统、大多数的实时系统,以及要求较高的批处理系统。

中级调度(Intermediate Scheduling)

  • 在内存和外存对换区之间按照给定的策略选择进程对换,解决内存紧张问题,提高内存的利用率和系统吞吐量。

  • 中级调度对进程进行切换时,要保留当前进程的 CPU 环境和设置新选中进程的 CPU 环境,使那些暂时不能运行的进程不再占用宝贵的内存资源,而将它们调至外存上去等待,把此时的进程状态称为就绪驻外存状态或挂起状态。当这些进程又具备运行条件且内存又稍有空闲时,由中级调度来决定把外存上的那些又具备运行条件的就绪进程重新调入内存,并修改其状态为就绪状态,挂在就绪队列上等待进程调度。中级调度实际上就是存储器管理中的对换功能。

调度队列模型和调度准则

调度队列模型

  • 仅有进程调度的调度队列模型:
    在分时系统中,通常仅设置了进程调度,用户键入的命令和数据都直接送入内存,对于命令,是由 OS 为之建立一个进程,系统可以把处于就绪状态的进程组织成栈、树或一个无序链表。

    每个进程在执行时都可能出现以下三种情况:
    任务在给定的时间片内已经完成,该进程便在释放处理机后进入完成状态。任务在本次分得的时间片内尚未完成,OS 便将该任务再放入就绪队列的末尾。在执行期间,进程因为某事件而被阻塞后,被 OS 放入阻塞队列。

  • 具有高级和低级调度的调度队列模型
    就绪队列的形式:在批处理系统中,最常用的是最高优先权优先调度算法,相应地,最常用的就绪队列形式是优先权队列。进程在进入优先级队列时,根据其优先权的高低,被插入具有相应优先权的位置上这样,调度程序总是把处理机分配给就绪队列中的队首进程。在最高优先权优先的调度算法中,也可采用无序链表方式,即每次把新到的进程挂在链尾。调度程序每次调度时,依次比较该链中进程的优先权,从中找出优先权最高的进程,将之从链中摘下,并把处理机分配给它。

    设置多个阻塞队列:对于小型系统,可以只设置一个阻塞队列,但当系统较大时,这将严重影响对阻塞队列操作的效率,故在大、中型系统中通常都设置了若干个阻塞队列,每个队列对应于某一种进程阻塞事件。

  • 同时具有三级调度的调度队列模型

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

  • 面向用户的准则:这是为了满足用户的需求所应遵循的一些准则

    周转时间短:通常把周转时间的长短作为评价批处理系统的性能、选择作业调度方式与算法的重要准则之一。周转时间是指从作业被提交给系统开始,到作业完成为止的这段时间间隔。包括作业在外存后备队列上等待时间,作业调度的时间,进程在就绪队列上等待进程调度的时间,执行时间,等待 I/O 操作完成的时间。对每个用户而言,都希望自己作业的周转时间最短,但作为计算机系统的管理者,则总是希望能使平均周转时间最短。作业的周转时间 T 与系统为它提供服务的时间 Ts 之比,即 W = T/Ts,称为带权周转时间。

    响应时间快:把响应时间的长短用来评价分时系统的性能。响应时间包括从键盘输入的请求信息传送到处理机的时间,处理机对请求信息进行处理的时间,所形成的响应信息回送到终端显示器的时间。

    截止时间的保证:这是评价实时系统性能的重要指标,截止时间为某任务必须开始执行的最迟时间,或必须完成的最迟时间。

    优先权准则:以便让某些紧急的作业能得到及时处理,在要求较严格的场合,往往还须选择抢占式调度方式,才能保证紧急作业得到及时处理。

  • 面向系统的准则:这是为了满足系统要求而应遵循的一些准则

    系统吞吐量高:这是用于评价批处理系统性能的另一个重要指标,因而是选择批处理作业调度的重要准则,由于吞吐量是指在单位时间内系统所完成的作业数,因而它与批处理作业的平均长度具有密切关系。事实上,对于同一批作业,若采用了较好的调度方式和算法, 则可显著地提高系统的吞吐量。处理机利用率:CPU的利用率=CPU有效工作时间/(CPU有效工作时间+CPU空闲等待时间)

    各类资源的平衡利用:为提高系统的资源利用率,应使系统中的处理机和其它所有资源都尽可能地保持忙碌状态。

  • 处理机调度算法的目标
    公平性:指应使诸进程都获得合理的CPU 时间,不会发生进程饥饿现象,公平性是相对的,对相同类型的进程应获得相同的服务,对于不同类型的进程,由于其紧急程度或重要性的不同,则应提供不同的服务。

    平衡性:由于在系统中可能具有多种类型的进程,有的属于计算型作业,有的属于I/O型,为使系统中的CPU和各种外部设备都能经常处于忙碌状态,调度算法应尽可能保持系统资源使用的平衡性。

    策略强制执行:对所制订的策略其中包括安全策略,只要需要,就必须予以准确地执行,即使会造成某些工作的延迟也要执行。

调度算法

先来先服务(first-come first-served,FCFS)调度算法

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

    FCFS 算法比较有利于长作业(进程),而不利于短作业(进程),有利于 CPU 繁忙型的作业,而不利于 I/O 繁忙型的作业(进程),人—机无法实现交互。

短作业(进程)优先(short job first,SJF)调度算法

  • 对短作业或短进程优先调度的算法,可以分别用于作业调度和进程调度。短作业优先调度算法从后备队列中选择一个或若干个估计运行时间最短的作业,将它们调入内存运行。而短进程优先(SPF)调度算法则是从就绪队列中选出一个估计运行时间最短的进程,将处理机分配给它,使它立即执行并一直执行到完成,或发生某事件而被阻塞放弃处理机时再重新调度。

    该算法对长作业不利,该算法完全未考虑作业的紧迫程度,因而不能保证紧迫性作业(进程)会被及时处理。由于作业(进程)的长短只是根据用户所提供的估计执行时间而定的,而用户又可能会有意或无意地缩短其作业的估计运行时间,致使该算法不一定能真正做到短作业优先调度。

高优先权优先调度算法

  • 为了照顾紧迫型作业,使之在进入系统后便获得优先处理。用于作业调度时,系统将从后备队列中选择若干个优先权最高的作业装入内存。当用于进程调度时,该算法是把处理机分配给就绪队列中优先权最高的进程。

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

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

  • 优先权的类型

    静态优先权:静态优先权是在创建进程时确定的,且在进程的整个运行期间保持不变。优先级是利用某一范围内的一个整数来表示的。通常,系统进程(如接收进程、对换进程、磁盘 I/O 进程)的优先权高于一般用户进程的优先权;对要求少的进程赋予较高的优先权或由用户进程的紧迫程度及用户所付费用的多少来确定优先权的。静态优先权法简单易行,系统开销小,但不够精确,很可能出现优先权低的作业(进程) 长期没有被调度的情况,仅在要求不高的系统中才使用静态优先权。

    动态优先权:指在创建进程时所赋予的优先权,是可以随进程的推进或随其等待时间的增加而改变的,以便获得更好的调度性能。在就绪队列中的进程, 随其等待时间的增长,其优先权以速率 a 提高。当采用抢占式优先权调度算法时,如果再规定当前进程的优先权以速率 b 下降,则可防止一个长作业长期地垄断处理机。

高响应比优先(Highest Response Ratio Next,HRRN)调度算法

  • 能为每个作业引入一个动态优先级,令它随等待时间延长而增加,这将使长作业的优先级在等待期间不断地增加,等到足够的时间后,必然有机会获得处理机。该优先权的变化规律可描述为:优先权=(要求服务时间+等待时间)/要求服务时间=响应时间/要求服务时间。如果作业的等待时间相同,则要求服务的时间愈短,其优先权愈高,因而该算法有利于短作业,当要求服务的时间相同时,作业的优先权决定于其等待时间,等待时间愈长,其优先权愈高,因而它实现的是先来先服务。在利用该算法时,要进行调度之前,都须先做响应比的计算,这会增加系统开销。

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

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

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

    进程切换时机:
    若一个时间片尚未用完,正在运行的进程便已经完成,就立即激活调度程序,将它从就绪队列中删除,再调度就绪队列中队首的进程运行,并启动一个新的时间片,在一个时间片用完时,计时器中断处理程序被激活,如果进程尚未运行完毕,调度程序将把它送往就绪队列的末尾。

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

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

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

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

    调度算法的性能:如果规定第一个队列的时间片略大于多数人机交互所需之处理时间时,便能较好地满足各种类型用户的需要

基于公平原则的调度算法: 保证调度算法

  • 它向用户所做出的保证并不是优先运行,而是明确的性能保证,该算法可以做到调度的公平性。一种比较容易实现的性能保证是处理机分配的公平性。如果在系统中有n个相同类型的进程同时运行,为公平起见,须保证每个进程都获得相同的处理机时间1/n
  • 在实施公平调度算法时系统中必须跟踪计算每个进程自创建以来已经执行的处理时间,计算每个进程应获得的处理机时间,即自创建以来的时间除以n,计算进程获得处理机时间的比率,即进程实际执行的处理时间和应获得的处理机时间之比,比较各进程获得处理机时间的比率。调度程序应选择比率最小的进程将处理机分配给它,并让该进程一直运行,直到超过最接近它的进程比率为止。
  • 分配给每个进程相同的处理机时间,这对诸进程而言,是体现了一定程度的公平。但如果各个用户所拥有的进程数不同,就会发生对用户的不公平问题

实时调度

实现实时调度的基本条件

  • 提供必要的信息:

    就绪时间:这是该任务成为就绪状态的起始时间,在周期任务的情况下,它就是事先预知的一串时间序列;

    开始截止时间和完成截止时间:对于典型的实时应用,只须知道开始截止时间,或者知道完成截止时间。

    处理时间:这是指一个任务从开始执行直至完成所需的时间。在某些情况下,该时间也是系统提供的。

    资源要求:这是指任务执行时所需的一组资源。

    优先级:如果某任务的开始截止时间已经错过,就会引起故障,则应为该任务赋予 “绝对”优先级。如果开始截止时间的推迟对任务的继续运行无重大影响,则可为该任务赋予“相对”优先级,供调度程序参考。

  • 系统处理能力强
    假定系统中有 m 个周期性的硬实时任务,它们的处理时间可表示为 Ci,周期时间表示为 Pi,在单处理机情况下,必须满足下面的限制条件:
    在这里插入图片描述

    提高系统的处理能力:其一仍是采用单处理机系统,但须增强其处理能力,以显著地减少对每一个任务的处理时间;其二是采用多处理机系统。假定系统中的处理机数为 N,则应将上述的限制条件改为:
    在这里插入图片描述

  • 采用抢占式调度机制
    当一个优先权更高的任务到达时,允许将当前任务暂时挂起,而令高优先权任务立即投入运行,这样便可满足该硬实时任务对截止时间的要求,但这种调度机制比较复杂。 对于一些小型实时系统,如果能预知任务的开始截止时间,则可采用非抢占调度机制,以简化调度时所花费的系统开销。但在设计这种调度机制时,应使所有的实时任务都比较小,并在执行完关键性程序和临界区后,能及时地将自己阻塞起来,以便释放处理机,供调度程序去调度那种开始截止时间即将到达的任务。

  • 具有快速切换机制
    对外部中断的快速响应能力:为使在紧迫的外部事件请求中断时系统能及时响应,要求系统具有快速硬件中断机构,还应使禁止中断的时间间隔尽量短,以免耽误时机(其它紧迫任务)。

  • 快速的任务分派能力
    在完成任务调度后,便应进行任务切换。为了提高分派程序进行任务切换时的速度,应使系统中的每个运行功能单位适当地小,以减少任务切换的时间开销。

实时调度算法的分类

  • 实时任务性质:硬实时,软实时。

  • 调度方式:非抢占调度算法,抢占调度算法。

  • 调度程序调度时间:
    静态调度算法:在进程执行前,调度程序已经决定了各进程间的执行顺序。
    动态调度算法:在进程的执行过程中,由调度程序根据情况临时决定将哪一进程投入运行。

  • 非抢占式调度算法:简单,易于实现,故在一些小型实时系统或要求不太严格的实时控制系统中经常采用。

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

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

  • 抢占式调度算法:在要求较严格的(响应时间为数十毫秒以下)的实时系统中,应采用抢占式优先权调度算法(复杂)。

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

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

  • 非抢占式调度方式用于非周期实时任务,抢占式调度方式用于周期实时任务。

常用的几种实时调度算法

  • 最早截止时间优先即 EDF(Earliest Deadline First)算法
    要求在系统中保持一个实时任务就绪队列,该队列按各任务截止时间的早晚排序,具有最早截止时间的任务排在队列的最前面。调度程序在选择任务时,总是选择就绪队列中的第一个任务,为之分配处理机,使之投入运行。最早截止时间优先算法既可用于抢占式调度,也可用于非抢占式调度方式中。

  • 最低松弛度优先即 LLF(Least Laxity First)算法
    该算法是根据任务紧急(或松弛)的程度,来确定任务的优先级。任务松弛度=必须完成时间–任务已经运行的时间 – 当前时间。任务的紧急程度愈高,为该任务所赋予的优先级就愈高,以使之优先执行,在实现该算法时要求系统中有一个按松弛度排序的实时任务就绪队列,松弛度最低的任务排在队列最前面。调度程序总是选择就绪队列中的队首任务执行,该算法主要用于可抢占调度方式中。

  • 优先级倒置(priority inversion problem)
    高优先级进程(或线程)被低优先级进程(或线程)延迟或阻塞,(低优先级的进程获得临界资源,高优先级进程获得处理机)。规定进程低优先级的进程在进入临界区后其所占用的处理机就不允许被抢占。

死锁(Deadlock)

  • 死锁指多个进程在运行过程中因争夺资源而造成的一种僵局(DeadlyEmbrace)。当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进,在一组进程发生死锁的情况下,这组死锁进程中的每一个进程,都在等待另一个死锁进程所占有的资源。

  • 可消耗性资源又称为临时性资源,它是在进程运行期间,由进程动态地创建和消耗的,每一类可消耗性资源的单元数目在进程运行期间是可以不断变化的,有时它可以有许多,有时可能为0。进程在运行过程中,可以不断地创造可消耗性资源的单元,将它们放入该资源类的缓冲区中,以增加该资源类的单元数目,进程在运行过程中,可以请求若干个可消耗性资源单元,用于进程自己的消耗,不再将它们返回给该资源类中。

  • 可重用性资源是一种可供用户重复使用多次的资源,每一个可重用性资源中的单元只能分配给一个进程使用,不允许多个进程共享。进程在使用可重用性资源时,须按照这样的顺序:请求资源。如果请求资源失败,请求进程将会被阻塞或循环等待。使用资源。进程对资源进行操作。释放资源。当进程使用完后自己释放资源。系统中每一类可重用性资源中的单元数目是相对固定的,进程在运行期间既不能创建也不能删除它。

  • 可抢占性资源:某进程在获得这类资源后,该资源可以再被其它进程或系统抢占。

  • 不可抢占性资源:一旦系统把某资源分配给该进程后,就不能将它强行收回,只能在进程用完后自行释放。

产生死锁的原因

  • 竞争不可抢占性资源引起死锁:通常系统中所拥有的不可抢占性资源其数量不足以满足多个进程运行的需要。
  • 竞争可消耗资源引起死锁。
  • 进程推进顺序不当引起死锁:称不会引起进程死锁的推进顺序是合法的。

产生死锁的必要条件

  • 互斥条件(无法改变):进程对所分配到的资源进行排它性使用。
  • 请求和保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源又已被其它进程占有。此时请求进程阻塞,但又对自己已获得的其它资源保持不放。
  • 不可抢占条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。
  • 循环等待条件:指在发生死锁时,必然存在一个进程资源的环形链。

预防死锁

  • 事先预防,通过设置某些限制条件,使四个必要条件中的第 2、3、4 个条件之一不能成立,来避免发生死锁。预防死锁是一种较易实现的方法,已被广泛使用。但由于所施加的限制条件往往太严格,因而可能会导致系统资源利用率和系统吞吐量降低。

  • 互斥条件:不仅不能改变,还应加以保证。

  • 请求和保持条件:简单、易于实现且安全 ,资源被严重浪费,使进程延迟运行。

    第一种协议:该协议规定,所有进程在开始运行之前,必须一次性地申请其在整个运行过程中所需的全部资源。

    第二种协议:它允许一个进程只获得运行初期所需的资源后,便开始运行。

  • 不剥夺条件:当一个已经保持了某些资源的进程,再提出新的资源请求而不能立即得到满足时,必须释放它已经保持了的所有资源,待以后需要时再重新申请。因为一个资源在使用一段时间后,它的被迫释放可能会造成前段工作的失效。

  • 环路等待条件:系统将所有资源按类型进行线性排队,为系统中各类资源所分配(确定)的序号必须相对稳定,这就限制了新类型设备的增加,使先获得的资源被长时间闲置。为方便用户,系统对用户在编程时所施加的限制条件应尽量少。

系统安全状态

系统能按某种进程顺序(P1,P2,…,Pn)(称〈P1,P2,…,Pn〉序列为安全序列)来为每个进程Pi分配其所需资源,直至满足每个进程对资源的最大需求,使每个进程都可顺利地完成。如果系统无法找到这样一个安全序列,则称系统处于不安全状态,当系统进入不安全状态后,便有可能进而进入死锁状态。只要系统处于安全状态,系统便可避免进入死锁状态。

避免死锁(事先预防)

  • 避免死锁的实质在于系统在进行资源分配时,如何使系统不进入不安全状态 。如果不按照安全序列分配资源,则系统可能会由安全状态进入不安全状态

  • 在避免死锁的方法中,允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次资源分配的安全性,若此次分配不会导致系统进入不安全状态,则将资源分配给进程;否则,令进程等待。这种方法只需事先施加较弱的限制条件,便可获得较高的资源利用率及系统吞吐量,但在实现上有一定的难度。

  • 银行家算法中的数据结构

    可利用资源向量 Available:其中的每一个元素代表一类可利用的资源数目。其初始值是系统中所配置的该类全部可用资源的数目,其数值随该类资源的分配和回收而动态地改变。

    最大需求矩阵 Max:它定义了系统中 n 个进程中的每一个进程对每类资源的最大需求。

    分配矩阵 Allocation:定义了系统中每一类资源当前已分配给每一进程的资源数。

    需求矩阵 Need:用以表示每一个进程尚需的各类资源数。Need[i, j]=Max[i, j]-Allocation[i, j]

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

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

死锁的检测

  • 这种方法并不须事先采取任何限制性措施,也不必检查系统是否已经进入不安全区,而是允许系统在运行过程中发生死锁,但可通过系统所设置的检测机构,及时地检测出死锁的发生,并精确地确定与死锁有关的进程和资源,采取适当措施,从系统中将已发生的死锁清除掉。

  • 死锁检测算法:该方法用于检测系统状态,以确定系统中是否发生了死锁。系统必须做到保存有关资源的请求和分配信息,提供一种算法,以利用这些信息来检测系统是否已进入死锁状态。

  • 资源分配图(Resource Allocation Graph)
    系统死锁可利用资源分配图来描述。该图是由一组结点 N 和一组边 E 所组成的一个对偶 G=(N,E),我们用圆圈代表一个进程,用方框代表一类资源。由于一种类型的资源可能有多个,我们用方框中的一个点代表一类资源中的一个资源,此时,请求边是由进程指向方框,而分配边则应始于方框中的一个点。

  • 死锁定理:
    S 为死锁状态的充分条件是:当且仅当 S 状态的资源分配图是不可完全简化的。在资源分配图中,找出一个既不阻塞又非独立的进程结点 Pi,在顺利的情况下,Pi 可获得所需资源而继续运行,直至运行完毕,再释放其所占有的全部资源,这相当于消去 pi所求的请求边和分配边,使之成为孤立的结点。在进行一系列的简化后,若能消去图中所有的边,使所有的进程结点都成为孤立结点,则称该图是可完全简化的。若不能通过任何过程使该图完全简化,则称该图是不可完全简化的。

  • 死锁检测中的数据结构
    可利用资源向量 Available,它表示了 m 类资源中每一类资源的可用数目。把不占用资源的进程(向量 Allocationi:=0)记入 L 表中,即 Li∪L。 从进程集合中找到一个 Requesti≤Work 的进程,将其资源分配图简化,释放出资源,增加工作向量 Work:=Work + Allocation i,将它记入 L 表中。若不能把所有进程都记入 L 表中,便表明系统状态 S 的资源分配图是不可完全简化的。因此,该系统状态将发生死锁。

Work:=Available;    
L:={Li |Allocation i=0∩Request i=0}    
for all Li ∉L  do      
	begin        
	for all Request i≤Work do          
		begin           
		Work :=Work + Allocation i;           
		L i ∪L;
      	end        
	end      
deadlock :=(L={p1,p2,…,pn})

死锁的解除

  • 解除死锁是与检测死锁相配套的一种措施。当检测到系统中已发生死锁时,须将进程从死锁状态中解脱出来。常用的实施方法是撤消或挂起一些进程,以便回收一些资源,再将这些资源分配给已处于阻塞状态的进程,使之转为就绪状态。死锁的检测和解除措施有可能使系统获得较好的资源利用率和吞吐量,但在实现上难度也最大。
  • 剥夺资源:从其它进程剥夺足够数量的资源给死锁进程,以解除死锁状态。
  • 撤消进程:最简单的撤消进程的方法是使全部死锁进程都夭折掉;付出的代价可能会很大。稍微温和一点的方法是按照某种顺序逐个地撤消进程,直至有足够的资源可用,使死锁状态消除为止。付出的代价可能很大。每终止一个进程,都需要用死锁检测算法确定系统死锁是否已经被解除,若未解除,需再终止另一个进程。
  • 策略:为解除死锁状态所需撤消的进程数目最小或撤消进程所付出的代价最小等。从死锁状态 S 中先撤消一个死锁进程 P1,使系统状态由 S 演变成 U1,将 P1记入被撤消进程的集合 d(T)中,并把所付出的代价 C1 加入到 rc(T)中,对死锁进程 P2、P3 等重复上述过程,得到状态 U1,U2,…,Ui,Un。然后,再按撤消进程时所花费代价的大小,把它插入到由 S 状态所演变的新状态的队列 L 中。显然,队列 L 中的第一个状态 U1是由 S 状态花最小代价撤消一个进程所演变成的状态 。在撤消一个进程后,若系统仍处于死锁状态,则再从 U1 状态按照上述处理方式再依次地撤消一个进程。如此下去,直到死锁状态解除为止。为把系统从死锁状态中解脱出来,所花费的代价可表 示为: R(S)min = min{CUi} + min{CUj} + min{CUk} + …
发布了30 篇原创文章 · 获赞 1 · 访问量 406

猜你喜欢

转载自blog.csdn.net/weixin_46265246/article/details/105058156
今日推荐