操作系統銀行家算法模擬實現(C語言版)

目錄

一、實驗目的        

二、實驗內容

三、實驗要點說明

銀行家算法實例

程序結構

四、實驗代碼

五、實驗運行結果


一、實驗目的        

       通過編寫一個模擬動態資源分配的銀行家算法程序,進一步深入理解死鎖、產生死鎖的必要條件、安全狀態等重要概念,並掌握避免死鎖的具體實施方法。

二、實驗內容

  • (1)模擬一個銀行家算法: 設置數據結構 設計安全性算法
  • (2) 初始化時讓系統擁有一定的資源
  • (3) 用鍵盤輸入的方式申請資源
  • (4)如果預分配後,系統處於安全狀態,則修改系統的資源分配情況
  • (5)如果預分配後,系統處於不安全狀態,則提示不能滿足請求

三、實驗要點說明

數據結構

  •  可利用資源向量   int  Available[m]   m爲資源種類
  • 最大需求矩陣        int  Max[n][m]     n爲進程的數量
  • 分配矩陣               int  Allocation[n][m]
  • 還需資源矩陣        int  need[i][j]=Max[i][j]- Allocation[i][j]
  • 申請資源數量        int  Request [m]  
  • 工作向量               int  Work[m]    int  Finish[n]

銀行家算法bank()函數

Requesti:進程Pi的請求向量。   0<=j<=m-1

  • (1) 若 Requesti[j] ≤ Need[i,j],轉向(2),否則出錯。
  • (2) 若 Requesti[j] ≤ Available[j],轉向(3),否則等待。
  • (3) 系統試探着把資源分配給進程Pi,修改下面內容:
  •       Available[j] = Available[j] – Requesti[j];
  •       Allocation[i,j] = Allocation[i,j] + Requesti[j];
  •       Need[i,j] = Need[i,j] –Requesti[j];
  • (4) 試分配後,執行安全性算法,檢查此次分配後系統是否處於安全狀態。若安全,才正式分配;否則,此次試探性分配作廢,進程Pi等待。

安全性算法safe()函數

  • (1) 初始化:設置兩個向量Work(1×m)和Finish(1×n)
  •       Work – 系統可提供給進程繼續運行所需各類資源數,初態賦值Available
  •       Finish – 系統是否有足夠資源分配給進程,初值false.
  • (2) 從進程集合中滿足下面條件進程:
  •       Finish[i] = false;  Need[i,j] ≤ Work[j];
  •       若找到,執行(3),否則,執行(4)。
  • (3) 進程Pi獲得資源,可順利執行,完成釋放所分配的資源。
  •       Work[j] = Work[j]+Allocation[i,j];  Finish[i] = true;  go to (2).
  • (4) 若所有進程Finish[i] = true,表示系統處於安全狀態,否則處於不安全狀態。

先對用戶提出的請求進行合法性檢查,即檢查請求的是否不大於需要的,是否不大於可利用的。 若請求合法,則進行試分配。最後對試分配後的狀態調用安全性檢查算法進行安全性檢查。 若安全,則分配,否則,不分配,恢復原來狀態,拒絕申請。

銀行家算法實例

假定系統中有五個進程{P0、P1、P2、P3、P4}和三種類型資源{A、B、C},每一種資源的數量分別爲10、5、7。各進程的最大需求、T0時刻資源分配情況如下所示。

試問:      

  • ①T0時刻是否安全?      
  • ② T0之後的T1時刻P1請求資源Request1(1,0,2)是否允許?      
  • ③ T1之後的T2時刻P4請求資源Request4(3,3,0)是否允許?      
  • ④ T2之後的T3時刻P0請求資源Request0(0,2,0)是否允許?

① T0時刻是否安全? 工作向量Work.它表示系統可提供給進程繼續運行所需要的各類資源的數目

(1) T0時刻安全性分析

存在安全序列{P1, P3, P4, P0, P2},系統安全。

(2) T0之後的T1時刻P1請求資源Request1(1,0,2)可否允許?

  • ①Request1(1,0,2) ≤ Need1(1,2,2),P1請求在最大需求範圍內
  • ②Request1(1,0,2) ≤ Available1(3,3,2),可用資源可滿足P1請求需要
  • ③假定可爲P1分配,修改Available,Allocation1,Need1向量
  •     Available(2,3,0) = Available(3,3,2)-Request1(1,0,2);
  •     Need1(0,2,0) = Need1(1,2,2)-Request1(1,0,2);
  •     Allocation1(3,0,2) =Allocation1(2,0,0)+Request1(1,0,2);
  • ④利用安全性算法檢查試探將資源分配後狀態的安全性

存在安全序列{P1, P3, P4, P0, P2},所以試探將資源分配給進程P1後的狀態是安全的,可將資源分配給進程P1。

③ T1之後的T2時刻P4請求資源Request4(3,3,0)是否允許?

  • Request4(3,3,0)≤Need4(4,3,1),P4請求在最大需求範圍內。
  • Request4(3,3,0)≤Available(2,3,0)不成立,即可用資源暫不能滿足P4請求資源需要,P4阻塞等待。

