一、实验目的与实验环境
实验目的:
本题主要内容是模拟实现资源分配。银行家算法是避免死锁的一种重要方法,本实验要求用高级语言编写和调试一个简单的银行家算法程序。加深了解有关资源申请、避免死锁等概念,并体会和了解死锁和避免死锁的具体实施方法。
实验环境:
Windows 10
Python 3.9.13
二、实验内容
1、银行家分配算法
银行家分配算法,顾名思义是来源于银行的借贷业务,一定数量的本金要应多个客户的借贷周转,为了防止银行加资金无法周转而倒闭,对每一笔贷款,必须考察其是否能限期归还。在操作系统中研究资源分配策略时也有类似问题,系统中有限的资源要供多个进程使用,必须保证得到的资源的进程能在有限的时间内归还资源,以供其他进程使用资源。如果资源分配不得到就会发生进程循环等待资源,每个进程都无法继续执行下去的死锁现象。
把每个进程需要和已占有资源的情况记录在进程控制中,假定进程控制块PCB其中“状态”有就绪态、等待态和完成态。当进程在处于等待态时,表示系统不能满足该进程当前的资源申请。“资源需求总量”表示进程在整个执行过程中总共要申请的资源量。显然,每个进程的资源需求总量不能超过系统拥有的资源总数,银行算法进行资源分配可以避免死锁。
2、算法描述
银行家算法:
设进程I提出请求Request[N],则银行家算法按如下规则进行判断。
(1) 如果Request[N]<= Need [I, N],则转(2);否则,出错。
(2) 如果Request[N]<= Available,则转(3);否则,出错。
(3) 系统试探分配资源,修改相关数据:
Available = Available -Request
Allocation = Allocation +Request
Need= Need - Request
(4) 系统执行安全性检查,如安全,则分配成立;否则试探险性分配作废,系统恢复原状,进程等待。
3、安全性检查
(1) 设置两个工作向量Work= Available;Finish[M]=False
(2) 从进程集合中找到一个满足下述条件的进程
Finish[i]=False
Need <=Work
如找到,执行(3);否则,执行(4)
(3) 设进程获得资源,可顺利执行,直至完成,从而释放资源
Work=Work+ Allocation
Finish=True
Go To 2
(4) 如所有的进程Finish[M]=true,则表示安全;否则系统不安全
三、主要算法设计及实现(主要代码)及运行情况说明(运行结果可截图)
本算法使用Python语言实现。
0.安装依赖
在控制台中输入pip install numpy,等待其安装完毕。
1.算法设计
(0) 构建allocation、need矩阵与available向量
使用numpy包中的array方法构建,向array方法传入一维或二维列表来构建。
(1) 判断request向量是否满足分配条件
使用numpy包中的all方法判断requset向量每一元素是否均不大于available向量和need矩阵上所对应的行向量。首先先进行各个元素的比较,若满足条件,则在这个位置上填True,否则填False,最终得到这样具有真假值的矩阵,再通过all方法与这个矩阵的每一个元素作and运算,得到最终比较结果(all方法中的axis参数确定轴,对于矩阵,axis=1代表列,axis=0代表行)。若结果为True,尝试分配资源;若结果为False,request向量不能满足分配条件,令该进程等待。
(2) 修改相关数据,尝试分配资源
修改need、allocation、available,初始化安全序列saftySeq为空,工作向量work、workPlusAllocation等于available。
(3) 执行安全性检查
使用saftySeq的长度作为安全性检查结束的主要判据,当saftySeq的长度小于进程总数时,除非无法满足进程的资源请求,否则继续进行资源分配。
如果该进程未结束(进程号不在saftySeq中,使用saftySeq来替代Finish),并且对应的need满足此时work向量(即上一状态的workPlusAllocation向量)的要求时,为该进程分配资源,添加到saftySeq中,输出相应信息并修改work与workPlusAllocation向量。
如果对于未结束的全部进程(数目大于0)均未能够满足work>=need条件,即在这一轮寻找结束前未找到,尝试分配失败,并将need、allocation、available恢复到之前的状态。
2.算法实现(仅展示banker方法)
3.运行情况说明
测试数据1:
测试数据2:
注释:下方的“request(n)”代表n号进程的请求向量。
(1)测试数据1 + request(1) = [1, 0, 2]
成功分配,并找到安全序列。
(2)测试数据1 + request(4) = [3, 3, 0]
无法为P4分配资源。
(3)测试数据1 + request(0) = [0, 2, 0]
无法为P0分配资源。
(4)测试数据1 + request(1) = [1, 0 ,2] + request(0) = [0, 2, 0]
无法为P0分配资源。
(5)测试数据1 + request(1) = [1, 0 ,2] + request(0) = [0, 1, 0]
成功分配。
(6)测试数据2 + request(1) = [0, 4, 2, 0]
成功分配。
(7)测试数据2 + request(4) = [0, 6, 2, 0]
无法分配。
四、代码
import numpy as np
allocation = np.array([[0, 1, 0], [2, 0, 0], [3, 0, 2], [2, 1, 1], [0, 0, 2]])
need = np.array([[7, 4, 3], [1, 2, 2], [6, 0, 0], [0, 1, 1], [4, 3, 1]])
available = np.array([3, 3, 2])
# allocation = np.array([[0, 0, 1, 2], [1, 0, 0, 0], [1, 3, 5, 4], [0, 6, 3, 2], [0, 0, 1, 4]])
# need = np.array([[0, 0, 0, 0], [0, 7, 5, 0], [1, 0, 0, 2], [0, 0, 2, 0], [0, 6, 4, 2]])
# available = np.array([1, 5, 2, 0])
def list_convert_nparray(arg):
return np.array(list(map(int, arg.split(','))))
# index starts from 0
def banker(index, request, allocation, need, available):
print(index, ' request:', request)
if np.all(request <= need[index, :], axis=0) and np.all(request <= available, axis=0):
saftySeq = []
available -= request
allocation[index, :] += request
need[index, :] -= request
work = workPlusAllocation = available
sumOfProcess = len(allocation) # len(allocation) equals the sum of processes
while len(saftySeq) < sumOfProcess:
for i in range(0, sumOfProcess):
cnt = 0
if len(saftySeq) == sumOfProcess:
break
if i not in saftySeq and np.all(need[i, :] <= workPlusAllocation, axis=0):
if len(saftySeq) != 0:
work = workPlusAllocation
workPlusAllocation = work + allocation[i, :]
saftySeq.append(i)
print('Process:', i, ' Work:', work, ' Need:', need[i], ' Allocation:', allocation[i],
' Work+Allocation:', workPlusAllocation)
cnt += 1
if i == sumOfProcess - 1 and cnt == 0:
available += request
allocation[index, :] -= request
need[index, :] += request
return False
print('Safty Sequence: ', saftySeq)
return True
else:
return False
if __name__ == '__main__':
while True:
print('Need:\n',need)
print('Allocation:\n',allocation)
print('Available:',available)
if banker(int(input("index:")), list_convert_nparray(input("request(split by ,):")), allocation, need, available):
print("Allocate Successfully")
else:
print('Can not Allocate')
print('-------------------------------')