资源分配与调度

1 资源管理概述

1.1 资源管理的目的和任务

目的:
1、保证资源的高利用率;
2、在“合理”时间内使所有顾客有获得所需资源的机会;
3、对不可共享的资源实施互斥使用;
4、防止由资源分配不当而引起的死锁。

对资源的管理应包括以下几个方面:
1、资源管理的描述--数据结构
2、确定资源的分配原则和调度原则
3、执行资源分配(实施)
4、存取控制和安全保护

1.2 资源的几种分类方法

(一)物理资源和程序资源
(二)单一访问入口的资源和多访问入口的资源
(三)等同资源
(四)虚拟资源

1.3资源管理的机构和策略

机构
进行资源分配所必需的基本部件,它包括描述资源状态的数据结构,还包括保证不可共享资源互斥使用的技术以及对不能满足的资源请求进行排队的手段等。

策略
给出机构所使用的方法,涉及到相应资源满足的情况下,批准请求的决策,包括死锁问题和系统平衡问题。

2 资源分配机构

描述资源的管理和控制信息的数据结构称为资源分配的机构 。
在教材上列出了两种:资源描述器、资源信息块
在实际的系统中,会根据实际需要设计相应的数据结构。例如:进程管理主要管理的机构:PCB、就绪队列和各种等待队列。

2.1 资源描述器

描述各类资源的最小分配单位的数据结构称为资源描述器rd(resource descriptor)
存放于一个描述器中的信息取决于资源的特征与对该资源的管理方式。
最简化的描述器可以用一个二进制位来实现,它表示该资源是可用的,还是已分配的。

2.2 资源信息块

资源信息块rib (resource information)是一个数据结构,应能说明资源、请求者以及实施分配所需的必要信息。
资源分配程序是接收分配命令把资源分配给请求者的例程。包括:分配程序和去分配程序。

3资源分配策略

3.1 概述

资源分配有两种方式:
静态分配:当一个进程(或程序)运行前,将它要求的资源一次分配给该进程,直到该进程终止,释放其占用的所有资源。这种分配方法效率太低;
动态分配:当一个进程要求使用某个(类)资源时,向系统提出资源的请求,系统响应程序的请求将某种资源分配给请求者,这种方法使得系统资源的利用率提高,但有可能造成死锁。
几种分配策略:
1、先请求先服务(FIFO)
2、优先调度
3、适应调度
4、均衡调度
5、针对设备特性的调度

3.2 先请求先服务(FIFO)

简单排队站策略或FIFO(First In First Out)策略。
按照进程就绪的先后次序来调度进程
优点:实现简单
缺点:没考虑进程的优先级

3.3 优先调度

在优先调度策略下,对于每个进程(或作业)要指定一个优先级,这一优先级反映了进程要求处理的紧迫程度。
进程调度队列是按进程的优先级由高到低的顺序排列的,队首为优先级最高者。
优先选择就绪队列中优先级最高的进程投入运行
优先级根据优先数来决定。

确定优先数的方法
静态优先数法:
在进程创建时指定优先数,在进程运行时优先数不变
动态优先数法:
在进程创建时创立一个优先数,但在其生命周期内优先数可以动态变化。如等待时间长优先数可改变。

两种占用CPU的方式
可剥夺式(可抢占式Preemptive):
当有比正在运行的进程优先级更高的进程就绪时,系统可强行剥夺正在运行进程的CPU,提供给具有更高优先级的进程使用
不可剥夺式(不可抢占式Non-preemptive ):
某一进程被调度运行后,除非由于它自身的原因不能运行,否则一直运行下去

分时系统中常用时间片轮转法

时间片选择问题:
固定时间片
可变时间片

与时间片大小有关的因素:
系统响应时间
就绪进程个数
CPU能力

多队列反馈调度算法:
将就绪队列分为N级,每个就绪队列分配给不同的时间片,队列级别越高,时间越长,级别越小,时间片越小,最后一级采用时间片轮转,其他队列采用先进先出; 系统从第一级调度,当第一级为空时,系统转向第二个队列,…当运行进程用完一个时间片,放弃CPU时,进入下一级队列;等待进程被唤醒时,进入原来的就绪队列;当进程第一次就绪时,进入第一级队列 。

  • 首先系统中设置多个就绪队列

  • 每个就绪队列分配给不同时间片,优先级高的为第一级队列,时间片最小,随着队列级别的降低,时间片加大

  • 各个队列按照先进先出调度算法

  • 一个新进程就绪后进入第一级队列

  • 进程由于等待而放弃CPU后,进入等待队列,一旦等待的事件发生,则回到原来的就绪队列

  • 当有一个优先级更高的进程就绪时,可以抢占CPU,被抢占进程回到原来一级就绪队列末尾

  • 当第一级队列空时,就去调度第二级队列,如此类推

  • 当时间片到后,进程放弃CPU,回到下一级队列

  • 进程调度的时机
    当一个进程运行完毕,或由于某种错误而终止运行
    当一个进程在运行中处于等待状态(等待I/O)
    分时系统中时间片到