P4請求資源Request4(3,3,0)不允許。

④ T2之後的T3時刻P0請求資源Request0(0,2,0)是否允許?

  • Request0(0,2,0)≤Need0(7,4,3);
  • Request0(0,2,0)≤Available(2,3,0);

系統暫時先假定可爲P0分配資源,並修改有關數據,如下圖所示:

進行安全性檢查:可用資源Available(2,1,0)已不能滿足任何進程的需要,故系統進入不安全狀態,此時系統不分配資源。

程序結構

程序共有以下五個部分:

  • (1).初始化init():輸入進程數量、資源種類、資源可利用量、進程資源已分配量、進程最大需求量
  • (2).當前安全性檢查safe():用於判斷當前狀態安全
  • (3).銀行家算法bank():進行銀行家算法模擬實現的模塊
  • (4).顯示當前狀態show():顯示當前資源分配詳細情況
  • (5).主程序main():逐個調用初始化、顯示狀態、安全性檢查、銀行家算法函數,使程序有序的進行

四、實驗代碼

#include<stdio.h>
#include<stdlib.h>

#define False 0
#define True 1

/********主要數據結構********/
char NAME[100]={0};//資源的名稱
int Max[100][100]={0};//最大需求矩陣
int Allocation[100][100]={0};//系統已分配矩陣
int Need[100][100]={0};//還需要資源矩陣
int Available[100]={0};//可用資源矩陣
int Request[100]={0};//請求資源向量	
int Work[100]={0};//存放系統可提供資源量 
int Finish[100]={0}; //標記系統是否有足夠的資源分配給各個進程 
int Security[100]={0};//存放安全序列

int M=100;//進程的最大數
int N=100;//資源的最大數

/********初始化數據:輸入進程數量、資源種類、各種資源可利用數量、
各進程對資源最大需求量、各進程的資源已分配數量等。********/
void init()
{
	/* m爲進程個數,即矩陣行數,n爲資源種類,即矩陣列數。*/
    int i,j,m,n;
	int number,flag;
	char name;//輸入資源名稱
	int temp[100]={0};//統計已經分配的資源
	//輸入系統資源數目及各資源初試個數 
	printf("系統可用資源種類爲:");
	scanf("%d",&n);
	N=n;
	for(i=0;i<n;i++)
	{
		printf("資源%d的名稱:",i);
		fflush(stdin);  //清空輸入流緩衝區的字符,注意必須引入#include<stdlib.h>頭文件
		scanf("%c",&name);
		NAME[i]=name;
		printf("資源%c的初始個數爲:",name);	
		scanf("%d",&number);
		Available[i]=number;
	}
	
	//輸入進程數及各進程的最大需求矩陣 
	printf("\n請輸入進程的數量:");	
	scanf("%d",&m);
	M=m;
	printf("請輸入各進程的最大需求矩陣的值[Max]:\n");
	do{
		flag = False;
		for(i=0;i<M;i++)
			for(j=0;j<N;j++)
			{
				scanf("%d",&Max[i][j]);
				if(Max[i][j]>Available[j])
					flag = True;				
			}
		if(flag)
			printf("資源最大需求量大於系統中資源最大量,請重新輸入!\n");								
	} while(flag);
	
			
	//輸入各進程已經分配的資源量,並求得還需要的資源量 
	do{
		flag=False;
		printf("請輸入各進程已經分配的資源量[Allocation]:\n");
		for(i=0;i<M;i++)
		{
			for(j=0;j<N;j++)
		  	{
				scanf("%d",&Allocation[i][j]);
				if(Allocation[i][j]>Max[i][j])  
					flag=True;				
				Need[i][j]=Max[i][j]-Allocation[i][j];
				temp[j]+=Allocation[i][j];//統計已經分配給進程的資源數目
		  	}
		}
		if(flag)
			printf("分配的資源大於最大量,請重新輸入!\n");		
	}while(flag);
	
	//求得系統中可利用的資源量 
	for(j=0;j<N;j++)
		Available[j]=Available[j]-temp[j];
}

/********顯示資源分配矩陣********/
void showdata()
{
	int i,j;
	printf("*************************************************************\n");
	printf("系統目前可用的資源[Available]:\n");
	for(i=0;i<N;i++)
        printf("%c  ",NAME[i]);
	printf("\n");
	for(j=0;j<N;j++)
        printf("%d  ",Available[j]);
	printf("\n");
	printf("系統當前的資源分配情況如下:\n");
	printf("            Max   	 Allocation    Need\n");
	printf("進程名     ");
	//輸出與進程名同行的資源名,Max、Allocation、Need下分別對應 
	for(j=0;j<3;j++){
		for(i=0;i<N;i++)
			printf("%c  ",NAME[i]);
		printf("     ");
	}
	printf("\n");
	//輸出每個進程的Max、Allocation、Need 
	for(i=0;i<M;i++){
		printf(" P%d        ",i);
	    for(j=0;j<N;j++)
			printf("%d  ",Max[i][j]);
		printf("     "); 
		for(j=0;j<N;j++)
			printf("%d  ",Allocation[i][j]);
		printf("     "); 
		for(j=0;j<N;j++)
			printf("%d  ",Need[i][j]);
		printf("\n");
	}
}

