银行家算法:Python模拟与实现
写在最前面
原文发布时间:2022/10/20 23:15:00
由于原文质量分过低,因此进行完善更新
主要补充:原代码进行分函数解读
原文
一、实验目的
1、 理解死锁产生的基本原理,以及死锁的必要条件;
2、 掌握死锁避免的基本原理与思路。
二、实验内容
试利用银行家算法对死锁避免算法进行模拟,确保系统在冬天申请资源的同时,永远不会陷入不安全状态。具体要求如下:
(1)程序中进程数量、资源种类数在程序运行时由用户输入;
(2)程序中的资源状态表结构根据输入的进程数量、资源种类数由程序动态生成;
(3)资源状态表中的数量既可以通过随机函数自动产生,也可以由用户手工输入;
(4)程序首先判断系统是否安全,然后在系统安全的前提下,由用户手动完成资源申请,其方法是:先输入或选择进程,然后输入该进程的资源申请要求;
(5)针对用户输入的资源申请,系统应视情况不同给出如下四种执行结果:
1)显示“资源申请不合理”;
2)显示“资源申请超过最大可用资源数,资源不够分配”;
3)显示“找不到安全序列,进程资源申请不予满足”;
4)先显示所找到的安全序列,进而告知用户资源已被分配,并同步修改资源状态表中相关数据。
三、实验要求
1、 写出程序,并调试程序,要给出测试数据和实验结果。
2、 整理上机步骤,总结经验和体会。
3、 完成实验报告和上交程序。
四、实验代码
结果展示
全部代码
import numpy as np
def get_data(types_of_resources, process_nums):
print(types_of_resources, process_nums)
Max = np.zeros((process_nums,types_of_resources))
Allocation = np.zeros((process_nums,types_of_resources))
Need = np.zeros((process_nums,types_of_resources))
Available = np.zeros(types_of_resources)
print("请输入当前可用的各资源数目: ",end=" ")
nums_cnt = input().split()
nums_cnt = [int(i) for i in nums_cnt]
for i in range(types_of_resources):
Available[i]=nums_cnt[i]
for i in range(process_nums):
print(f"请输入P{i}的需要的最大资源数目:",end=" ")
nums_cnt = input().split()
nums_cnt = [int(i) for i in nums_cnt]
for j in range(types_of_resources):
Max[i][j] = nums_cnt[j]
for i in range(process_nums):
print(f"请输入P{i}已经分配的资源数目:", end=" ")
nums_cnt = input().split()
nums_cnt = [int(i) for i in nums_cnt]
for j in range(types_of_resources):
Allocation[i][j] = nums_cnt[j]
# 求取Need矩阵
for i in range(process_nums):
for j in range(types_of_resources):
Need[i][j] = Max[i][j] - Allocation[i][j]
draw_resource_map(Max, Allocation, Need, Available,types_of_resources, process_nums)
return Max, Allocation, Need, Available
def draw_resource_map(Max,Allocation,Need,Available,types_of_resources, process_nums):
kg_num = int(types_of_resources/2)+1
print("|---"+'-'*kg_num+"进程"+"--"+"最大需求"+"--"*kg_num+"已占有资源数目"+"--"*kg_num+"最多还需要分配"+"--"*kg_num+"各资源剩余数目"+"--|")
for i in range(process_nums):
print("| "*kg_num+"P"+str(i)+" "*kg_num+str(list(Max[i]))+" "*kg_num+str(list(Allocation[i]))+" "*kg_num+str(list(Need[i]))+str(list(Available))+" |")
return None
def main_banker_algorithm(Max, Allocation, Need, Available,types_of_resources, process_nums):
process_sequence = input("请输入请求分配的进程的序号(从0开始):")
process_sequence = int(process_sequence)
# 请求各个资源的数目
Requests = np.zeros(types_of_resources)
print("请输入请求的各个资源的数目:",end=" ")
nums_cnt = input().split()
nums_cnt = [int(i) for i in nums_cnt]
for j in range(types_of_resources):
Requests[j] = nums_cnt[j]
# 判断申请是否超过之前声明的最大需求出
# 检查此时系统剩余的可用资源是否满足这次请求
flag,Need_cnt,Allocation_cnt,Available_cnt = is_initial_conditions(Need,Allocation,Available,Requests,process_sequence,types_of_resources)
if not flag:
print("main~无法找到安全序列")
else:
# 先试着分配,看效果
analog_distribution(Max,Need_cnt,Allocation_cnt,Available_cnt,types_of_resources, process_nums)
return None
def is_initial_conditions(Need,Allocation,Available,Requests,process_sequence,types_of_resources):
Need_cnt = Need
Available_cnt = Available
Allocation_cnt = Allocation
for i in range(types_of_resources):
# 判断申请是否超过之前声明的最大需求出
if Requests[i] > Need[process_sequence][i]:
print("申请超过之前声明的最大需求")
return False
else:
Need_cnt[process_sequence][i]-=Requests[i]
# 检查此时系统剩余的可用资源是否满足这次请求
if Requests[i]>Available[i]:
print("此时系统剩余的可用资源不能满足这次请求")
return False
else:
Available_cnt[i]-=Requests[i]
Allocation_cnt[process_sequence][i]+=Requests[i]
return True,Need_cnt,Allocation_cnt,Available_cnt
def analog_distribution(Max,Need_cnt,Allocation_cnt,Available_cnt,types_of_resources, process_nums):
# 先找出满足现在当前序列的排在第一个进程
the_first_process = []
for i in range(process_nums):
flag = 0
for j in range(types_of_resources):
if (Available_cnt[j]>=Need_cnt[i][j]):
flag+=1
if(flag==types_of_resources):
the_first_process.append(i)
if len(the_first_process)==0:
print("没有找到安全序列")
else:
for rank in the_first_process:
Need, Allocation, Available = Need_cnt,Allocation_cnt,Available_cnt
# 记录进程是否执行完毕
process_over = [0]*process_nums
other = [i for i in range(process_nums) if i!=rank]
# 例子,剩下的三种,一共有6种排序方法,这里使用暴力大法(其实这里可以改善,不过没想到好的方法,嘻嘻)
# 应该是n!个方法
# 如果强行使用n!的暴力方法的话,我感觉是绕园路了,试下走一步弄一部吧
# 满足该进程后,彻底回收该进程使用的资源
for i in range(types_of_resources):
Available[i]+=Allocation[rank][i]
# 该进程执行完毕
process_over[rank] += 1
# 当前路径下的名称
road_name=[]
road_name.append(rank)
# 根据后面的序列判断是否存在合理的程序
isRight=True
# 用递归的方式查找对应的序列
look_for_reods(Need, Allocation, Available,process_over,len(other),road_name,isRight,types_of_resources, process_nums)
road_name.pop(-1)
process_over[rank] -= 1
for i in range(types_of_resources):
Available[i] -= Allocation[rank][i]
def look_for_reods(Need, Allocation, Available,process_over,geshu,road_name,isRight,types_of_resources, process_nums):
if isRight:
isRight_cnt=isRight
geshu_cnt = geshu
# 先找出满足现在当前序列的排在第一个进程
the_first_process = []
for i in range(process_nums):
if process_over[i]==0:
flag = 0
for j in range(types_of_resources):
if (Available[j] >= Need[i][j]):
flag += 1
if (flag == types_of_resources):
the_first_process.append(i)
if len(the_first_process) == 0 and len(road_name)!=process_nums:
print(str(list(road_name))+"没有找到安全序列")
isRight_cnt=False
for rank in the_first_process:
Need_cnt, Allocation_cnt, Available_cnt = Need.copy(), Allocation.copy(), Available.copy()
# 满足该进程后,彻底回收该进程使用的资源
for i in range(types_of_resources):
Available_cnt[i] += Allocation[rank][i]
# 该进程执行完毕
process_over[rank] += 1
road_name.append(rank)
geshu_cnt=geshu-1
if(geshu_cnt==0):
print("安全序列为:",end=" ")
print(road_name)
if isRight_cnt:
look_for_reods(Need_cnt, Allocation_cnt, Available_cnt, process_over, geshu_cnt, road_name, isRight_cnt,types_of_resources, process_nums)
road_name.pop(-1)
process_over[rank]-=1
def main():
types_of_resources , process_nums = input("请输入资源种类和进程数目:").split(" ")
types_of_resources, process_nums = int(types_of_resources) , int(process_nums)
Max, Allocation, Need, Available = get_data(types_of_resources, process_nums)
while True:
main_banker_algorithm(Max, Allocation, Need, Available,types_of_resources, process_nums)
return None
if __name__ == '__main__':
main()
完善
利用银行家算法进行死锁避免算法的模拟
在计算机科学领域,死锁是一种常见的问题,它可以发生在多个进程或线程之间,当它们相互等待资源时会导致系统陷入无法前进的状态。为了解决这个问题,我们可以使用银行家算法,一种死锁避免算法,它通过合理分配资源来确保系统永远不会陷入不安全状态。本文将介绍如何模拟银行家算法,以确保系统在申请资源时不会陷入死锁。
银行家算法简介
银行家算法是一种用于管理资源分配的算法,最初由艾兹格·迪杰克斯特拉(Edsger W. Dijkstra)提出。它的核心思想是在分配资源之前检查系统的状态,以确保分配资源后系统不会陷入不安全状态,从而避免死锁的发生。
银行家算法的基本概念如下:
- 每个进程声明它最多可能需要的每种资源的数量,这称为"最大需求"。
- 每个进程声明它当前已经分配的资源的数量,这称为"已分配资源"。
- 系统维护一个可用资源向量,表示当前系统可用的每种资源的数量。
- 当一个进程请求资源时,系统会检查分配资源后系统是否仍然处于安全状态,如果是,就分配资源;如果不是,就等待。
模拟银行家算法
以下是对上述Python代码的详细分段分析:
导入库
import numpy as np
这段代码导入了NumPy库,用于处理多维数组和执行数学运算。NumPy是用于科学计算的重要库。
获取数据函数
def get_data(types_of_resources, process_nums):
这个函数用于获取用户输入的资源和进程数量,以及相关的信息(最大需求、已分配资源、需求资源)。它创建了名为 Max
、Allocation
、Need
和 Available
的矩阵,用于存储相关数据。
def get_data(types_of_resources, process_nums):
print(types_of_resources, process_nums)
Max = np.zeros((process_nums,types_of_resources))
Allocation = np.zeros((process_nums,types_of_resources))
Need = np.zeros((process_nums,types_of_resources))
Available = np.zeros(types_of_resources)
print("请输入当前可用的各资源数目: ",end=" ")
nums_cnt = input().split()
nums_cnt = [int(i) for i in nums_cnt]
for i in range(types_of_resources):
Available[i]=nums_cnt[i]
for i in range(process_nums):
print(f"请输入P{i}的需要的最大资源数目:",end=" ")
nums_cnt = input().split()
nums_cnt = [int(i) for i in nums_cnt]
for j in range(types_of_resources):
Max[i][j] = nums_cnt[j]
for i in range(process_nums):
print(f"请输入P{i}已经分配的资源数目:", end=" ")
nums_cnt = input().split()
nums_cnt = [int(i) for i in nums_cnt]
for j in range(types_of_resources):
Allocation[i][j] = nums_cnt[j]
# 求取Need矩阵
for i in range(process_nums):
for j in range(types_of_resources):
Need[i][j] = Max[i][j] - Allocation[i][j]
draw_resource_map(Max, Allocation, Need, Available,types_of_resources, process_nums)
return Max, Allocation, Need, Available
以下是对函数中各部分的详细解释:
-
types_of_resources
和process_nums
是函数的两个参数,分别表示资源的种类数量和进程的数量。这些参数将在后续操作中用于创建相应大小的矩阵。 -
函数开始时,创建了四个NumPy数组:
Max
、Allocation
、Need
和Available
,分别用于存储最大资源需求、已分配资源、需求资源和可用资源。 -
用户被要求输入当前可用的各种资源数量,这些资源的数量由用户以空格分隔的方式输入,并在函数中存储在
Available
数组中。 -
然后,用户需要逐个输入每个进程的最大资源需求,这些数据存储在
Max
数组中。 -
接下来,用户需要输入每个进程已分配的资源数量,这些数据存储在
Allocation
数组中。 -
使用输入的数据,函数计算了Need矩阵,表示每个进程还需要多少资源才能完成。
-
最后,函数调用了
draw_resource_map
函数,以绘制资源分配图,这是一个在函数中没有详细展示的子函数。
总的来说,这个函数用于收集关于资源分配的数据,包括资源的种类、进程的数量、最大资源需求、已分配资源数量和可用资源数量。
输出资源分配矩阵
def draw_resource_map(Max, Allocation, Need, Available, types_of_resources, process_nums):
这个函数用于在控制台上输出资源分配矩阵,以便用户能够清晰地看到资源的状态。
def draw_resource_map(Max,Allocation,Need,Available,types_of_resources, process_nums):
kg_num = int(types_of_resources/2)+1
print("|---"+'-'*kg_num+"进程"+"--"+"最大需求"+"--"*kg_num+"已占有资源数目"+"--"*kg_num+"最多还需要分配"+"--"*kg_num+"各资源剩余数目"+"--|")
for i in range(process_nums):
print("| "*kg_num+"P"+str(i)+" "*kg_num+str(list(Max[i]))+" "*kg_num+str(list(Allocation[i]))+" "*kg_num+str(list(Need[i]))+str(list(Available))+" |")
return None
以下是对函数中各部分的详细解释:
-
draw_resource_map
函数接受多个参数,包括Max
、Allocation
、Need
、Available
、types_of_resources
和process_nums
。这些参数包含了资源分配的关键信息,包括最大资源需求、已分配资源、需求资源和可用资源。 -
首先,函数计算了一个变量
kg_num
,它表示了资源种类数量的一半加一。这个值用于控制输出表格中的格式,以使其更具可读性。 -
接下来,函数打印了一行分隔线,包含了表格的表头,表头包括"进程"、“最大需求”、“已占有资源数目”、"最多还需要分配"和"各资源剩余数目"等信息,通过分隔线进行分隔。
-
使用循环迭代每个进程(从0到
process_nums-1
),函数以表格的形式打印了每个进程的相关信息,包括进程编号(如P0、P1等)、最大需求资源、已占有资源、最多还需要分配的资源和各资源的剩余数目。这些信息以表格的形式呈现,以帮助用户更好地理解资源分配情况。 -
最后,函数返回
None
,因为它的主要目的是打印信息并可视化资源分配情况,而不是返回数据。
总的来说,这个函数用于在命令行或控制台中绘制一个资源分配图,以帮助用户清晰地了解每个进程的资源需求和分配情况。
主银行家算法函数
def main_banker_algorithm(Max, Allocation, Need, Available, types_of_resources, process_nums):
这是主要的银行家算法逻辑。用户将输入请求的进程和资源,然后检查请求的有效性。如果请求有效,将模拟资源分配,否则会显示错误消息。
def main_banker_algorithm(Max, Allocation, Need, Available,types_of_resources, process_nums):
process_sequence = input("请输入请求分配的进程的序号(从0开始):")
process_sequence = int(process_sequence)
# 请求各个资源的数目
Requests = np.zeros(types_of_resources)
print("请输入请求的各个资源的数目:",end=" ")
nums_cnt = input().split()
nums_cnt = [int(i) for i in nums_cnt]
for j in range(types_of_resources):
Requests[j] = nums_cnt[j]
# 判断申请是否超过之前声明的最大需求出
# 检查此时系统剩余的可用资源是否满足这次请求
flag,Need_cnt,Allocation_cnt,Available_cnt = is_initial_conditions(Need,Allocation,Available,Requests,process_sequence,types_of_resources)
if not flag:
print("main~无法找到安全序列")
else:
# 先试着分配,看效果
analog_distribution(Max,Need_cnt,Allocation_cnt,Available_cnt,types_of_resources, process_nums)
return None
以下是对函数中各部分的详细解释:
-
main_banker_algorithm
函数接受多个参数,包括Max
、Allocation
、Need
、Available
、types_of_resources
和process_nums
。这些参数包含了资源分配的关键信息,包括最大资源需求、已分配资源、需求资源和可用资源,以及资源的种类数量和进程的数量。 -
函数首先要求用户输入请求分配的进程序号(从0开始),并将其存储在变量
process_sequence
中。 -
然后,用户需要输入请求的各个资源的数目,这些数据存储在
Requests
数组中。用户输入的数据通过输入以空格分隔的方式获取,并在函数中存储为整数。 -
接下来,函数调用了
is_initial_conditions
函数,以检查请求是否超出最大需求,并且检查系统剩余的可用资源是否满足这次请求。如果请求合法且满足条件,flag
将设置为True
,否则为False
。 -
如果
flag
为False
,表示无法找到安全序列,函数打印相应的提示信息。如果flag
为True
,表示请求合法,函数调用了analog_distribution
函数,以模拟分配资源并查看效果。 -
最后,函数返回
None
,因为它的主要目的是处理资源请求和模拟分配,而不是返回数据。
总的来说,这个函数实现了银行家算法的核心逻辑,用于判断资源请求是否合法,以及模拟资源分配的效果。
检查请求的有效性
def is_initial_conditions(Need, Allocation, Available, Requests, process_sequence, types_of_resources):
这个函数用于检查请求是否有效。它检查请求是否超过了之前声明的最大需求,并检查系统是否有足够的可用资源满足请求。
def is_initial_conditions(Need,Allocation,Available,Requests,process_sequence,types_of_resources):
Need_cnt = Need
Available_cnt = Available
Allocation_cnt = Allocation
for i in range(types_of_resources):
# 判断申请是否超过之前声明的最大需求出
if Requests[i] > Need[process_sequence][i]:
print("申请超过之前声明的最大需求")
return False
else:
Need_cnt[process_sequence][i]-=Requests[i]
# 检查此时系统剩余的可用资源是否满足这次请求
if Requests[i]>Available[i]:
print("此时系统剩余的可用资源不能满足这次请求")
return False
else:
Available_cnt[i]-=Requests[i]
Allocation_cnt[process_sequence][i]+=Requests[i]
return True,Need_cnt,Allocation_cnt,Available_cnt
以下是对函数中各部分的详细解释:
-
is_initial_conditions
函数接受多个参数,包括Need
、Allocation
、Available
、Requests
、process_sequence
、types_of_resources
。这些参数包含了资源分配的关键信息,包括需求资源、已分配资源、可用资源、请求资源、进程号以及资源的种类数量。 -
函数首先创建了三个新的变量:
Need_cnt
、Available_cnt
、Allocation_cnt
,它们用于存储在检查过程中的临时值,并初始化为与输入参数相同的值。这是因为在检查中,函数需要修改这些值以反映分配资源的效果。 -
然后,函数使用循环迭代每个资源类型(从0到
types_of_resources-1
),执行以下检查:- 检查请求的资源数量是否超过了之前声明的最大需求。如果请求超出最大需求,函数将返回
False
,并打印相应的提示信息。 - 检查此时系统剩余的可用资源是否足够满足这次请求。如果可用资源不足,函数将返回
False
,并打印相应的提示信息。 - 如果请求合法,函数将更新
Need_cnt
、Available_cnt
和Allocation_cnt
,以反映资源的分配和更新状态。
- 检查请求的资源数量是否超过了之前声明的最大需求。如果请求超出最大需求,函数将返回
-
如果所有的资源请求都合法且满足条件,函数将返回
True
以及更新后的Need_cnt
、Allocation_cnt
和Available_cnt
,表示资源请求可以满足初始条件。
总的来说,这个函数用于检查资源请求是否满足初始条件,包括请求是否超出最大需求和是否可用资源足够。这是银行家算法中的关键步骤,用于确保资源分配的安全性。
模拟资源分配
def analog_distribution(Max, Need_cnt, Allocation_cnt, Available_cnt, types_of_resources, process_nums):
这个函数模拟资源的分配和回收过程。首先找到可以满足当前序列的进程,并尝试模拟资源分配。如果找不到满足的进程,会显示错误消息。
def analog_distribution(Max,Need_cnt,Allocation_cnt,Available_cnt,types_of_resources, process_nums):
# 先找出满足现在当前序列的排在第一个进程
the_first_process = []
for i in range(process_nums):
flag = 0
for j in range(types_of_resources):
if (Available_cnt[j]>=Need_cnt[i][j]):
flag+=1
if(flag==types_of_resources):
the_first_process.append(i)
if len(the_first_process)==0:
print("没有找到安全序列")
else:
for rank in the_first_process:
Need, Allocation, Available = Need_cnt,Allocation_cnt,Available_cnt
# 记录进程是否执行完毕
process_over = [0]*process_nums
other = [i for i in range(process_nums) if i!=rank]
# 例子,剩下的三种,一共有6种排序方法,这里使用暴力大法(其实这里可以改善,不过没想到好的方法,嘻嘻)
# 应该是n!个方法
# 如果强行使用n!的暴力方法的话,我感觉是绕园路了,试下走一步弄一部吧
# 满足该进程后,彻底回收该进程使用的资源
for i in range(types_of_resources):
Available[i]+=Allocation[rank][i]
# 该进程执行完毕
process_over[rank] += 1
# 当前路径下的名称
road_name=[]
road_name.append(rank)
# 根据后面的序列判断是否存在合理的程序
isRight=True
# 用递归的方式查找对应的序列
look_for_reods(Need, Allocation, Available,process_over,len(other),road_name,isRight,types_of_resources, process_nums)
road_name.pop(-1)
process_over[rank] -= 1
for i in range(types_of_resources):
Available[i] -= Allocation[rank][i]
以下是对函数中各部分的详细解释:
-
analog_distribution
函数接受多个参数,包括Max
、Need_cnt
、Allocation_cnt
、Available_cnt
、types_of_resources
和process_nums
。这些参数包含了资源分配的关键信息,包括最大需求、需求、已分配和可用资源的状态,以及资源的种类数量和进程的数量。 -
首先,函数找出满足当前资源状态的排在第一个进程,并将它们存储在
the_first_process
列表中。这是通过检查每个进程的需求是否小于等于可用资源来实现的。 -
如果没有找到满足当前状态的进程,函数打印相应的提示信息,表示没有找到安全序列。否则,函数进入下一步。
-
对于每个满足条件的进程,函数进入一个循环,并执行以下操作:
- 复制当前的
Need_cnt
、Allocation_cnt
、Available_cnt
到新的Need
、Allocation
、Available
变量,以便在模拟中修改。 - 创建一个
process_over
列表,用于记录进程是否执行完毕,初始化为0。 - 创建一个
other
列表,用于存储除当前进程之外的其他进程的索引。 - 初始化一个
road_name
列表,用于存储当前路径下的进程顺序。 - 初始化一个
isRight
变量,用于表示当前路径是否是合理的序列。
- 复制当前的
-
然后,函数开始模拟分配资源。它首先回收当前进程已使用的资源,将已分配的资源添加回可用资源中。然后,标记当前进程为执行完毕。
-
接下来,函数使用递归的方式查找对应的序列。在递归查找中,函数检查下一个进程是否可以执行,如果可以执行,则将其添加到路径中,并继续查找下一个进程。如果在某个路径下找到合理的序列,
isRight
将设置为True
。 -
最后,函数回溯到上一级进程,恢复资源状态,并继续查找其他路径。如果找到一个路径中的合理序列,函数将打印相应的提示信息。
总的来说,这个函数用于模拟资源分配,并查找安全序列,以确保资源分配的安全性。这在操作系统中的资源管理和并发编程中非常有用。
查找安全序列
def look_for_reods(Need, Allocation, Available, process_over, geshu, road_name, isRight, types_of_resources, process_nums):
这个函数是银行家算法的核心。它通过递归方式查找可能的安全序列,以满足进程的资源需求。这一部分是银行家算法的实现关键。
def look_for_reods(Need, Allocation, Available,process_over,geshu,road_name,isRight,types_of_resources, process_nums):
if isRight:
isRight_cnt=isRight
geshu_cnt = geshu
# 先找出满足现在当前序列的排在第一个进程
the_first_process = []
for i in range(process_nums):
if process_over[i]==0:
flag = 0
for j in range(types_of_resources):
if (Available[j] >= Need[i][j]):
flag += 1
if (flag == types_of_resources):
the_first_process.append(i)
if len(the_first_process) == 0 and len(road_name)!=process_nums:
print(str(list(road_name))+"没有找到安全序列")
isRight_cnt=False
for rank in the_first_process:
Need_cnt, Allocation_cnt, Available_cnt = Need.copy(), Allocation.copy(), Available.copy()
# 满足该进程后,彻底回收该进程使用的资源
for i in range(types_of_resources):
Available_cnt[i] += Allocation[rank][i]
# 该进程执行完毕
process_over[rank] += 1
road_name.append(rank)
geshu_cnt=geshu-1
if(geshu_cnt==0):
print("安全序列为:",end=" ")
print(road_name)
if isRight_cnt:
look_for_reods(Need_cnt, Allocation_cnt, Available_cnt, process_over, geshu_cnt, road_name, isRight_cnt,types_of_resources, process_nums)
road_name.pop(-1)
process_over[rank]-=1
这是一个递归函数,用于查找满足银行家算法的安全序列。以下是对函数中各部分的详细解释:
-
look_for_reods
函数接受多个参数,包括Need
、Allocation
、Available
、process_over
、geshu
、road_name
、isRight
、types_of_resources
和process_nums
。这些参数包含了资源分配的关键信息,以及资源的种类数量、进程的数量以及查找过程中的状态信息。 -
首先,函数检查
isRight
变量是否为True
,如果是,表示当前路径是合理的,可以继续查找。然后,创建两新的变量isRight_cnt
和geshu_cnt
,分别初始化为isRight
和geshu
,用于在递归中传递状态信息。 -
接着,函数找出满足当前资源状态的排在第一个进程,并将它们存储在
the_first_process
列表中。这是通过检查每个进程的需求是否小于等于可用资源来实现的。 -
如果没有找到满足当前状态的进程,且路径不包含所有进程(即
len(road_name)
不等于process_nums
),函数打印当前路径和相应的提示信息,表示没有找到安全序列,并将isRight_cnt
设置为False
。 -
对于每个满足条件的进程,函数进入一个循环,并执行以下操作:
- 复制当前的
Need
、Allocation
、Available
到新的Need_cnt
、Allocation_cnt
、Available_cnt
变量,以便在模拟中修改。 - 回收当前进程已使用的资源,将已分配的资源添加回可用资源中,标记当前进程为执行完毕,将当前进程添加到路径中,减少待查找的进程数量
geshu_cnt
。
- 复制当前的
-
如果
geshu_cnt
等于0,表示已找到一个安全序列,函数打印安全序列。 -
如果
isRight_cnt
仍为True
,函数继续查找下一个进程。这是通过递归调用look_for_reods
函数来实现的,传递更新后的Need_cnt
、Allocation_cnt
、Available_cnt
、process_over
、geshu_cnt
和road_name
。然后,函数回溯到上一级进程,移除已添加的进程,恢复资源状态,并继续查找其他路径。
总的来说,这个函数用于递归查找满足银行家算法的安全序列,以确保资源分配的安全性。它会遍历所有可能的序列,并找到合理的安全序列。
主函数
def main():
这是程序的主函数。它获取用户输入的资源和进程数量,初始化资源矩阵,然后进入一个无限循环,允许用户不断输入资源请求并模拟资源分配。
def main():
types_of_resources , process_nums = input("请输入资源种类和进程数目:").split(" ")
types_of_resources, process_nums = int(types_of_resources) , int(process_nums)
Max, Allocation, Need, Available = get_data(types_of_resources, process_nums)
while True:
main_banker_algorithm(Max, Allocation, Need, Available,types_of_resources, process_nums)
return None
这是一个主函数main()
,它用于启动整个银行家算法的模拟。以下是对函数的详细解释:
-
首先,函数通过用户输入获取资源的种类数量和进程的数量。用户需要输入一个空格分隔的字符串,其中第一个数字表示资源种类数量,第二个数字表示进程数量。这些输入信息存储在
types_of_resources
和process_nums
变量中。 -
接下来,函数调用
get_data()
函数来获取资源分配的初始数据,包括Max
(最大需求矩阵)、Allocation
(已分配矩阵)、Need
(需求矩阵)和Available
(可用资源向量)。这些数据将在模拟过程中用于银行家算法的执行。 -
进入一个无限循环
while True
,在循环中不断执行银行家算法的模拟。 -
在每次循环迭代中,函数调用
main_banker_algorithm()
函数,传递初始数据和资源的种类数量、进程数量。 -
main_banker_algorithm()
函数用于模拟银行家算法的执行,包括用户输入请求、检查请求的合法性、尝试分配资源,以及查找安全序列。如果成功找到安全序列,就会执行资源分配;否则,算法将等待下一个请求的输入。 -
整个循环会不断迭代,允许用户模拟多次资源请求和分配的过程。
总的来说,main()
函数是银行家算法模拟的入口点,用户可以通过输入资源种类数量和进程数量,然后在循环中模拟资源请求和分配的过程,以验证算法的正确性和安全性。
主程序入口
if __name__ == '__main__':
这一行确保主程序在直接运行时才执行。
这个程序是一个简单的银行家算法模拟器,用于学习和理解银行家算法的工作原理。用户可以输入资源和进程的数据,然后模拟资源的申请和分配过程,以及查找安全序列。