銀行家算法的python實現
前言
寫操作系統作業的時候,發現代碼題沒有要求語言,就試着用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實現.