/********嘗試分配資源********/
int test(int i) //試探性的將資源分配給第i個進程 
{ 
	for(int j=0;j<N;j++)
	{
		Available[j]=Available[j]-Request[j];
		Allocation[i][j]=Allocation[i][j]+Request[j];
		Need[i][j]=Need[i][j]-Request[j];
	}
	return True;
}

/********試探性分配資源作廢********/
int Retest(int i) //與test操作相反 
{ 
	for(int j=0; j<N; j++)
	{
		Available[j] = Available[j] + Request[j];
		Allocation[i][j] = Allocation[i][j] - Request[j];
		Need[i][j] = Need[i][j] + Request[j];
	}
	return True;
}

/********安全性算法********/
int safe()
{
	int i,j,k=0,m,apply;
	//初始化work 
	for(j=0;j<N;j++)
        Work[j] = Available[j];
    //初始化Finish 
    for(i=0;i<M;i++) 
    	Finish[i] = False;
	//求安全序列 
	for(i=0;i<M;i++){ 
		apply=0;
		for(j=0;j<N;j++){
			if(Finish[i]==False && Need[i][j]<=Work[j])
			{   
				apply++;
				//直到每類資源尚需數都小於系統可利用資源數纔可分配
				if(apply==N)
				{  
					for(m=0;m<N;m++)
				        Work[m]=Work[m]+Allocation[i][m];//更改當前可分配資源
					Finish[i]=True;
					Security[k++]=i;
					i=-1; //保證每次查詢均從第一個進程開始		
				}
			}
		}
	}
	
	for(i=0;i<M;i++){
		if(Finish[i]==False){
			printf("系統不安全\n");//不成功系統不安全
			return False;
		}
	}
    printf("系統是安全的!\n");//如果安全,輸出成功
    printf("存在一個安全序列:");
	for(i=0;i<M;i++){//輸出運行進程數組
		printf("P%d",Security[i]);
		if(i<M-1) 
			printf("->");
	}
	printf("\n");
	return True;
}

/********利用銀行家算法對申請資源進行試分********/
void bank()
{
	int flag = True;//標誌變量,判斷能否進入銀行家算法的下一步 
	int i,j;

	printf("請輸入請求分配資源的進程號(0-%d):",M-1); 
    scanf("%d",&i);//輸入須申請資源的進程號
    
	printf("請輸入進程P%d要申請的資源個數:\n",i);
	for(j=0;j<N;j++)
	{
		printf("%c:",NAME[j]);
		scanf("%d",&Request[j]);//輸入需要申請的資源
	}
	
	//判斷銀行家算法的前兩條件是否成立 
    for (j=0;j<N;j++)
	{
		if(Request[j]>Need[i][j])//判斷申請是否大於需求,若大於則出錯
		{ 
			printf("進程P%d申請的資源大於它需要的資源",i);
			printf("分配不合理,不予分配!\n");
			flag = False;
			break;
		}
		else 
		{
            if(Request[j]>Available[j])//判斷申請是否大於當前可分配資源,若大於則出錯
			{                         
				printf("進程%d申請的資源大於系統現在可利用的資源",i);
				printf("\n");
				printf("系統尚無足夠資源,不予分配!\n");
				flag = False;
				break;
			}
		}
    }
    //前兩個條件成立,試分配資源,尋找安全序列 
    if(flag) {
		test(i); //根據進程需求量,試分配資源 
		showdata(); //根據進程需求量,顯示試分配後的資源量 
		if(!safe()) //尋找安全序列
		{
			Retest(i);
			showdata();
		}
    }
}


int main()//主函數
{	
	char choice;
	printf("\t---------------------------------------------------\n");
	printf("\t||                                               ||\n");
	printf("\t||               銀行家算法的實現                ||\n");
	printf("\t||                                               ||\n");
	printf("\t||                                               ||\n");
	printf("\t||                     在此輸入個人姓名:******  ||\n");
	printf("\t||                                               ||\n");
	printf("\t---------------------------------------------------\n");
	init();//初始化數據
    showdata();//顯示各種資源
    //用銀行家算法判定系統當前時刻是否安全,不安全就不再繼續分配資源 
	if(!safe()) exit(0);
	
	do{
		printf("*************************************************************\n");
		printf("\n");
		printf("\n");
		printf("\t-------------------銀行家算法演示------------------\n");
		printf("                     R(r):請求分配   \n");	
		printf("                     E(e):退出       \n");
		printf("\t---------------------------------------------------\n");
		printf("請選擇:");
		fflush(stdin);  //清空輸入流緩衝區的字符,注意必須引入#include<stdlib.h>頭文件
		scanf("%c",&choice);
		switch(choice)
		{
			case 'r':
			case 'R':
				bank();break;			
			case 'e':
			case 'E':
				exit(0);
			default: printf("請正確選擇!\n");break;
		}
	} while(choice);
}


五、實驗運行結果

 

 

 

 

 

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