*进程调度的时机
当有一个优先级更高的进程就绪(可抢占式),例如:新创建一个进程,一个等待进程变成就绪。
在进程通信中,执行中的进程执行了某种原语操作(P操作,阻塞原语,唤醒原语)

*CPU调度过程

  • 保存现场:顺序保存,最后一步保存PSW
  • 选择要运行的程序
    (如果没有就绪进程,系统会安排一个闲逛进程(idle),没有其他进程时该进程一直运行,在执行过程中可接收中断)
  • 恢复现场:最后一步恢复选中进程的PSW

4 死锁

4.1 死锁的概念

在这两个进程并发执行时,当P1进程占有R1、P2进程占用R2时,P1要求R2,由于P2已占R2有而得不到,P1进程只有等待;P2申请R1,由于P1已占有R1,而得不到,P2进程只有等待,就出现了死等的情况。
在这里插入图片描述
死锁是进程死锁的简称,是由Dijkstra于1965年研究银行家算法时首先提出来的。它是计算机操作系统乃至并发程序设计中最难处理的问题之一。实际上,死锁问题不仅在计算机系统中存在,在我们日常生活中它也广泛存在。
在计算机系统中,涉及软件,硬件资源都可能发生死锁。例如:系统中只有一台CD-ROM驱动器和一台打印机,某一个进程占有了CD-ROM驱动器,又申请打印机;另一进程占有了打印机,还申请CD-ROM。结果,两个进程都被阻塞,永远也不能自行解除。

死锁简单的定义:
死锁就是两个或两个以上的进程等候着一个永远不会发生的事件时所处的一种系统状态。
教材上关于死锁的定义:
两个或两个以上并发进程,如果每个进程持有某种资源,而又等待着别的进程释放它或它们现在保持着的资源,否则就不能向前推进。此时,每个进程都占用了一定的资源,但又都不能向前推进。这种现象称为死锁。

4.2 死锁的起因

并发进程共享系统资源,在竞争资源时可能会产生称为死锁的附带后果。
产生死锁的根本原因是系统能够提供的资源个数比要求该资源的进程数要少。所以,当系统中两个或多个进程没有能力进一步时。系统就发生死锁。
A1: P1 request(r1) A2: P2 request(r2)
B1: P1 request(r2) B2: P2 request(r1)
C1: P1 request(r1) C2: P2 request(r2)
D1: P1 request(r2) D2: P2 request(r1)
在这里插入图片描述
第一条折线:p1运行,p2运行。
p1运行 A1: P1 request(r1),B1: P1 request(r2)
C1: P1 request(r2),D1: P1 request(r1)
p2运行 A2: P2 request(r2),B2: P2 request(r1)
C2: P2 request(r2),D2: P2 request(r1)

第二条折线:p1运行,p2运行, p1运行 。
p2运行 A2: P2 request(r2),B2: P2 request(r1)
C2: P2 request(r2),D2: P2 request(r1)
p1运行 A1: P1 request(r1),B1: P1 request(r2)
C1: P1 request(r1),D1: P1 request(r2)

第三条折线:p1运行,p2运行。
p1运行 A1: P1 request(r1);
p2运行 A2: P2 request(r2),进入D区;
p1运行 B1: P1 request(r2),p1阻塞;
p2运行 B2: P2 request(r2),p2阻塞,到达死锁点N。
在此种情况下出现死锁。

产生死锁的原因是:系统资源不足;进程推进顺序非法。

产生死锁的四个必要条件:
1、互斥条件
2、不可剥夺条件
3、部分分配
4、环路条件

在这里插入图片描述

4.3 解决死锁问题的策略

一、解决死锁问题的几个策略
为了不发生死锁,必须设法破坏产生死锁的四个必要条件之一。
条件1:难以否定,但可采用相应的技术,如利用假脱机技术,即用可共享使用的设备模拟非共享的设备;
条件2:容易否定,可制定相应的规则即可,例如,当一个进程(程序)申请某资源被拒绝,则必须释放已占用的资源,如需要再与其它所需资源一起申请。对CPU还可进行可剥夺分配。
条件3:也是很容易否定的,只要分配策略上规定一个进程(或程序)一次将所需资源一次申请到位。用完后释放。可以全部用完后,统一释放,也可使用完后立即释放,只要是一次申请到的,系统就不会出现死锁。
条件4:实际上系统不采用部分分配,也就破坏了环路条件。

