銀行家算法詳解(C語言)

概述

銀行家算法是荷蘭學者Dijkstra爲銀行系統設計的,以確保銀行在發放現金貸款時,不會發生不能滿足所有客戶需要的情況。後來該算法被用在操作系統中,用於避免死鎖
核心思想:在進程提出資源申請時,先預判此分配是否會導致系統進入不安全狀態。如果會進入不安全狀態,就暫時不答應這次請求,讓該進程先阻塞等待。

過程演示圖解

假定有五個進程{P0,P1,P2,P3,P4}和三類資源{A,B,C},各種資源的數量分別爲10、5、7。在T0時刻的資源分配情況如下
在這裏插入圖片描述
T0時刻的安全性

在這裏插入圖片描述
P1發出請求向量Request1(1,0,2),系統按銀行家算法進行檢查:

  1. Request1(1,0,2)<=Need1(1,2,2)
  2. Request1(1,0,2)<=Available1(3,3,2)
    滿足條件。再利用安全性算法檢查此時系統是否安全
    在這裏插入圖片描述

銀行家算法

1.數據結構

在這裏插入圖片描述

2. 銀行家算法bank()函數

在這裏插入圖片描述

3.程序共有五部分

在這裏插入圖片描述

代碼實現

#include<stdio.h> 
#include <cstdlib>
/*定義數據結構*/
int Max[100][100] ={0};//最大需求矩陣 
int Allocation[100][100]={0};//已分配矩陣 
int Need[100][100]={0};//需求矩陣 
int Available[100]={0}; //資源可用情況 
char Name[100]={0};//資源名稱
int Work[100]={0};//記錄系統中當前各類可用資源的數目 
int Request[100]={0};//系統對各類資源請求的數目 
int Security[100]={0};//保存進程在安全情況下的執行順序 
int M;//系統中進程的數量
int N;//資源類型的數量 

void init()
{
	int i=0,j=0;
	printf("請輸入可用資源的種類數量:");
	scanf("%d",&N);
	for(i=0;i<N;i++)
	{
		printf("請輸入第 %d 個可用資源的名稱: ",i);
		scanf("%s",&Name[i]);
		printf("請輸入初始可用資源 %c 的數量: ",Name[i]);
		scanf("%d",&Available[i]);
	}
	printf("\n");
	printf("請輸入進程的數量:");
	scanf("%d",&M);
	printf("請輸入進程的Max矩陣:\n");
	for(i=0;i<M;i++){//遍歷每一個進程 
		for(j=0;j<N;j++){//輸入第i個進程中每種資源的數量 
			scanf("%d",&Max[i][j]);
		}
	}
	printf("請輸入進程的Allocation矩陣:\n");
	int temp[100]={0};//爲了算新的Available 
	for(i=0;i<M;i++){//遍歷每一個進程 
		for(j=0;j<N;j++){//輸入第i個進程中每種資源的數量 
			scanf("%d",&Allocation[i][j]);
			//第一個進程需要j類資源的數量:最大需求量-已經分配的 
			Need[i][j]=Max[i][j]-Allocation[i][j];
			temp[j]+=Allocation[i][j]; //統計已經分配的資源量 
		}
	}
	for(j=0;j<N;j++)//更新可用資源數目Available
	{
		Available[j]=Available[j]-temp[j];
	} 
}

void show(){//功能:進行資源及進程相關信息顯示
	printf("\t--------------------\n");
	printf("\t系統當前可用的資源矩陣Available:\n");
	int i;
	for(i=0;i<N;i++){
		printf("%c ",Name[i]);
	} 
	printf("\n");
	for(i=0;i<N;i++)
		printf("%d ",Available[i]);
	printf("\n");
	printf("\t系統當前資源分配情況如下: \n");
	printf("\t  Max     Allocation      Need\n");
	printf("進程名  ");
	int j=0;
	for(j=0;j<3;j++)//每個進程名要輸出三次
	{
		for(i=0;i<N;i++){//遍歷所有的資源名稱 
			printf("%c    ",Name[i]);
		}
	 } 
	 printf("\n");
	 for(i=0;i<M;i++){//打印進程
	 	printf("P%d      ",i);
	 	for(j=0;j<N;j++){
	 		printf("%d    ",Max[i][j]);
		 }
		 for(j=0;j<N;j++){
	 		printf("%d    ",Allocation[i][j]);
		 }
		 for(j=0;j<N;j++){
	 		printf("%d    ",Need[i][j]);
		 }
		 printf("\n");
	 }	
}

