计算机操作系统笔记(3)

第三章处理机调度与死锁

3.1处理机调度的层次和调度算法的目标

处理机的调度层次

  • 高级调度/作业调度
    根据某种算法,决定将外存上处于后备队列的哪几个作业调入内存,然后为其分配资源
    主要用于多道批处理系统中,在分时和实时系统不设置高级调度
  • 低级调度/进程调度
    调度对象是进程(或内核级线程)
    有抢占和非抢占方式
    三种调度中最重要的一种,多道批/分时/实时系统都必有
  • 中级调度/内存调度
    作用:提高内存利用率和系统吞吐量

调度队列模型

  1. 仅有进程调度的调度队列模型
  2. 具有高级和低级调度的调度队列模型
    与模型1的区别:
    就绪队列的形式
    设置多个阻塞队列
  3. 同时具有三级调度的调度队列模型

    (实际很少用,更多是在虚拟内存中唤入唤出)

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

面向用户的准则:

  • 周转时间短(常用于批处理系统)
    概念:作业从提交到完成的时间
    分为:驻外等待时间、驻内等待时间、执行时间、阻塞时间
    平均周转时间:T=1n[i=1nTi]
    平均带权:W=1n[i=1nTiTs]Ti是作业的周转时间,Ts是系统为它提供服务的时间)
    T,W越小越好
  • 响应时间快:(对交互性作业)
    概念:键盘首次提交请求到首次响应的时间
    包括:输入传送时间、处理时间、响应传送时间
  • 截止时间的保证(特别是实时系统)
  • 优先权准则(即需要抢占调度)

面向系统准则:

  • 吞吐量高(特别于批处理):单位时间完成的作业数
  • 处理机利用率高:(因CPU贵,特别于大中型多用户系统)
  • 各类资源的平衡利用

3.2&3.3调度算法

FCFS、SJF(可用于作业/进程调度)

  • FCFS:先来先服务调度算法
    按照作业到达的先后顺序来进行调度
    考虑等待时间最长的作业
    特点:
    简单,有利于长时间作业
  • SJF:短作业优先调度算法
    按照作业的长短来计算优先级(越短优先级越高)
    考虑运行时间最长的作业
    特点:
    平均周转时间比FCFS快
    对长作业不利,有可能得不到服务(饥饿)
    估计时间不易确定

高优先权优先调度算法

  • 优先权调度算法类型(多用于进程,可用于作业)
  1. 非抢占式:执行某进程时除非完成或阻塞否则不会让出处理机
  2. 抢占式:允许按某种原则中断某个正在执行的进程将处理机分配给另一进程(包括:优先权原则、短进程优先原则、时间片原则)
    (非抢占式和抢占式都无法解决饥饿问题)
  • 优先权类型(多用于进程,可用于作业)
  1. 静态优先权:进程优先权在整个运行期不变
    确定优先权依据:进程类型、进程对资源的需求、根据用户需求
    特点:简单,但低优先权作业可能长期不被调度
  2. 动态优先权:进程优先级随进程推进或等待时间的增加而改变
    利用响应比Rp作为优先权
    优:长短兼顾 缺:要计算Rp
  • 高响应比优先算法(主要用于作业调度)
    响应比(Rp) = tw+tsts
    特点:
    短作业RP大(RP大优先服务)
    ts相同的进程间相当于FCFS
    长作业等待一段时间仍能得到服务

基于时间片的轮转调度算法(用于进程调度)

  • 时间片轮转算法
    时间片大小的确定(过大退化为FCFS,过小系统开销过大)
    系统对响应时间的要求(T=nq)
    就绪队列中进程的数目
    系统的处理能力:(应保证一个时间片处理完常 用命令)
  • 多级反馈队列调度
    设置多个就绪队列,每个队列的优先级不同(第一最高,后面逐渐降低)
    每个队列采取FCFS算法
    按队列优先级调度,优先级高的时间片小
    特点:长、短作业兼顾,有较好的响应时间(短时间作业一次完成、中型作业周转时间不长、大型作业不会长期不处理)

n道批处理系统,一次最多能将n个作业调度到内存中,其余作业被阻塞在内存之外
当前,在系统处理任务时,不考虑并发,处理机一次只能处理一个进程(通常问题中也是一个作业一个进程),其它进程则在内存中等待
进程处理时可被打断被别的优先级更高的作业/进程抢占执行,被打断的进程则在内存中等待

3.4实时调度

实现实时调度的基本条件

  • 提供必要的信息
    包括就绪时间、开始截止时间和完成截止时间、处理时间、资源要求、优先级
    (开始截止时间和完成截止时间是很多情况下是等价的)
  • 系统处理能力强
    单处理机情况下,满足下列条件才可调度:
    i=1mCiPi1Ci为处理时间,Pi为周期时间,N为处理机数)
    提高系统处理能力的途径:增强处理能力(减少每个任务的处理时间Ci减小)、采用多处理机系统(N增大)
    i=1mCiPiN
  • 采用抢占调度方式
  • *具有快速切换机制

实时调度算法的分类

分为非抢占式调度算法、抢占式调度算法

  • 非抢占式调度算法
    非抢占式轮转调度算法:安排一个队列,每次取队首执行,完成后挂在队尾
    非抢占式优先调度算法:安排一个队列,队列中的任务按优先级排列,每次取队首(当前优先级最高)执行
  • 抢占式调度算法
    基于时钟中断的抢占式优先级调度算法:在非抢占优先调度算法的基础上,把时钟作为调度时间
    立即抢占的优先级调度算法:与基于时钟中断相类似,不过一旦出现外部中断就立即剥夺执行(只要不在临界区),把处理机分配给请求中断的任务

