第三章:处理机调度和死锁

第三章:处理机调度和死锁

1、处理机调度概述

处理机调度:按照一定的算法,从就绪队列中选择一个进程将处理机分配给它运行,以实现进程并发地执行。

1.1、处理机调度的层次

一个批处理型作业,从进入系统并驻留在外存的后备队列上开始,直至作业运行完毕,可能要经历的三级调度:
1586932462643.png

1.2、高级调度

High Level Scheduling、又称作业调度、长程调度、接纳调度

分时系统、实时系统一般直接进入内存,无此环节。

由于内存空间有限,有时无法将用户提交的作业全部放入内存,因此就需要确定某种规则,来决定将作业调入内存的顺序。

  • 作用:按照一定的调度算法,从外存后备队列中选择作业调入内存,创建PCB等,插入就绪队列(内存资源的角度)

  • 使用的系统:批处理系统

  • 调度时要决定:

    • 接纳作业数:取决于多道程序度。
    • 接纳策略:取决于作业调度算法。
  • 调度时机:有作业退出系统或者系统负荷不足时

  • 执行频率:几分钟、几秒钟。

1.3、低级调度

Low Level Scheduling、又称进程调度、短程调度

  • 作用:按某种规则,决定就绪队列中的某个进程获得处理机,由分派程序(Dispatcher)实施处理机分派。(CPU资源角度)
  • 使用系统:各种系统均需要。
  • 调度时要解决:
    • What:按照什么原则分配CPU?进程调度算法
    • When:什么时候引发进程调度、分配CPU?进程调度的时机
    • How:如何分配CPU?进程调度过程
  • 执行频率:几十毫秒一次。

1、抢占方式:允许调度程序根据某种原则,去暂停某个正在执行的进程,将处理机重新分配给另一个进程。

优点:

  • 防止一个长进程长时间占用处理机
  • 为大多数进程提供更公平的服务
  • 能满足对实时任务的需求

2、非抢占方式:一旦把处理机分配给某个进程后,一直让它运行下去,直至该进程完成,资源释放处理机,或被阻塞。

1.4、中级调度

Intermediate-Level Scheduling、中程调度

  • 对象:外存中因暂时不能运行而被挂起(就绪挂起和阻塞挂起)的进程

  • 动作:将外存挂起的进程激活,调入内存,进入就绪队列

  • 目的:提高内存的利用率和系统吞吐量。

注意

  • 三种调度运行频率:低级调度 > 中级调度 > 高级调度
  • 进程调度(低级调度)在操作系统中必不可少。

2、选择调度算法的准则

2.1、面向用户的准则

针对的系统
周转时间短(short turnaround time) 批处理系统
响应时间快(quick response time) 分时系统
截止时间的保证(guaranteed deadline) 实时系统
优先权原则(priority priciple) 各种OS

1、周转时间:从作业提交系统到完成为止

时间包括:

  • 驻外存等待作业调度时间
  • 驻内存等待进程调度时间(可能执行多次)
  • 执行时间(可能执行多次)
  • 阻塞时间(可能执行多次)

计算机系统要求的是:平均周转时间最短(mean turnaround time)

1586936110698.png

2、响应时间:从用户通过键盘提交一个请求开始,到系统首次产生响应(屏幕显示结果)为止的时间。是评价分时系统的一个重要指标。

  • 输入传送到CPU的时间
  • 处理的时间
  • 结果回送到显示器的时间

3、截止时间:任务必须开始执行的最迟时间,或必须完成的最迟时间。

评价实时系统性能的一个重要指标。

2.2、面向系统的准则

系统吞吐量高
处理机利用率高
各类资源平衡利用

1、系统吞吐量:单位时间内系统所完成的作业数。

评价批处理系统性能的重要指标

处理的长作业多,则吞吐量低

1586936909546.png

1586937282352.png

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

先来先服务(FCFS, First Come First Serve)是最简单的调度算法,按先后顺序进行调度。

