【避免死鎖的銀行家算法】操作系統原理與實踐教程實驗

由於滕豔平所寫的《操作系統原理與實踐教程》這本書的後面的實驗在格式上比較亂,且不容易看懂,所以自己在看懂之後寫了代碼並且在適當的位置後面給予了註釋,同時代碼的格式更容易看,希望能夠更深入瞭解一下避免死鎖的銀行家算法。

爲了更快讀懂代碼,推薦步驟如下:

①、理解避免死鎖的銀行家算法的算法原理

②、由於這篇代碼裏面也有c++裏面的一些東西,如cout<<, cin>>,具體意思在下面的備註裏面,在讀代碼之前應該知道這是什麼。

備註:

①什麼是cout<<?

簡單地說cout就像是c語言中的printf,其中<<後面的內容是輸出的內容:

如:cout<<"你好";

就是輸出‘你好’。

再比如:cout<<endl<<"p"<<j<<"->allocation:";

其中j是變量,所以不用引號。假設j=1。

輸出結果是:先換行,然後輸出p1->allocation:

②什麼是cin>>?

簡單地說cin就是c語言裏面的scanf。

如:cin>>k;

就是讓你輸入變量k的值。

總之這2個東西就是輸入輸出。但是在使用之前必須加

#include <iostream>
using namespace std ;

滕豔平這本書是

#include <iostream.h>
但是運行的時候會報錯,即使全部代碼打一樣也會有報錯。
比如:
①、main函數中調用的函數被放在了main函數之後也會報錯。
②、滕那本書safecheck函數裏面有p[i].state=='W',但是W改成R也對。

如果想深入瞭解這2個東西,建議查更多詳細的資料

/*避免死鎖的銀行家算法*/ 
#include <iostream>
using namespace std ;
struct PCB{
       char state; //進程的狀態
       int request; //需求量 
       int max;   //最大需求量 
       int allocation;  //當前已經分配給該進程的資源數量 
};

/*輸出每個進程的編號,最大需求量,當前請求量,已分配量和狀態*/
void show(struct PCB p[],int av)
{
	int i;
	cout<<endl<<"available="<<av;
	cout<<endl<<"number  max  request  allocation  state";
	for(i=0;i<3;i++){  //循環輸出每個進程的信息 
		cout<<endl<<i;
		cout<<"  ";
		cout<<p[i].max;
		cout<<"  ";
		cout<<p[i].request;
		cout<<"  ";
		cout<<p[i].allocation;
		cout<<"  ";
		cout<<p[i].state;
		cout<<endl;
	}
}
/*隨機分配算法*/
void randomallocation(struct PCB p[],int av){
	int i=0;
	int j=0;
	int w;
	int e;
	while(1) {
		if(i==3)
			i=i-3;
		while(1){
			if(i==3)
				i=i-3;
			else{
				if(p[i].state=='R'){  //判斷當前進程是不是可以安排資源的狀態 
					do{
						cout<<endl<<"p"<<i<<"->request:";  //輸入當前進程的需求量 
						cin>>p[i].request;
					}while(p[i].request>(p[i].max-p[i].allocation));    //當輸入的需求量不符合條件,執行重新輸入 
					break;  //當前進程的資源安排好之後,跳出當前循環 
				}
				else
					i++;
			} 
		}
		if(p[i].request<=av){  //判斷分配的資源是否小於可獲得的總資源個數 
			av=av-p[i].request;  //系統剩餘資源減少 
			p[i].allocation=p[i].allocation+p[i].request;
			p[i].request=0;  //置當前進程的需求量爲0 
			if(p[i].max==p[i].allocation){
				av=av+p[i].allocation; //完成該進程,釋放該進程所佔的資源,歸還給系統
				p[i].state='E'; //將該進程的狀態置爲完成狀態 
				p[i].allocation=0;
				p[i].request=0;
			}
			j=0;
			while(j<3){
				if((p[j].request<=av)&&(p[j].state=='W')){
					av=av+p[j].allocation;
					p[j].request=0;
					p[j].state='E';
					p[j].allocation=0;
				}
				if((p[j].max<av+p[j].allocation)&&(p[j].state=='W')){
					p[j].state='R';
				}
				j++;
			}
			show(p,av);
		}
		else{
			p[i].state='W';
			show(p,av);
		}
		w=0;
		e=0;
		for(j=0;j<3;j++){
			if(p[j].state=='W')
				w++;
			else if(p[j].state=='E')
				e++;
				else break;
		}
		if(((w+e)==3)&(w!=0)){
			cout<<endl<<"發生死鎖!";
			return;
		}
		else if(e==3){
			cout<<endl<<"三個進程順利執行完!";
			return; 
		}
		i++;
	}
} 