最早截止时间算法(EDF)

根据任务的截止时间确定任务的优先级(截止时间越早优先级越高)
最早截止时间算法可用于抢占和非抢占式调度

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

最低松弛度优先算法(LLF)

根据任务的紧急程度(松弛度)判断优先级(松弛度越低优先级越高)
主要用于可抢占的调度方式中
松弛度=完成截止时间-当前时间-本身运行时间

3.5死锁概述

产生死锁的原因

  • 竞争资源引起死锁
    可剥夺(CPU、内存)和不可剥夺性(打印机,磁带机)资源
    竞争非剥夺性资源可造成死锁
    竞争临时性资源可造成死锁

  • 进程推进顺序不当引起死锁

产生死锁的必要条件

包括四个条件:

  1. 互斥条件(资源的临界性)
  2. 请求和保持条件
  3. 不剥夺条件
  4. 环路等待

处理死锁的基本方法

包括预防、避免、检测、解除(前两个是发生前、后两个是发生后)

  1. 预防:破坏4个必要条件之一
    有效,但使资源利用率低
  2. 避免:防止进入不安全状态
    允许动态申请资源,银行家算法
  3. 检测:检测到死锁再清除
  4. 解除:与“检测”配套

3.6预防死锁

破坏产生死锁的四个必要条件中的一个或几个

  1. 破坏互斥条件:互斥是资源固有属性,不可避免
  2. 破坏请求和保持条件:资源的一次性分配
    全分配,全释放(AND)
    缺点:延迟进程运行、资源严重浪费
  3. 破坏“不剥夺”条件:新申请不能满足则释放已获得资源
    缺点:增加系统开销,且进程前段工作可能失效
  4. 破坏“环路”条件:资源的有序分配法(为资源编号,申请时需按编号进行)
    缺点:新增资源不便(原序号已排定)、用户不自由、资源与进程使用顺序不同造成浪费

3.7避免死锁

安全状态:在“避免死锁”方法中的判断条件(能找到安全序列(进程执行序列)的状态为安全状态)

  • 银行家算法:一种能够避免死锁的调度算法
    大致思想:

    特点:
    1)允许动态申请资源,可提高资源利用率
    2)要求事先说明最大资源要求,在现实中很困难
    数据结构:
max[i,j]=k; //进程i需要Rj的最大数k个
alloc[i,j]=k; //进程i已得到Rj类资源k个
need[i,j]=k; //进程i还需要Rj类资源k个
available[j]=k; //系统现有Rj类资源k个
有:need[i,j]= max[i,j]-alloc[i,j]
Requesti[j]=k; //表示进程i需要k个Rj类型的资源(Requesti[j]要<=need[i,j])
Work 表示进程继续运行所需的各类资源数目
在执行安全算法开始时,Work∶=Available
finish[i]; //布尔量,表进程i能否顺序完成

算法伪代码:

//一开始判断资源能否分配给某个进程
//银行家算法进行检查
if(reqi<=need); //判断是否合法
else error;
if(reqi<=avail); //判断资源是否足够
else block;
//先假设性地分配资源
//修改相关数据结构
avail=avail-reqi;
alloci=alloci+reqi;
needi=needi-reqi;
//再推算出剩下的进程需求是否有满足要求的执行序列
//安全性算法
while()
{
//找到满足条件的进程
finish[i]=.F.
needi<=work
//进程结束后释放资源
work=work+alloci
finish[i]=.T.
}

3.8死锁的检测与解除

死锁的检测

  • 资源分配图
    圆圈表示进程,方框表示资源,方框内的点表示资源数,箭头表示“占有”或者“请求”
  • 死锁定理
    S为死锁状态的充分条件是:当且仅当S状态的资源分配图是不可完全简化
    简化:找出一个既不阻塞又非独立的进程结点(从进程集合中找到一个有边连接,并且资源申请数量小于系统中的空闲资源数)
  • 检测死锁的算法
Work = available
L = {Li|alloci=0 ∩ reqi=0} //孤立进程点并入集合L
for(all Li ∉ L) //对于所有非孤立进程点
{
for(all reqi <= Work) //不阻塞则并入集合L
{
Work = Work + alloci;
Li ∪ L;
}
}
deadlock = ~(L={p1 … pn}) //若所有进程点都在L中则不会发生死锁
  • 检测死锁的时机
    资源请求时去检测(占用昂贵的CPU时间)
    每隔一定时间检测一次
    CPU使用率下降到某一阀值时检测(原因:死锁进程过多->较少进程可以被执行->CPU被限制)

死锁的解除

三种办法:

  1. 抢占资源
    从某一进程抢走资源给其他进程使用,完了再还给原来的进程
    较野蛮
  2. 进程回退
    定期记录进程状态信息,死锁时再逐步倒回历史状态
    不野蛮,但代价高
  3. 撤消进程(目前最常用)
    两种撤销:终止所有死锁进程、逐个终止死锁进程
    很野蛮
posted @   kksk43  阅读(214)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
特效
黑夜
侧边栏隐藏
点击右上角即可分享
微信分享提示