定义:

  • 按照作业提交或进程变为就绪状态的先后次序,分派CPU;
  • 当前作业或进程占用CPU,直到执行完或阻塞,才出让CPU(非抢占方式)。
  • 在作业或进程唤醒后(如I/O完成),并不立即恢复执行,通常等到当前作业或进程出让CPU。

举例:

1586939056314.png

只考虑等候时间,忽略了执行时间。

优缺点(适用场景)

  • 有利于长作业(进程)而不利于短作业(进程)

  • 有利于CPU繁忙型作业(进程)而不利于I/O繁忙型作业(进程)

短作业优先(SJF, Shortest Job First)又称为“短进程优先”SPF(Shortest Process First);这是对FCFS算法的改进,其目标是减少平均周转时间。

定义:

  • 对预计执行时间短的作业(进程)优先分派处理机。

  • 通常后来的短作业不抢先正在执行的作业。

  • 但允许比当前进程剩余时间更短的进程来抢占

举例:

1586939777530.png

1586939801441.png

1、优点:

比FCFS改善平均周转时间平均带权周转时间,缩短作业的等待时间;

提高系统的吞吐量

2、缺点:

  • 对长作业非常不利,可能长时间得不到执行;

  • 未能依据作业的紧迫程度来划分执行的优先级,不能保证紧迫性作业(进程)会被及时处理。

  • 无法精确知道一个作业的运行时间,作业(进程)的长短只是根据用户所提供的估计运行时间而定的。

4、高优先权优先和高响应比优先调度算法

优先级算法(Priority Scheduling)是多级队列算法的改进,平衡各进程对响应时间的要求。适用于作业调度和进程调度,可分成抢先式和非抢先式。

静态优先权:

  • 在创建进程时确定的,且在进程的整个运行期间保持不变。

动态优先权:

  • 在创建进程时所赋予的优先权。
  • 可以随进程的推进或随其等待时间的增加而改变的。

同时适用于作业调度和进程调度

优先权调度算法的类型:

1、非抢占式优先权算法:

  • 用于批处理系统中;
  • 也可用于某些对实时性要求不严的实时系统中;

2、抢占式优先权算法:

  • 常用于 要求比较严的实时系统
  • 对性能要求较高的批处理和分时系统中

最高响应比优先法(HRRF,Highest Response_ratio First)是对FCFS方式和SJF方式的一种综合平衡

  • FCFS只考虑作业的等待时间,而忽视了作业的计算时间
  • SJF或SPF只考虑用户估计的作业的计算时间,而忽视了作业的等待时间

最高响应比优先算法(HRRF)是介于FCFS和SJF这两者之间的折中算法。

  • 既考虑了作业等待时间,又考虑了作业的运行时间。
  • 既照顾了短作业,又不使长作业的等待时间过长。
  • 改进了调度性能。

引入动态优先权,使作业的优先级随着等待时间的增加而以速率 a 提高

响应比R定义如下: R =(W+T)/T = 1+W/T

其中T为该作业估计需要的执行时间,W为作业在后备状态队列中的等待时间。每当要进行作业调度时,系统计算每个作业的响应比,选择其中R最大者投入执行

几点说明:

  • 等待时间相同,则要求服务时间愈短,优先权愈高 -- SJF
  • 服务时间相同,优先权决定于等待时间 -- FCFS
  • 长作业,等待一定时间后,则响应比增加,利于调度。

由于每次调度前要计算响应比,系统开销也要相应增加。

5、死锁概述

死锁:死锁是指两个或两个以上的线程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象。

若无外力作用,它们都将无法推进下去。

此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。

5.1、产生死锁的原因:

  • 资源不足导致的资源竞争:多个进程所共享的资源不足,引起它们对资源的竞争而产生死锁。
  • 并发执行的顺序不当。进程运行过程中,请求和释放资源的顺序不当,而导致进程死锁。如在消费者-生产者问题中的P,V操作的顺序不当。

死锁可能涉及同一种类型的资源、或者是不同类型的资源。