二、系统状态分析(略)

4.4 死锁的预防

预先分配一个进程要用的所有资源是防止死锁的一种安全而简单的方法,但设备的使用效率太低。其缺点也是明显的:
1、一个用户(进程)在程序运行之前很难提出将要使用的全部设备;
2、设备(资源)的浪费太大,有些资源在进程运行过程中可能只有很少的时间才用到,有的甚至不会用到,例如,一个分支语句。

4.5 死锁的避免

为了提高设备的利用率,应采用动态的设备分配方法,但应设法避免发生死锁,若存在发生死锁的可能性,则拒绝分配。
预防死锁:
采用的分配策略本身就否定了产生死锁的四个必要条件之一,这就保证了不会发生死锁;
死锁避免:
是在动态分配资源的策略下采用某种算法来预防可能发生的死锁,从而拒绝可能产生死锁的某个资源的请求。
一、有序资源分配法
这种算法按某种规则为系统中的所有资源统一编号(例如打印机为1、磁带机为2、磁盘为3、等等),申请时必须以上升的次序。
系统要求申请进程:
1、对它所必须使用的而且属于同一类的所有资源,必须一次申请完;
2、在申请不同类资源时,必须按各类设备的编号依次申请。
例如:进程PA,使用资源的顺序是R1,R2;
进程PB,使用资源的顺序是R2,R1;
若采用动态分配有可能形成环路条件,造成死锁。
采用有序资源分配法:R1的编号为1,R2的编号为2;
PA:申请次序应是:R1,R2
PB:申请次序应是:R1,R2
这样就破坏了环路条件,避免了死锁的发生。

二、银行家算法
避免死锁算法中最有代表性的算法是Dijkstra E.W 于1968年提出的银行家算法:
该算法需要检查申请者对资源的最大需求量,如果系统现存的各类资源可以满足申请者的请求,就满足申请者的请求。
这样申请者就可很快完成其计算,然后释放它占用的资源,从而保证了系统中的所有进程都能完成,所以可避免死锁的发生。

4.6 死锁的检测和恢复

死锁的检测:
通常的方法是程序员的经验,如UNIX系统中,可考察进程的运行时间。在UNIX系统中有命令PS可显示进程占用CPU的时间,若发现有一组进程在一段时间内没有占用CPU,就认为这类进程出现了死锁。
死锁排除的方法:
1、撤销陷于死锁的全部进程;
2、逐个撤销陷于死锁的进程,直到死锁不存在;
3、从陷于死锁的进程中逐个强迫放弃所占用的资源,直至死锁消失。

  • 3
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
很抱歉,Python并不是操作系统,也不是用于操作系统开发的编程语言,因此Python本身并没有实现银行家算法。但是,我们可以使用Python编写模拟银行家算法的程序来进行资源分配和进程调度的模拟。 以下是一个简单的Python程序,用于模拟银行家算法的资源分配和进程调度: ```python 定义银行家算法的数据结构 class Banker: def __init__(self, available, max_need, allocation): self.available = available # 可用资源 self.max_need = max_need # 进程最大需求量 self.allocation = allocation # 进程已分配资源量 self.need = max_need - allocation # 进程尚需资源量 # 检查是否存在安全序列 def is_safe(self): work = self.available.copy() finish = [False] * len(self.max_need) safe_sequence = [] while True: found = False for i in range(len(self.max_need)): if not finish[i] and all(need <= work for need, work in zip(self.need[i], work)): work = [work[j] + self.allocation[i][j] for j in range(len(work))] finish[i] = True safe_sequence.append(i) found = True if not found: break return all(finish), safe_sequence # 分配资源 def allocate(self, process_id, request): if all(request <= self.need[process_id]) and all(request <= self.available): self.available -= request self.allocation[process_id] += request self.need[process_id] -= request return True else: return False # 释放资源 def release(self, process_id, release): self.available += release self.allocation[process_id] -= release self.need[process_id] += release # 测试程序 if __name__ == '__main__': # 初始化银行家算法的数据结构 available = [3, 3, 2] max_need = [[7, 5, 3], [3, 2, 2], [9, 0, 2], [2, 2, 2], [4, 3, 3]] allocation = [[0, 1, 0], [2, 0, 0], [3, 0, 2], [2, 1, 1], [0, 0, 2]] banker = Banker(available, max_need, allocation) # 模拟进程请求资源 process_id = 0 request = [0, 2, 0] if banker.allocate(process_id, request): print('分配成功') if banker.is_safe()[0]: print('存在安全序列') else: print('不存在安全序列,分配失败') banker.release(process_id, request) else: print('分配失败') ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值