实验要求
本题主要内容是模拟实现资源分配。银行家算法是避免死锁的一种重要方法,本实验要求用高级语言编写和调试一个简单的银行家算法程序。加深了解有关资源申请、避免死锁等概念,并体会和了解死锁和避免死锁的具体实施方法。
通过对这个算法的设计,让学生能够对书本知识有更深的理解,在操作和其它方面有更高的提升。
要求如下:
(1) 设计一个3个并发进程共享3类不同资源的系统,进程可动态地申请资源和释放资源,系统按各进程的申请动态地分配资源。
(2) 设计用银行家算法 ,实现资源分配 ,应具有显示或打印各进程依次要求申请的资源数以及依次分配资源的情况。
(3) 确定一组各进程依次申请资源数的序列, 输出运行结果。
上面是我们操作系统实验的要求,大家随便看看就行~~
银行家算法的核心是进程提出分配资源请求后检查是否存在安全序列,从而确定是否分配给进程资源,保证系统不会发生死锁,这也是此次实验的难点,具体实现见代码~~
代码如下
import random
class system: ##系统类
def __init__(self,res_a,res_b,res_c): ##系统拥有的资源量ABC
self.res_a=res_a
self.res_b=res_b
self.res_c=res_c
def output(self): ##输出系统资源量
print("系统资源A数量:"+str(self.res_a),
"系统资源B数量:"+str(self.res_b),
"系统资源C数量:"+str(self.res_c))
def safeTest(self,res_a,res_b,res_c): ##检测系统是否能满足进程的请求资源量
if self.res_a<res_a or self.res_b<res_b or self.res_c<res_c:
return False
else:
return True
def safeList(self,list_p,PCB): ##检测系统分配给进程资源后的安全队列
list1=[] ##除了当前进程的所有进程
list2=[] ##安全队列
ra=self.res_a ##记录系统的当前资源量
rb=self.res_b
rc=self.res_c
self.freed(PCB) ##假设当前进程已经释放资源
for i in list_p: ##将除了当前进程的所有进程放入list1
if i.pid!=PCB.pid:
list1.append(i)
for i in range(0,len(list1)): ##循环找出安全队列
for i in list1:
if self.safeTest(i.need_a,i.need_b,i.need_c):
self.freed(i) ##模拟每次进程执行完后释放资源
list2.append(i.pid)
list1.remove(i)
break
self.res_a=ra ##还原系统当前资源量
self.res_b=rb
self.res_c=rc
return list2 ##返回安全队列
def freed(self,PCB): ##进程执行完后释放资源
self.res_a+=PCB.res_a
self.res_b+=PCB.res_b
self.res_c+=PCB.res_c
class PCB:
def __init__(self,pid,res_a,res_b,res_c): ##进程所需资源量need_res,进程当前资源量res=0,状态state为等待
self.pid=pid
self.need_a=res_a
self.need_b=res_b
self.need_c=res_c
self.res_a=self.res_b=self.res_c=0
self.state="等待"
def output(self): ##输出进程信息
print("进程"+str(self.pid)+"资源拥有量为:",self.res_a,self.res_b,self.res_c,
"进程还需资源量为:",self.need_a,self.need_b,self.need_c)
def finish(self,system,res_a,res_b,res_c): ##系统为进程分配资源
print("系统正在为进程"+str(self.pid)+"分配资源")
self.res_a+=res_a
self.res_b+=res_b
self.res_c+=res_c
self.need_a-=res_a
self.need_b-=res_b
self.need_c-=res_c
system.res_a-=res_a
system.res_b-=res_b
system.res_c-=res_c
if self.need_a==self.need_b==self.need_c==0: ##进程执行
self.state="就绪"
print("进程"+str(self.pid)+"已就绪,进程正在执行")
if self.state=="就绪": ##进程释放资源
self.state="完成"
print("进程"+str(self.pid)+"已执行完毕,正在释放资源")
system.freed(self)
def bankerAlgorithm():
list_p=[]
a=system(10,10,10) ##系统初始资源量为:A 10,B 10,C 10
print("初始化——————————————————————————")
for i in range(0,5):
list_p.append(PCB(i,random.randint(3,6),random.randint(3,6), ##进程所需资源量设为:A 3-6=B=C
random.randint(3,6)))
for i in list_p:
i.finish(a,random.randint(0,i.need_a//2),random.randint(0,i.need_b//2), ##进程初始资源量设为: A 0-所需资源量的一半=B=C
random.randint(0,i.need_c//2))
print("初始化完成————————————————————————")
time=0 ##模拟时间
list_f=[] ##进程执行完成队列
while 1:
print("time:"+str(time)) ##输出当前时间
a.output() ##输出系统当前资源量
for i in list_p: ##输出各个进程的信息
i.output()
for i in list_p: ##判断系统能否满足当前进程的需求,如果能并且分配后存在安全队列,则将资源分配给进程
if a.safeTest(i.need_a,i.need_b,i.need_c) and len(a.safeList(list_p,i))==len(list_p)-1:
print("系统准备为进程"+str(i.pid)+"分配资源,安全队列为:",a.safeList(list_p,i))
i.finish(a,i.need_a,i.need_b,i.need_c)
list_f.append(i.pid) ##将进程的id放入完成队列list_f
list_p.remove(i) ##将进程从进程队列移除
break
elif i!=list_p[-1]: ##若不满足当前进程的需求,则转入下一进程
continue
else: ##若都不满足,则输出警告
print("系统不安全,请重新调整参数!")
time+=1 ##时间+1
print("") ##输出一行空白隔开每一秒
if list_p==[] or list_f==[]: ##如果进程全部执行完毕或全都不能执行,终止循环
break
a.output() ##输出系统当前资源量
print("进程的执行顺序为:",list_f) ##输出进程的执行顺序
if __name__ == "__main__":
bankerAlgorithm()
运行结果如下
没错,这次进程和系统的各种信息还是Random库随机生成的,一个F5一下执行到底的那种~~
当然,这种方式也存在一些问题,进程默认请求全部的资源,没有更好的模拟实际进程请求情况,可操作性也很低,感兴趣的同学可以自己试试修改,加入更多的input操作,修改时要注意修改检查安全序列部分。