银行家算法python实现Dijkstra
题目要求
- 假定系统有3类资源A(10个)、B(15个)、C(12个),系有5个进程并发执行,进程调度采用时间片轮转调度算法。
- 每个进程由一个进程控制块( PCB)表示,进程控制块可以包含如下信息:进程名、需要的资源总数、已分配的资源数、进程状态。
- 由程序自动生成进程(包括需要的数据,要注意数据的合理范围)。
- 进程在运行过程中会随机申请资源(随机生成请求的资源数),如果达到最大需求,表示该进程可以完成;如果没有达到最大需求,则运行一个时间片后,调度其它进程运行。资源分配采用银行家算法来避免死锁。
- 每个进程的状态可以是就绪 W(Wait)、运行R(Run)、阻塞B(Block)或完成F(Finish)状态之一。
- 每进行一次调度,程序都要输出一次运行结果:正在运行的进程、就绪队列中的进程、阻塞队列中的进程、完成的进程以及各个进程的 PCB,以便进行检查。
银行家算法原理
原理
这里不再赘述
分析
本算法中有几个矩阵:需求矩阵need,用于保存和更新每个进程的实时需要;请求矩阵request, 用于保存和更新每个进程的实时请求;分配矩阵allocation, 用于保存和更新每个进程的实时分配;每个进程的PCB保存了该进程的名字、状态、对各资源的最大需求、和已分配给该进程的资源数。
进程调度采用时间片轮转的方式。进程初始状态为就绪状态。当进程申请资源时,在以下两种情况会进入阻塞:1.资源不足;2.若同意该资源申请系统会进入不安全状态,即不能通过安全性算法。进入阻塞的进程就失去申请资源的权限。再每次进程调度时,会遍历阻塞队列,当当前资源数满足阻塞进程需求时,则加入就绪队列。当就绪队列的第一个进程尝试申请资源时,将进行安全性检测;此时会试探着将资源分配出去,即将需求矩阵、分配矩阵和可用资源向量Available复制一次,对复制的矩阵进行安全性判断;若系统安全则将资源分配出去,并更新需求矩阵、分配矩阵和可用资源向量Available等。
代码
这里给出仅为主体代码,测试部分较为简单,可以自行补充,或者关注以下公众号,回复100904获得全部代码
"""
2020/06本代码为本人实验内容,有需要的人可做参考,请勿直接ctrl c+v copy
函数命名和个别变量名请改成自己需要的名字
"""
import random
import numpy as np
import copy
class PCB:
def __init__(self,name,state,need_A_max,need_B_max,need_C_max,all_A ,all_B ,all_C ): ##初始化进程
self.name = name #进程名字
self.state=state #状态
self.need_A_max = need_A_max #最大需求A资源
self.need_B_max = need_B_max
self.need_C_max = need_C_max
self.all_A = all_A #已经为该进程分配的A
self.all_B = all_B
self.all_C = all_C
def output(self): #时间片轮转输出
# print("本程序资源默认顺序为A B C")
# print("进程名字 各类资源最大需求 已经分配资源 状态") #1+3+3+1
print('%-13s%-4s%-4s%-12s%-4s%-4s%-8s%-10s' % (str(self.name), str(self.need_A_max), str(self.need_B_max), str(self.need_C_max),str(self.all_A)
,str(self.all_B),str(self.all_C),str(self.state)))
def Run(self): ##将状态置为Run
self.state="Run"
def Finish(self): ##将状态置为Finish
self.state="Finish"
def Wait(self): ##将状态置为Wait
self.state="Wait"
def Block(self):
self.state="Block" #阻塞
def running(self,Available1,allocation1,need1):
# 安全性算法
i = 0
Finish = [False,False,False,False,False]
work = [0,0,0]
k = 0
cwj_dex = 0
for f in range(3):
Available1[f] = Available[f] - request[int(list[0].name)][f]
allocation1[int(list[0].name)][f] = allocation[int(list[0].name)][f] + request[int(list[0].name)][f]
need1[int(list[0].name)][f] = need[int(list[0].name)][f] - request[int(list[0].name)][f]
for mm in range(3):
#可以和上面循环合并
work[mm] = Available1[mm]
# for u in range(3):
l = 0
while l<5:
for g in range(5):
if( (need1[g][0]<=work[0]) and Finish[g] == False and (need1[g][1]<=work[1]) and (need1[g][2]<=work[2]) ):
# and need1[int(list[0].name)][g]<work[g]
work[0] = work[0] + allocation1[g][0]
work[1] = work[1] + allocation1[g][1]
work[2] = work[2] + allocation1[g][2]
Finish[g] = True
break
l += 1
#检查Finishw
for haha in range(5):
if(Finish[haha] == False):
#不安全
k = 1
break
if (k == 0):
cwj_dex = 1
return cwj_dex
def initialization_ChenWJ(num):
#初始化进程和可利用资源向量,开始为10,15,12
list0=[] #就绪队列
for i in range(num):
list0.append(PCB(str(i),"Wait",random.randint(0,10),
random.randint(0,15),random.randint(0,12),0,0,0))
for c in range(5):
need[c][0] = int(list0[c].need_A_max)
need[c][1] = int(list0[c].need_B_max)
need[c][2] = int(list0[c].need_C_max)
print(need)
return list0
def RR_time():
#时间片轮转算法
#list 就绪队列 list_b 阻塞队列
cwj_dex = 0#0表示系统不安全
list_b = []
time = 0
cwj = 0 #调度锁
RR_time = 3 #时间片长度
list_cwj = []
while(1):
print("time:", time)
if (cwj == 0):
#获得调度权限
print("剩余",end = "")
print("A:"+str(int(Available[0]))+" B:"+str(int(Available[1]))+" C:"+str(int(Available[2])))
if(list):
# 给就绪队列头随机生成请求资源
need[int(list[0].name)][0] = list[0].need_A_max - list[0].all_A
need[int(list[0].name)][1] = list[0].need_B_max - list[0].all_B
need[int(list[0].name)][2] = list[0].need_C_max - list[0].all_C
for m in range(3):
request[int(list[0].name)][m] = random.randint(0,need[int(list[0].name)][m]) #设定请求量小于需求
#调度前打印打印就绪队列
print("**********************************************")
print("目前就绪进程如下所示:")
print("进程名字 各类资源最大需求 已经分配资源 状态") # 1+3+3+1
for i in range(len(list)):
print('%-13s%-4s%-4s%-12s%-4s%-4s%-8s%-10s' % (str(list[i].name), str(list[i].need_A_max), str(list[i].need_B_max), str(list[i].need_C_max), str(int(list[i].all_A))
, str(int(list[i].all_B)), str(int(list[i].all_C)), str(list[i].state)))
print("目前阻塞进程如下所示:")
print("进程名字 各类资源最大需求 已经分配资源 状态") # 1+3+3+1
if (not list_b):
print("无阻塞进程")
for i in range(len(list_b)):
print('%-13s%-4s%-4s%-12s%-4s%-4s%-8s%-10s' % (str(list_b[i].name), str(list_b[i].need_A_max), str(list_b[i].need_B_max), str(list_b[i].need_C_max), str(list_b[i].all_A)
, str(list_b[i].all_B), str(list_b[i].all_C), str(list_b[i].state)))
print("**********************************************" + "\n")
if (list_b):
print("正在检测阻塞队列")
y = 0
index_btow = []
for y in range(len(list_b)):
#判断能否变成就绪
if((request[int(list_b[y].name)][0] <= Available[0]) and (request[int(list_b[y].name)][1] <= Available[1]) and
(request[int(list_b[y].name)][2] <= Available[2])):
index_btow.append(y)
for wo in range(len(index_btow)):
list_b[index_btow[wo]].Wait()
list.append(list_b[index_btow[wo]])
print("进程" + str(list_b[index_btow[wo]].name) + "已经从阻塞转换成就绪")
for wo1 in range(len(index_btow)-1,-1,-1):
list_b.remove(list_b[index_btow[wo1]])
index_btow.clear()
if (list): #执行过程
print("进程"+str(list[0].name)+"运行"+",剩余时间片"+str(RR_time-1)+",总时间片"+str(3))
print("进程"+str(list[0].name)+" 申请了A:"+str(int(request[int(list[0].name)][0])) +" 申请了B:"+str(int(request[int(list[0].name)][1])) +" 申请了C:"+str(int(request[int(list[0].name)][2]) ) )
#判断当前资源是不是够分配
if ((request[int(list[0].name)][0] <= Available[0]) and (request[int(list[0].name)][1] <= Available[1]) and (request[int(list[0].name)][2] <= Available[2])):
#满足,尝试分配
allocation1 = copy.deepcopy(allocation)
Available1 = copy.deepcopy(Available)
need1 = copy.deepcopy(need)
cwj_dex = list[0].running(Available1,allocation1,need1)
if(cwj_dex == 1):
#系统安全,正式分配资源,可以运行
list[0].Run()
for f in range(3):
Available[f] = Available[f] - request[int(list[0].name)][f]
allocation[int(list[0].name)][f] = allocation[int(list[0].name)][f] + request[int(list[0].name)][f]
need[int(list[0].name)][f] = need[int(list[0].name)][f] - request[int(list[0].name)][f]
print("该资源申请成功!")
list[0].all_A = allocation[int(list[0].name)][0]
list[0].all_B = allocation[int(list[0].name)][1]
list[0].all_C = allocation[int(list[0].name)][2]
RR_time -= 1 #有进程成功申请进程,时间才用完
else:
#不安全阻塞
print("进程"+str(list[0].name)+"因为系统不安全,进入阻塞")
list[0].Block()
list_b.append(list[0])
list.remove(list[0])
else:
#资源不够,阻塞
print("进程" + str(list[0].name) + "因为资源不够,进入阻塞")
list[0].Block()
list_b.append(list[0])
list.remove(list[0])
if (RR_time == 0):
#时间片用完
if(((list[0].need_A_max-list[0].all_A) == 0) and ((list[0].need_B_max-list[0].all_B) == 0) and ((list[0].need_C_max-list[0].all_C) == 0) ):
#资源达到最大要求
list[0].Finish()
for p in range(3):
allocation[int(list[0].name)][p] = 0
allocation1[int(list[0].name)][p] = 0
Available[0] = Available[0] + list[0].all_A
Available[1] = Available[1] + list[0].all_B
Available[2] = Available[2] + list[0].all_C
Available1[0] = Available1[0] + list[0].all_A
Available1[1] = Available1[1] + list[0].all_B
Available1[2] = Available1[2] + list[0].all_C
print("*****!!!进程" + list[0].name + "执行完毕" + "!!!*****")
list.remove(list[0])
else:
#未运行完,该进程放到就绪队列末尾
list[0].Wait()
list_cwj.append(list[0])
list.remove(list[0])
list.append(list_cwj[0])
list_cwj.remove(list_cwj[0]) #再次清空备用列表
cwj = 0 # 开权限为调度做准备
RR_time = 3 # 时间片长度
print("#####!!!该时间片已经用完!!!#####")
if (RR_time>0 and list):
if( ((list[0].need_A_max-list[0].all_A) == 0) and ((list[0].need_B_max-list[0].all_B) == 0) and ((list[0].need_C_max-list[0].all_C) == 0)):
#时间片未用完,该进程已经运行完
list[0].Finish()
for p in range(3):
allocation[int(list[0].name)][p] = 0
allocation1[int(list[0].name)][p] = 0
Available[0] = Available[0] + list[0].all_A
Available[1] = Available[1] + list[0].all_B
Available[2] = Available[2] + list[0].all_C
Available1[0] = Available1[0] + list[0].all_A
Available1[1] = Available1[1] + list[0].all_B
Available1[2] = Available1[2] + list[0].all_C
print("*****!!!进程" + list[0].name + "执行完毕" + "!!!*****")
list.remove(list[0])
cwj = 0
RR_time = 3 # 时间片长度
time += 1
# if (time == 35):
# break
if (not list and not list_b):
print("所有进程都运行完毕")
#如果空,退出
break