/*安全性算法*/
bool safecheck(struct PCB p[],int av){
	bool finish[3];  //finish有2中取值,true和false,表示該進程是否已經完成 
	int order[3];  //order裏面依次存放已經完成的線程的下標 
	int i;
	int j=0;
	int f=0;  //f用來存放能夠順利完成的進程的個數 
	int k=0;
	int work;  //在試着分配的過程中,work用來等效替代available的作用,表示系統中該資源的剩餘量 
	int temp;  //temp用來存放進程的資源擁有量,因爲在試分配過程中會改變allocation的值,等試分配完了,用它可以恢復allocation的值 
	work=av;
	for(i=0;i<3;i++) {
		order[i]=0;
		if(p[i].state=='E')  //如果該進程的狀態爲E,則標誌該進程已經完成 
			finish[i]=true;
		else   //否則如果該進程的狀態不爲E,則標誌該進程還未完成 
			finish[i]=false;
	}
	while(k<3){  //有這個控制的原因:每一次的控制都通過看看所有進程中是否有滿足條件的 
		for(i=0;i<3;i++) {
			if((p[i].state=='R')&&(p[i].request<=work)&&(finish[i]==false)){  //試着爲該進程分配資源 
				temp=p[i].allocation;
				p[i].allocation=p[i].request+p[i].allocation;
			}
			if(((p[i].allocation+work)>=p[i].max)&&(finish[i]==false)){
				work=p[i].allocation+work; //完成該進程,並且歸還該進程使用的資源給系統 
				finish[i]=true;  //標誌該進程已經完成 
				order[j]=i;    //將該進程的下標加入已經完成的進程的序列中 
				j++;
				if(p[i].state=='R')
					p[i].allocation=temp;   //恢復該進程的資源擁有量值 
			}
		}
		k++;
	}
	for(i=0;i<3;i++)
		if(finish[i]==true)
			f++;   // f用來存放能夠順利完成的進程的個數 ,能夠順利完成的個數加1
	if(f==3){   //所有進程都能夠順利完成,返回true表示這種分配方式安全 
			//showorder(order);
		return true;   
	}
	else   //所有進程不能都順利完成,返回false表示這種分配方式不安全 
		return false;
}

/* 銀行家算法*/ 
void bankallocation(struct PCB p[],int av){
	int k;
	int request;
	int f;
	int i;
	show(p,av);
	while(1){
		request=0;
		k=-1;
		do{
			if(k!=-1)
				cout<<endl<<"不是安全狀態!";
			av=av+request;
			p[k].allocation=p[k].allocation-request;
			do{
				cout<<endl<<"p"<<"->NO.:";
				cin>>k;
			}while(p[k].state!='R');
			do{
				cout<<endl<<"p"<<k<<"->request:";
				cin>>request;
			}while(request>(p[k].max-p[k].allocation));
			if(request>av){
				p[k].request=request;
				p[k].state='W';
				break;
			}
			p[k].allocation=p[k].allocation+request;
			av=av-request;
		}while(safecheck(p,av)!=true);
		if(p[k].allocation==p[k].max){
			p[k].state='E';
			av=av+p[k].allocation;
			p[k].allocation=0;
		}
		for(i=0;i<3;i++){
			if((p[i].state=='W')&&(p[i].request<=av)){
				if(safecheck(p,av)==true){
					p[i].allocation=p[i].request+p[i].allocation;
					av=av-p[i].request;
					p[i].request=0;
					p[i].state='R';
					if(p[i].max==p[i].allocation){
						p[i].state='E';
						av=av+p[i].allocation;
						p[i].allocation=0;
					}
				}
				else{
					cout<<endl<<"不是安全狀態!原請求資源量無效。";
					p[i].request=0;
					p[i].state='R';
			}
		}
	}
	show(p,av);
	f=0;
	for(i=0;i<3;i++){
		if(p[i].state=='E')
			f++;
	}
	if(f==3){
		cout<<endl<<"所有進程順利執行完!";
		break;
	}
}
}
int main()
{
     struct PCB process[3]; //定義3個結構體進程 
     int i;  //循環變量,進程號的下標 
     int j;  //循環變量,進程號的下標 
     int k;  //選項變量 
     int available=10;  //可獲得的資源 
     for(i=0;i<3;i++){
         cout<<endl;  //換行操作 
         cout<<"p"<<i<<"->max:";  //打印:pi->max ,其中i是變量 
         cin>>process[i].max;  //輸入一個進程的資源最大需求量 
         if(process[i].max>10){   //如果當前進程的需求量大於系統該資源的最大量 
             cout<<endl;
             cout<<"錯誤,請重新輸入!";
             i--;
         } 
         else{
              do{
                  cout<<endl<<"->allocation:";  
                  cin>>process[i].allocation;//否則輸入當前進程對該資源的擁有量 
              }
              while((process[i].allocation>process[i].max)||(available-process[i].allocation<0));  //當輸入的進程的擁有量大於了進程需要的最大量
			  																					//  或者大於了系統可提供的最大量,重新執行循環體輸入當前進程對該資源的擁有量 
              available=available-process[i].allocation;  //系統中該資源的剩餘量(進程對該資源可獲得的量)減少 
              process[i].request=0;  // 置該進程的資源需求量爲0 
              process[i].state='R';   //置該進程的狀態爲R 
         }
     }
     show(process,available);
     cout<<endl<<"1--隨機分配算法       2--銀行家算法";
	 do{
	 	cout<<endl<<"請選擇:"; 
	 	cin>>i; 
	 } while(!((i==1)||(i==2)));
	 if(i==1){
	 	randomallocation(process,available);
	 }
	 else{
	 	do{
	 		if(safecheck(process,available)==false){
	 			cout<<endl<<"當前狀態不安全!";
				cout<<endl<<"     1--退出     2--重置";
				do{
					cout<<endl<<"選擇:";
					cin>>k; 
				}while((k!=1)&&(k!=2));
				if(k==2){   //執行重置 
					available=10;   //置系統資源爲10 
					for(j=0;j<3;j++){   //依次對3個進程執行重置資源擁有量 
						cout<<endl<<"p"<<j<<"->allocation:";
						cin>>process[j].allocation;   //輸入當前資源的擁有量 
						available=available-process[j].allocation;  //系統資源量減少(減去剛剛分配的) 
					}
				}
	 		}
	 		else{  //安全性檢查結果爲安全 
	 			k=0;
	 			break;
	 		}
	 	}while(k==2);
	 	if(k==1) return -1;
	 	else if(k==0)   //如果安全性檢查結果爲安全,執行銀行家算法 
	 		bankallocation(process,available);
	 }	 
}


運行結果:



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