前言


写操作系统作业的时候,发现代码题没有要求语言,就试着用python写了。

《现代操作系统》第四版,第六章死锁的课后题41题:
41.Program a simulation of the banker’s algorithm. Your program should cycle through
each of the bank clients asking for a request and evaluating whether it is safe or unsafe. Output a log of requests and decisions to a file.

41.编写银行家算法的模拟程序。该程序应该能够循环检查每一个提出请求的银行客户,并且能判断这一请求是否安全。请把有关请求和相应决定的列表输出到一个文件中。


一、什么是银行家算法(Banker’s Algorithm)

简单的来说,就是每次分配资源之前检查一下这次分配会不会导致某个进程得不到足够的资源导致死锁,不会就分配,会就等待。


“银行家算法(Banker’s Algorithm)是一个避免死锁(Deadlock)的著名算法,是由艾兹格·迪杰斯特拉在1965年为T.H.E系统设计的一种避免死锁产生的算法。它以银行借贷系统的分配策略为基础,判断并保证系统的安全运行。
在银行中,客户申请贷款的数量是有限的,每个客户在第一次申请贷款时要声明完成该项目所需的最大资金量,在满足所有贷款要求时,客户应及时归还。银行家在客户申请的贷款数量不超过自己拥有的最大值时,都应尽量满足客户的需要。在这样的描述中,银行家就好比操作系统,资金就是资源,客户就相当于要申请资源的进程。
银行家算法是一种最有代表性的避免死锁的算法。在避免死锁方法中允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次分配资源的安全性,若分配不会导致系统进入不安全状态,则分配,否则等待。为实现银行家算法,系统必须设置若干数据结构。
要解释银行家算法,必须先解释操作系统安全状态和不安全状态。
安全序列是指一个进程序列{P1,…,Pn}是安全的,即对于每一个进程Pi(1≤i≤n),它以后尚需要的资源量不超过系统当前剩余资源量与所有进程Pj (j < i )当前占有资源量之和。” ——摘自百度百科


二、代码实现

1.requirements

为了方便矩阵运算,用了numpy, 同时因为要求输出logs,用了time。
numpy==1.20.2

from numpy import *
import time

2.定义变量

MAXN定义最大的线程数,MAXM定义资源种数。

logs存输出的日志的字符串。
Available存可使用的资源数,
MaxNeed存最大需求量,
Allocation存已分配的资源数,
Need存接下来还能要多少资源,
request存请求资源的矩阵,
logs存输出日志的字符串。

#N is quentity of processes. M is quentity of kinds of resources.
MAXN=5
MAXM=5
#define for resources scheduling
Available=full(MAXM,10)
MaxNeed=random.randint(1, 20, size=(MAXN, MAXM))
Allocation=zeros((MAXN, MAXM))
Need=MaxNeed-Allocation
#request matrix [process NO, resource type]
request=zeros((MAXN, MAXM), int)
#logs of requests and decisions in string
logs='Banker\'s algorithm simulator \n@created by Concyclics\n\n'

3.检查本次分配是否安全

对于每一个进程,检查它用剩下的资源能否完成任务,如果可以,就把它已有的资源一起加入可分配的资源中,因为它可以很快地完成并释放资源。
work数组里存可用的资源,finish存能够结束的进程。
如果有进程不能结束,说明这种分配不安全。

#the function to check the allocation is safe or not
def safe():
	work=Available
	finish=full(MAXN, 0)
	for i in range(MAXN):
		if finish[i]==0:
			for j in range(MAXM):
				if Need[i][j]<=work[j]:
					work[j]+=Allocation[i][j]
				else:
					break
			finish[i]=1
	for i in finish:
		if i ==0:
			return False
	return True

4.分配函数

从request中顺序读取请求并执行模拟分配,用safe()函数检查是否安全。

#function for allocating by the request matrix
def bank():
	global logs
	Need=MaxNeed-Allocation
	for i in range(MAXN):
		for j in range(MAXM):
			logs+='\nin '+time.strftime('%Y年 %m月 %d日 %H:%M:%S',time.localtime(time.time()))
			logs+='\nProcess '+str(i)+' requests for '+str(request[i][j])+' resource type:'+str(j)+'\n result:\n'
			if request[i][j]>Need[i][j] or request[i][j]>Available[j]:
				logs+='the request is too large! Failed!\n'
			elif request[i][j]<=Available[j]:
				Available[j]-=request[i][j]
				Allocation[i][j]+=request[i][j]
				Need[i][j]-=request[i][j]
				if safe()==False:
					Available[j]+=request[i][j]
					Allocation[i][j]-=request[i][j]
					Need[i][j]+=request[i][j]
					logs+='the request will make the system danger! Wait!\n'
				else:
					logs+='the request is safe. Success.\n'

5.完整代码

#by concyclics

'''
filename Banker.py
version of Python 3.8.2
requirements:
numpy==1.20.2
'''
from numpy import *
import time

#N is quentity of processes. M is quentity of kinds of resources.
MAXN=5
MAXM=5
#define for resources scheduling
Available=full(MAXM,10)
MaxNeed=random.randint(1, 10, size=(MAXN, MAXM))
Allocation=zeros((MAXN, MAXM))
Need=MaxNeed-Allocation
#request matrix [process NO, resource type]
request=zeros((MAXN, MAXM), int)
#logs of requests and decisions in string
logs='Banker\'s algorithm simulator \n@created by Concyclics\n\n'

#the function to check the allocation is safe or not
def safe():
	work=Available
	finish=full(MAXN, 0)
	for i in range(MAXN):
		if finish[i]==0:
			for j in range(MAXM):
				if Need[i][j]<=work[j]:
					work[j]+=Allocation[i][j]
				else:
					break
				finish[i]=1
	for i in finish:
		if i ==0:
			return False
	return True

#function for allocating by the request matrix
def bank():
	global logs
	Need=MaxNeed-Allocation
	for i in range(MAXN):
		for j in range(MAXM):
			logs+='\nin '+time.strftime('%Y年 %m月 %d日 %H:%M:%S',time.localtime(time.time()))
			logs+='\nProcess '+str(i)+' requests for '+str(request[i][j])+' resource type:'+str(j)+'\n result:\n'
			if request[i][j]>Need[i][j] or request[i][j]>Available[j]:
				logs+='the request is too large! Failed!\n'
			elif request[i][j]<=Available[j]:
				Available[j]-=request[i][j]
				Allocation[i][j]+=request[i][j]
				Need[i][j]-=request[i][j]
				if safe()==False:
					Available[j]+=request[i][j]
					Allocation[i][j]-=request[i][j]
					Need[i][j]+=request[i][j]
					logs+='the request will make the system danger! Wait!\n'
				else:
					logs+='the request is safe. Success.\n'


if __name__=='__main__':
	i=0
	for x in Available:
		logs+='resource type'+str(i)+' quentity: '+str(x)+'\n'
		i+=1
	logs+='\n'+'MaxNeed matrix i for process, j for resource'
	logs+='\n'+str(MaxNeed)+'\n'
	request+=random.randint(1, 5, size=(MAXN,MAXM))
	bank()
	print(logs)
	#write logs into file Banker_logs.txt
	with open('Banker_logs.txt','w',encoding='utf-8') as fileLogs:
		fileLogs.write(logs)
	

三、我的仓库

存放了我写的一些作业。
链接: Github仓库.
链接: Gitee仓库.
求个star ❤️ ❤️ ❤️
代码链接: 银行家算法的python实现.