【避免死锁的银行家算法】操作系统原理与实践教程实验

由于滕艳平所写的《操作系统原理与实践教程》这本书的后面的实验在格式上比较乱,且不容易看懂,所以自己在看懂之后写了代码并且在适当的位置后面给予了注释,同时代码的格式更容易看,希望能够更深入了解一下避免死锁的银行家算法。

为了更快读懂代码,推荐步骤如下:

①、理解避免死锁的银行家算法的算法原理

②、由于这篇代码里面也有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);
	 }	 
}


运行结果:



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