5.2、竞争资源引起死锁(不可避免)

1587024020916.png

5.3、进程推进顺序不当引起死锁(进程并发的异步性)

1587024225476.png

关于死锁的几个有用结论

  1. 参与死锁的进程数至少为二
  2. 参与死锁的所有进程均在等待资源
  3. 参与死锁的进程至少有两个占有资源
  4. 参与死锁的进程时系统中当前正在运行进程集合的一个子集

5.4、死锁产生的四个必要条件

虽然进程在运行过程中,可能发生死锁,但死锁的发生也必须具备一定的条件,死锁的发生必须同时具备以下四个必要条件:

1、互斥条件

系统中存在临界资源,进程应互斥使用这些资源

2、请求和保持条件

进程在请求资源得不到满足而等待时,不释放已占有的资源。

3、不剥夺条件

已占有的资源只能由属主释放,不允许被其他进程剥夺。

4、环路等待条件

在发生死锁时,必然存在一个由 两个或两个以上进程 形成的进程—资源 环形链。环路中的进程形成等待链。

6、死锁的预防和避免

6.1、处理死锁的方法

1、预防死锁:通过预先设置条件,破坏产生死锁的一个或几个必要条件(静态策略)

2、避免死锁(不让死锁发生):不事先采取措施,在资源的动态分配过程中,防止出现死锁(动态策略)

3、检测和接触死锁(允许死锁发生):允许死锁发生,但通过检测机构能及时检测出,采用解除机制,清除死锁。

4、忽略死锁(鸵鸟算法):假装死锁永不发生,对死锁不采取任何措施,会造成系统奔溃。

6.2、预防死锁

预防死锁的本质实际上是,破坏产生死锁的四个必要条件中的一个或者多个,来保证不会发生死锁现象。

保证互斥条件

由于设备(非共享资源)的固有特性所决定,因此我们无法剥夺互斥条件,只能加以保护互斥条件。

摒弃请求和保持条件

要求所有的进程要一次性的申请在整个运行过程中所需的所有资源;

允许进程在没有资源的情况下,可以申请资源。

优点:

  • 简单、易于实现、安全。

缺点:

  • 一个进程可能被阻塞很长时间,等待资源,发生饥饿。
  • 资源严重浪费,进程延迟运行。

摒弃不剥夺条件

可以剥夺一个进程占有的资源,分配给其他进程

一个已经保持了某些资源的进程,当它再提出新的资源请求而不能立即得到满足时,必须释放它已经保持的所有资源,待以后需要时再重新申请;

适用条件:资源的状态可以很容易地保存和恢复,如CPU寄存器、内存空间,不能适用于打印机、磁带机

缺点:实现复杂、代价大,反复申请 / 释放资源,系统开销大,降低系统吞吐量。

摒弃环路等待条件

此方法要求资源类型序号相对稳定,进程对资源的请求 必须按照资源序号递增 的次序提出。

缺点:

  • 易造成资源浪费
  • 限制进程对资源的请求

总之,预防死锁是一种较易实现的方法,但由于所施加的限制条件往往太严格,可能会导致系统资源利用率和系统吞吐量降低。

6.3、避免死锁

定义:在系统运行过程中,对进程发出的每一个系统能够满足的资源申请进行动态检查,并根据检查结果决定是否分配资源,若分配后系统可能发生死锁,则不予分配,否则予以分配。

也就是:

  • 如果一个新进程的资源请求会导致死锁,则拒绝启动这个进程;
  • 如果满足一个进程新提出的一项资源请求会导致死锁,则拒绝分配资源给这个进程;

1587028154975.png

1587034271596.png

  • 如果系统处于安全状态(safe),没有死锁;
  • 如果系统处于不安全状态(unsafe),有可能死锁;
  • 死锁的避免本质上是:确保系统永远不会进入不安全状态;

7、银行家算法

重点是掌握算法的执行过程(原理)!

7.1、银行家算法

背景:银行家算法(Banker's Algorithm)是一个避免死锁(Deadlock)的著名算法,是由艾兹格·迪杰斯特拉在1965年为T.H.E系统设计的一种避免死锁产生的算法。它以银行借贷系统的分配策略为基础,判断并保证系统的安全运行。

对借贷的客户,好比是向操作系统申请资源的进程,需要满足一下约束条件:

  • 每位客户必须预先说明自己所要求的的 最大资金量
  • 每位客户每次提出 部分资金量 申请和获得分配;
  • 如果银行满足了客户对资金的最大需求量,则客户在资金运作后,能在有限时间内 全部归还

银行家算法的设计思想:

当用户申请一组资源时,系统必须做出判断:如果把这些资源分出去,系统是否还处于安全状态,若是,就可以分配这些资源;否则,暂时不分配。

为实现银行家算法,系统必须实现某些数据结构

1)可利用资源向量Available

是个含有m个元素的数组,其中的每一个元素代表一类可利用的资源数目。如果Available[j]=K,则表示系统中现有Rj类资源K个。

2)最大需求矩阵Max

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

3)分配矩阵Allocation

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

4)需求矩阵Need

这也是一个n×m的矩阵,用以表示每一个进程尚需的各类资源数。如果Need[i,j]=K,则表示进程i还需要Rj类资源K个,方能完成其任务。

Need[i,j]=Max[i,j]-Allocation[i,j]

算法实现步骤:

设Requesti是进程Pi的请求向量,如果Requesti[ j ] = K,表示进程 Pi需要K个Rj类型的资源。当Pi发出资源请求后,系统按下述步骤进行检查:

1)如果Requesti[ j ] <= Need[i, j],便转向步骤 2);

否则认为出错,因为它所需要的资源数已超过它所宣布的最大值;

2)如果Requesti[ j ] <= Available[i, j],便转向步骤 3);

否则表示当前尚无足够的资源,Pi需要等待;

3)系统试探着把资源分配给进程 Pi,并修改下面的数据结果中的数值

Available[j] = Available[j] - Request[j];
Allocation[i, j] = Allocation[i, j] - Request[j];
Need[i, j] = Need[i, j] - Request[j];

4)系统执行安全性检查算法,检查此次资源分配后,系统是否处于安全状态。若安全,才正式将资源分配给进程 Pi,已完成本次分配;

否则,将本次的试探分配作废,恢复原来的资源分配状态,让进程 Pi等待。

7.2、安全性检查算法

1、设置两个向量

  • 工作向量 Work:它表示系统可提供给进程继续运行所需的各类资源数目,它含有 m 个元素,在执行安全性检查算法开始时, Work := Available
  • Finish:它表示系统是否有足够的资源分配给进程,使之运行完成。开始时先做 Finish[ i ] := false; 当有足够资源分配给进程时,再令 Finish[ i ] := true;

2、从进程集合中找到一个能满足下述条件的进程

Finish[i] = false;
Need[i,j] <= Work[j]; 
// 若找到,执行步骤 3,否则,执行步骤 4

8、例题

1、

1587259825275.png

1)FCFS:

作业号 提交时刻 执行时间 完成时间 周转时间 带权周转时间
1 10:00 2 12:00 2 1
2 10:20 1 13:00 2.67 2.67
3 10:40 0.5 13:30 2.83 5.66
4 10:50 0.3 13:48 2.97 9.89

平均周转时间:2.617 小时

平均带权周转时间:4.805 小时

调度顺序:1 --> 2 --> 3 --> 4

2)SJF:

作业号 提交时刻 执行时间 完成时间 周转时间 带权周转时间
1 10:00 2 12:00 2 1
2 10:20 1 13:48 3.47 3.47
3 10:40 0.5 12:48 2.13 4.26
4 10:50 0.3 12:18 1.47 4.9

平均周转时间:2.268 小时

平均带权周转时间:3.408 小时

调度顺序:1 --> 4 --> 3 --> 2

原文地址:https://www.cnblogs.com/rainszj/p/12730508.html