• 操作系统实验三:死锁避免程序设计


    写在最前面

    原文发布时间: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()
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187

    完善

    利用银行家算法进行死锁避免算法的模拟

    在计算机科学领域,死锁是一种常见的问题,它可以发生在多个进程或线程之间,当它们相互等待资源时会导致系统陷入无法前进的状态。为了解决这个问题,我们可以使用银行家算法,一种死锁避免算法,它通过合理分配资源来确保系统永远不会陷入不安全状态。本文将介绍如何模拟银行家算法,以确保系统在申请资源时不会陷入死锁。

    银行家算法简介

    银行家算法是一种用于管理资源分配的算法,最初由艾兹格·迪杰克斯特拉(Edsger W. Dijkstra)提出。它的核心思想是在分配资源之前检查系统的状态,以确保分配资源后系统不会陷入不安全状态,从而避免死锁的发生。

    银行家算法的基本概念如下:

    • 每个进程声明它最多可能需要的每种资源的数量,这称为"最大需求"。
    • 每个进程声明它当前已经分配的资源的数量,这称为"已分配资源"。
    • 系统维护一个可用资源向量,表示当前系统可用的每种资源的数量。
    • 当一个进程请求资源时,系统会检查分配资源后系统是否仍然处于安全状态,如果是,就分配资源;如果不是,就等待。

    模拟银行家算法

    以下是对上述Python代码的详细分段分析:

    导入库

    import numpy as np
    
    • 1

    这段代码导入了NumPy库,用于处理多维数组和执行数学运算。NumPy是用于科学计算的重要库。

    获取数据函数

    def get_data(types_of_resources, process_nums):
    
    • 1

    这个函数用于获取用户输入的资源和进程数量,以及相关的信息(最大需求、已分配资源、需求资源)。它创建了名为 MaxAllocationNeedAvailable 的矩阵,用于存储相关数据。

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    以下是对函数中各部分的详细解释:

    1. types_of_resourcesprocess_nums是函数的两个参数,分别表示资源的种类数量和进程的数量。这些参数将在后续操作中用于创建相应大小的矩阵。

    2. 函数开始时,创建了四个NumPy数组:MaxAllocationNeedAvailable,分别用于存储最大资源需求、已分配资源、需求资源和可用资源。

    3. 用户被要求输入当前可用的各种资源数量,这些资源的数量由用户以空格分隔的方式输入,并在函数中存储在Available数组中。

    4. 然后,用户需要逐个输入每个进程的最大资源需求,这些数据存储在Max数组中。

    5. 接下来,用户需要输入每个进程已分配的资源数量,这些数据存储在Allocation数组中。

    6. 使用输入的数据,函数计算了Need矩阵,表示每个进程还需要多少资源才能完成。

    7. 最后,函数调用了draw_resource_map函数,以绘制资源分配图,这是一个在函数中没有详细展示的子函数。

    总的来说,这个函数用于收集关于资源分配的数据,包括资源的种类、进程的数量、最大资源需求、已分配资源数量和可用资源数量。

    输出资源分配矩阵

    def draw_resource_map(Max, Allocation, Need, Available, types_of_resources, process_nums):
    
    • 1

    这个函数用于在控制台上输出资源分配矩阵,以便用户能够清晰地看到资源的状态。

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    以下是对函数中各部分的详细解释:

    1. draw_resource_map函数接受多个参数,包括MaxAllocationNeedAvailabletypes_of_resourcesprocess_nums。这些参数包含了资源分配的关键信息,包括最大资源需求、已分配资源、需求资源和可用资源。

    2. 首先,函数计算了一个变量kg_num,它表示了资源种类数量的一半加一。这个值用于控制输出表格中的格式,以使其更具可读性。

    3. 接下来,函数打印了一行分隔线,包含了表格的表头,表头包括"进程"、“最大需求”、“已占有资源数目”、"最多还需要分配"和"各资源剩余数目"等信息,通过分隔线进行分隔。

    4. 使用循环迭代每个进程(从0到process_nums-1),函数以表格的形式打印了每个进程的相关信息,包括进程编号(如P0、P1等)、最大需求资源、已占有资源、最多还需要分配的资源和各资源的剩余数目。这些信息以表格的形式呈现,以帮助用户更好地理解资源分配情况。

    5. 最后,函数返回None,因为它的主要目的是打印信息并可视化资源分配情况,而不是返回数据。

    总的来说,这个函数用于在命令行或控制台中绘制一个资源分配图,以帮助用户清晰地了解每个进程的资源需求和分配情况。

    主银行家算法函数

    def main_banker_algorithm(Max, Allocation, Need, Available, types_of_resources, process_nums):
    
    • 1

    这是主要的银行家算法逻辑。用户将输入请求的进程和资源,然后检查请求的有效性。如果请求有效,将模拟资源分配,否则会显示错误消息。

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    以下是对函数中各部分的详细解释:

    1. main_banker_algorithm函数接受多个参数,包括MaxAllocationNeedAvailabletypes_of_resourcesprocess_nums。这些参数包含了资源分配的关键信息,包括最大资源需求、已分配资源、需求资源和可用资源,以及资源的种类数量和进程的数量。

    2. 函数首先要求用户输入请求分配的进程序号(从0开始),并将其存储在变量process_sequence中。

    3. 然后,用户需要输入请求的各个资源的数目,这些数据存储在Requests数组中。用户输入的数据通过输入以空格分隔的方式获取,并在函数中存储为整数。

    4. 接下来,函数调用了is_initial_conditions函数,以检查请求是否超出最大需求,并且检查系统剩余的可用资源是否满足这次请求。如果请求合法且满足条件,flag将设置为True,否则为False

    5. 如果flagFalse,表示无法找到安全序列,函数打印相应的提示信息。如果flagTrue,表示请求合法,函数调用了analog_distribution函数,以模拟分配资源并查看效果。

    6. 最后,函数返回None,因为它的主要目的是处理资源请求和模拟分配,而不是返回数据。

    总的来说,这个函数实现了银行家算法的核心逻辑,用于判断资源请求是否合法,以及模拟资源分配的效果。

    检查请求的有效性

    def is_initial_conditions(Need, Allocation, Available, Requests, process_sequence, types_of_resources):
    
    • 1

    这个函数用于检查请求是否有效。它检查请求是否超过了之前声明的最大需求,并检查系统是否有足够的可用资源满足请求。

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    以下是对函数中各部分的详细解释:

    1. is_initial_conditions函数接受多个参数,包括NeedAllocationAvailableRequestsprocess_sequencetypes_of_resources。这些参数包含了资源分配的关键信息,包括需求资源、已分配资源、可用资源、请求资源、进程号以及资源的种类数量。

    2. 函数首先创建了三个新的变量:Need_cntAvailable_cntAllocation_cnt,它们用于存储在检查过程中的临时值,并初始化为与输入参数相同的值。这是因为在检查中,函数需要修改这些值以反映分配资源的效果。

    3. 然后,函数使用循环迭代每个资源类型(从0到types_of_resources-1),执行以下检查:

      • 检查请求的资源数量是否超过了之前声明的最大需求。如果请求超出最大需求,函数将返回False,并打印相应的提示信息。
      • 检查此时系统剩余的可用资源是否足够满足这次请求。如果可用资源不足,函数将返回False,并打印相应的提示信息。
      • 如果请求合法,函数将更新Need_cntAvailable_cntAllocation_cnt,以反映资源的分配和更新状态。
    4. 如果所有的资源请求都合法且满足条件,函数将返回True以及更新后的Need_cntAllocation_cntAvailable_cnt,表示资源请求可以满足初始条件。

    总的来说,这个函数用于检查资源请求是否满足初始条件,包括请求是否超出最大需求和是否可用资源足够。这是银行家算法中的关键步骤,用于确保资源分配的安全性。

    模拟资源分配

    def analog_distribution(Max, Need_cnt, Allocation_cnt, Available_cnt, types_of_resources, process_nums):
    
    • 1

    这个函数模拟资源的分配和回收过程。首先找到可以满足当前序列的进程,并尝试模拟资源分配。如果找不到满足的进程,会显示错误消息。

    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]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    以下是对函数中各部分的详细解释:

    1. analog_distribution函数接受多个参数,包括MaxNeed_cntAllocation_cntAvailable_cnttypes_of_resourcesprocess_nums。这些参数包含了资源分配的关键信息,包括最大需求、需求、已分配和可用资源的状态,以及资源的种类数量和进程的数量。

    2. 首先,函数找出满足当前资源状态的排在第一个进程,并将它们存储在the_first_process列表中。这是通过检查每个进程的需求是否小于等于可用资源来实现的。

    3. 如果没有找到满足当前状态的进程,函数打印相应的提示信息,表示没有找到安全序列。否则,函数进入下一步。

    4. 对于每个满足条件的进程,函数进入一个循环,并执行以下操作:

      • 复制当前的Need_cntAllocation_cntAvailable_cnt到新的NeedAllocationAvailable变量,以便在模拟中修改。
      • 创建一个process_over列表,用于记录进程是否执行完毕,初始化为0。
      • 创建一个other列表,用于存储除当前进程之外的其他进程的索引。
      • 初始化一个road_name列表,用于存储当前路径下的进程顺序。
      • 初始化一个isRight变量,用于表示当前路径是否是合理的序列。
    5. 然后,函数开始模拟分配资源。它首先回收当前进程已使用的资源,将已分配的资源添加回可用资源中。然后,标记当前进程为执行完毕。

    6. 接下来,函数使用递归的方式查找对应的序列。在递归查找中,函数检查下一个进程是否可以执行,如果可以执行,则将其添加到路径中,并继续查找下一个进程。如果在某个路径下找到合理的序列,isRight将设置为True

    7. 最后,函数回溯到上一级进程,恢复资源状态,并继续查找其他路径。如果找到一个路径中的合理序列,函数将打印相应的提示信息。

    总的来说,这个函数用于模拟资源分配,并查找安全序列,以确保资源分配的安全性。这在操作系统中的资源管理和并发编程中非常有用。

    查找安全序列

    def look_for_reods(Need, Allocation, Available, process_over, geshu, road_name, isRight, types_of_resources, process_nums):
    
    • 1

    这个函数是银行家算法的核心。它通过递归方式查找可能的安全序列,以满足进程的资源需求。这一部分是银行家算法的实现关键。

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    这是一个递归函数,用于查找满足银行家算法的安全序列。以下是对函数中各部分的详细解释:

    1. look_for_reods函数接受多个参数,包括NeedAllocationAvailableprocess_overgeshuroad_nameisRighttypes_of_resourcesprocess_nums。这些参数包含了资源分配的关键信息,以及资源的种类数量、进程的数量以及查找过程中的状态信息。

    2. 首先,函数检查isRight变量是否为True,如果是,表示当前路径是合理的,可以继续查找。然后,创建两新的变量isRight_cntgeshu_cnt,分别初始化为isRightgeshu,用于在递归中传递状态信息。

    3. 接着,函数找出满足当前资源状态的排在第一个进程,并将它们存储在the_first_process列表中。这是通过检查每个进程的需求是否小于等于可用资源来实现的。

    4. 如果没有找到满足当前状态的进程,且路径不包含所有进程(即len(road_name)不等于process_nums),函数打印当前路径和相应的提示信息,表示没有找到安全序列,并将isRight_cnt设置为False

    5. 对于每个满足条件的进程,函数进入一个循环,并执行以下操作:

      • 复制当前的NeedAllocationAvailable到新的Need_cntAllocation_cntAvailable_cnt变量,以便在模拟中修改。
      • 回收当前进程已使用的资源,将已分配的资源添加回可用资源中,标记当前进程为执行完毕,将当前进程添加到路径中,减少待查找的进程数量geshu_cnt
    6. 如果geshu_cnt等于0,表示已找到一个安全序列,函数打印安全序列。

    7. 如果isRight_cnt仍为True,函数继续查找下一个进程。这是通过递归调用look_for_reods函数来实现的,传递更新后的Need_cntAllocation_cntAvailable_cntprocess_overgeshu_cntroad_name。然后,函数回溯到上一级进程,移除已添加的进程,恢复资源状态,并继续查找其他路径。

    总的来说,这个函数用于递归查找满足银行家算法的安全序列,以确保资源分配的安全性。它会遍历所有可能的序列,并找到合理的安全序列。

    主函数

    def main():
    
    • 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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    这是一个主函数main(),它用于启动整个银行家算法的模拟。以下是对函数的详细解释:

    1. 首先,函数通过用户输入获取资源的种类数量和进程的数量。用户需要输入一个空格分隔的字符串,其中第一个数字表示资源种类数量,第二个数字表示进程数量。这些输入信息存储在types_of_resourcesprocess_nums变量中。

    2. 接下来,函数调用get_data()函数来获取资源分配的初始数据,包括Max(最大需求矩阵)、Allocation(已分配矩阵)、Need(需求矩阵)和Available(可用资源向量)。这些数据将在模拟过程中用于银行家算法的执行。

    3. 进入一个无限循环while True,在循环中不断执行银行家算法的模拟。

    4. 在每次循环迭代中,函数调用main_banker_algorithm()函数,传递初始数据和资源的种类数量、进程数量。

    5. main_banker_algorithm()函数用于模拟银行家算法的执行,包括用户输入请求、检查请求的合法性、尝试分配资源,以及查找安全序列。如果成功找到安全序列,就会执行资源分配;否则,算法将等待下一个请求的输入。

    6. 整个循环会不断迭代,允许用户模拟多次资源请求和分配的过程。

    总的来说,main()函数是银行家算法模拟的入口点,用户可以通过输入资源种类数量和进程数量,然后在循环中模拟资源请求和分配的过程,以验证算法的正确性和安全性。

    主程序入口

    if __name__ == '__main__':
    
    • 1

    这一行确保主程序在直接运行时才执行。

    这个程序是一个简单的银行家算法模拟器,用于学习和理解银行家算法的工作原理。用户可以输入资源和进程的数据,然后模拟资源的申请和分配过程,以及查找安全序列。

  • 相关阅读:
    恒峰—高压森林应急消防泵:保障森林安全
    WPF开发随笔收录-心电图曲线绘制
    2022 ICPC 济南总结
    谷爱凌出席米兰时装周波司登米兰·达芬奇庄园首秀
    FLStudio21汉化破解激活版下载,Fl Studio 2024中文破解版激活补丁
    玩转 jmeter backend listener kafka
    Kafaka核心设计与实践原理(第一部分)
    Python自行车租车系统设计与实现报告,基于Django+MySQL
    提升客户体验,你只需要做到这一点
    VBA调用宏的方式总结大全
  • 原文地址:https://blog.csdn.net/wtyuong/article/details/127437180