银行家算法,以及安全检测算法:
import copy
# 银行家算法(资源分配合法性)
def BankersAlgorithm(Process_num, Resources_num, Request, Max, Available, Allocation, Need):
PID = Request['PID'] # 获取发起请求的进程ID
# Step1.如果该进程(PID)请求的RID类资源个数加上已经给它分配的RID类资源的个数小于等于该进程PID类资源最大需求量则转入Step2,否则报错,中断返回
for rId in range(1, Resources_num):
if Request['Request_num'][rId] + Allocation[PID][rId] > Max[PID][rId]:
print('Request resource overage!')
return # 请求非法,终止分配
# Step2.若PID进程请求RID类资源个数小于等于当前可分配的资源个数,则转向Step3.否则系统中RID类资源不能满足该PID进程PID的资源申请,将其阻塞
for rId in range(Resources_num):
if Request['Request_num'][rId] > Available[rId]:
print('Insufficient resources!')
return # 资源不足,终止分配,进入阻塞队列
# Step3.系统资源试分配
for rId in range(Resources_num):
Available[rId] = Available[rId] - Request['Request_num'][rId] # 更新系统剩余可用资源
Allocation[PID][rId] = Allocation[PID][rId] + Request['Request_num'][rId] # 更新各进程已分配资源
Need[PID][rId] = Need[PID][rId] - Request['Request_num'][rId] # 更新各进程资源需求
# 安全检查算法(资源分配合理性)
# 拿什么来检查就合理了?--如果该进程下一次请求其剩余所需的全部资源时,会不会发生资源不足的情况。
def security_check(Process_num, Resources_num, Request, Available, Allocation, Need):
# Step1 工作向量Work[1:m](m表示资源种数) 表示系统当前可供分配的各资源个数,执行算法开始时Work = Available
Work = copy.deepcopy(Available) # 重要!! copy.deepcopy() 深度拷贝,浅拷贝(具体原因不再深究)
# Step2 布尔型向量Finish[1:n] 表示是否有足够的资源分配给各进程,使之运行完成。开始时Finish[i] = false。
Finish = [False] * Process_num # 初始化所有进程的可执行状态
sequence = [] # 初始化安全序列(主要是方便后续存储)
# Step3.寻找安全进程为什么这里就单单加一个大循环就能找出符合要求的序列?--因为Available一直在增加
for _ in range(Process_num): # 重要!!! 每轮至少需要找出一个安全进程,至多Process_num轮可找出安全序列
for pID in range(Process_num): # 遍历进程
sign = 1 # 是否满足资源充足的标志位
if Finish[pID] == False:
for rId in range(Resources_num): # 遍历每种资源的需求量
if Need[pID][rId] > Work[rId]: # 需要的某类资源大系统当前拥有的资源时#标志位 置0
sign = 0
break # 放弃本轮对该进程的其它资源检查
if sign != 0: # sign != 0,表示该进程各资源需求可以满足
# 这里实际是需要给该进程分配资源,由于只是检查,再加之并发实际是串行,分配了执行完毕还得回收
# 所以没有进行:Available = Available - Need
# Availbale = Available + Need
for rId in range(Resources_num):
# 可以完成,并释放出分配给它的资源,故应该执行:
Work[rId] = Work[rId] + Allocation[pID][rId] # 将之前分配的资源回收
# 该进程若运行有足够的资源,故置Finish[i] = True
Finish[pID] = True
sequence.append(f'P{pID}') # 将改进程添加到安全序列中
# Step4 如果所有进程的Finish[i]== True,说明所有进程都已经出现在安全序列中,表明当前系统处于安全状态,只要有一个进程的Finish为false则当前系统处于不安全状态
if all(Finish):
return sequence # 返回该安全序列
else:
# 安全序列不存在,驳回银行家算法的分配操作(加回去)
PID = Request['PID']
for rId in range(Resources_num):
Available[rId] = Available[rId] - Request['Request_num'][rId] # 更新系统剩余可用资源
Allocation[PID][rId] = Allocation[PID][rId] + Request['Request_num'][rId] # 更新各进程已分配资源
Need[PID][rId] = Need[PID][rId] - Request['Request_num'][rId] # 更新各进程资源需求
return sequence # 照例返回,但这不是一个完整的安全序列,调用者需要判断
if __name__ == '__main__':
# 初始化:
Process_num = 3 # 并发进程个数
Resources_num = 3 # 系统资源种类个数
Resources_All = [8, 3, 6] # 各系统资源的总个数
# 进程资源申请矩阵
Request = {'PID': 0, 'Request_num': [1, 0, 0]} # Process_name:发出该请求的经进程PID,Request_num:请求的各类资源数量 安全
# 各进程已分配(持有)的资源数量矩阵
Allocation = [[0, 0, 0],
[4, 1, 2],
[1, 0, 1]]
# 进程需要的最大资源数量
Max = [[5, 3, 2],
[7, 3, 4],
[3, 0, 2]]
# 当前系统可分配资源矩阵(动态计算)
Available = []
for rId in range(Resources_num):
Allocation_sum = 0
for pId in range(Process_num):
Allocation_sum += Allocation[pId][rId]
Available.append(Resources_All[rId] - Allocation_sum)
# 各进程还需要的各资源数量矩阵(动态计算)
Need = []
for pId in range(Process_num):
need = []
for rId in range(Resources_num):
need.append(Max[pId][rId] - Allocation[pId][rId])
Need.append(need)
# 调用银行家算法
BankersAlgorithm(Process_num, Resources_num, Request, Max, Available, Allocation, Need)
sequence = security_check(Process_num, Resources_num, Request, Available, Allocation, Need)
# 检查得到的进程序列是否包含了全部进程,如果包含全部进程则是一个安全序列,否则不是安全序列
if len(sequence) == Process_num:
print(f'系统安全,允许分配请求。存在安全序列:{sequence}')
else:
print('不存在安全序列,系统不安全。驳回分配请求!!!')