int safe()
{
	int Finish[100]={0};//Finish:系統是否有足夠的資源分配給進程,使之完成運行 
	// 開始時先令Finish[i]=0,當有祖國資源分配給進程時,再令Finish[i]=1 
	int i=0;
	for(i=0;i<N;i++)
	{
		Work[i]=Available[i];//在執行安全算法開始時,Work=Available 
	}
	int j=0,count=0,k=0,m=0;
	for(i=0;i<M;i++)
	{	
		count=0;//遍歷完一個進程就將count置爲0,對新的i號進程資源達標數進行計數 
		for(j=0;j<N;j++){
			//Finish[i]=0表示未執行 
			if(Finish[i]==0&&Need[i][j]<=Work[j])
			{//如果進程沒有執行且資源需求條件滿足 
				count++;//統計有多少種資源滿足條件 
				if(count==N) //表示對於i號進程所有資源都滿足 
				{
					Finish[i]=1;//記錄i號進程爲可執行 
					for(k=0;k<N;k++)
					{
						Work[k]=Work[k]+Allocation[i][k];
					}
					Security[m]=i;//記錄第m個執行的是i號進程
					i=-1;//將i置爲-1;通過for循環執行i++後變爲0,從第一個進程重新開始找 
					m++;
				} 
			} 
		}
	}
	for(i=0;i<M;i++)
	{
		if(Finish[i]==0)
		{
			printf("系統不安全\n");
			return -1;
		}
	 } 
	 printf("系統時安全的\n");
	 for(i=0;i<M;i++)
	 {
	 	printf("P%d",Security[i]);
	 	if(i<M-1)
	 		printf("-->");
	 }
	printf("\n");
	return 0;
}
bool bank()
{
	printf("請輸入希望手動分配資源的進程的編號:");
	int Id,j;
	bool flag=true;
	while(scanf("%d",&Id))
	{
		if(Id < 0 || Id > M-1)
			printf("進程不存在!請重新輸入\n請輸入希望手動分配資源的進程的編號:");
		else break;
	}
	printf("請輸入請求資源數(%d個):\n",N);
	for(j=0;j<N;j++)
	{
		scanf("%d",&Request[j]);
	}
	printf("開始爲進程P%d分配資源:\n",Id);
	
	for(j=0;j<N;j++)
	{
		if(Request[j]>Need[Id][j]){
			printf("進程請求資源數大於所需資源數,無法分配!\n");
			flag=false;
			break;			
		}
		else if(Request[j]>Available[j]){
			printf("進程請求資源數大於可用資源數,無法分配!\n");
			flag=false;
			break;
		}
		else{
			Available[j] -= Request[j];
	        Allocation[Id][j] += Request[j];
	        Need[Id][j] -= Request[j];
		}
		
	}	
	return flag; 
}
int main()
{
	printf("\t--------------------------\n");
	printf("\t||                      ||\n");
	printf("\t||    模擬銀行家算法    ||\n");
	printf("\t||                      ||\n");
	printf("\t||                      ||\n");
	printf("\t||            Sparky    ||\n");
	printf("\t||                      ||\n");
	printf("\t--------------------------\n");
	init();	
	show();
	safe();
	char choice;
	printf("\t-------------------------------------\n");
	printf("\t||                                  ||\n");
	printf("\t||        手動進行資源請求          ||\n");
	printf("\t||        輸入R(r)請求資源          ||\n");
	printf("\t||        輸入E(e)退出程序          ||\n");
	printf("\t||                                  ||\n");
	printf("\t||                                  ||\n");
	printf("\t-------------------------------------\n");
	while(true){
	
		printf("請選擇資源分配還是退出");
		scanf("%s",&choice); 
		if(choice=='R'||choice=='r')
		{
			if(bank()){
				safe();	
				show(); 
				//exit(0);
			}else{//說明沒有分配資源,不必退出程序。 
				show();
			}				
		}
		else if(choice=='E'||choice=='e')
		{
			exit(0);
		}
		else
			printf("請正確選擇"); 
		
	}
	return 0;	
} 

附簡單測試案例

在這裏插入圖片描述

運行結果

3種資源:

A B C
10 5 7

Max矩陣

7 5 3
3 2 2
9 0 2
2 2 2
4 3 3

Allocation

0 1 0
2 0 0
3 0 2
2 1 1
0 0 2

在這裏插入圖片描述在這裏插入圖片描述在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章