由於滕豔平所寫的《操作系統原理與實踐教程》這本書的後面的實驗在格式上比較亂,且不容易看懂,所以自己在看懂之後寫了代碼並且在適當的位置後面給予了註釋,同時代碼的格式更容易看,希望能夠更深入瞭解一下避免死鎖的銀行家算法。
爲了更快讀懂代碼,推薦步驟如下:
①、理解避免死鎖的銀行家算法的算法原理
②、由於這篇代碼裏面也有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);
}
}
運行結果: