操作系统第七章实验死锁的避免.docx
《操作系统第七章实验死锁的避免.docx》由会员分享,可在线阅读,更多相关《操作系统第七章实验死锁的避免.docx(15页珍藏版)》请在冰豆网上搜索。
操作系统第七章实验死锁的避免
第7章死锁的避免
软件1211102052019金凯
1.实验题目:
用银行家算法实现资源的分配
银行家算法:
Dijkstra(1965)提出了一种能够避免死锁的调度算法,称为银行家算法。
其基本思想是:
系统中的所有进程放入一个进程集合,先把资源试探性地分配给它。
然后找出剩余资源能满足最大需求量的进程,进行分配。
(来源于教材202页)
2.程序中所使用的数据结构及主要符号说明
考虑到一个系统有n个进程和m种不同类型的资源,定义以下向量和矩阵数据结构。
1.系统中每类资源总数向量Resource=(R1,R2,…,Rm)
2.系统中当前每类资源可用数向量Available=(V1,V2,…,Vm)
3.进程对各类资源的最大需求矩阵(Cij表示进程Pi需要Rj类资源的最大数目)
C11C12…C1m
C21C22…C2m
Claim=………
Cn1Cn2…Cnm
4.系统中当前资源的已分配情况矩阵(Aij表示进程Pi已分配到Rj类资源的数目)
A11A12…A1m
A21A22…A2m
Allocation=………
An1An2…Anm
系统安全性定义:
在时刻T0系统是安全的,仅当存在一个进程序列P1,P2,…,Pn,对进程Pk(k=1,2,…n)满足公式:
{Cki-Aki<=Vi+∑Aji(j=1...),k=1,2,…,n;i=1,2,…,m}
此公式为安全序列(参考教材201页)
3.程序流程图
1、系统主要过程流程图
2、银行家算法流程图
3、安全性算法流程图
4.源程序
本程序在c++编译器cfree上通过测试,vc6.0没有经过测试。
说明:
这里建立了如教材204-206页上面的一个例子,模拟了5个进程请求资源的情况。
具体可以对照教材说明进行查阅。
#include
usingnamespacestd;
voidprint(int*Max,int*Allocation,int*Need,int*Available,intp,intr)
{
inti,j,flag=1;
cout<<("进程号请求的占用的C-A:
需要的可用")<cout<<"P[i]ClaimAllocationNeedAvailable"<//这是一个表头,下面是英文,上面用汉字说明作用
for(i=0;i
{
cout<<"P"<
for(j=0;j{
cout<<*(Max+i*r+j)<<"";
}
cout<<'\t';//制表符,用于排列,无特殊意义
for(j=0;j{
cout<<*(Allocation+i*r+j)<<"";
}
cout<<'\t';
for(j=0;j{
cout<<*(Need+i*r+j)<<"";
}
cout<<'\t';
if(flag==1)
{
for(j=0;j{
cout<<*(Available+j)<<"";
}
flag=0;
}
cout<}
}
boolcheckSafe(int*Need,int*Allocation,int*Available,intp,intr)
{
inti=0,j=0,k=0,m=0,count=0,flag1=0,flag2=0;
int*list,*Work;//设置工作向量Work,安全序列list,均用指针来做。
数组太麻烦了
bool*Finish;//完成标志Finish
Work=newint[r];
Finish=newbool[p];
list=newint[p];
//初始化完成标志Finish,默认为false
for(i=0;i
*(Finish+i)=false;
//初始化工作向量Work
for(i=0;i*(Work+i)=*(Available+i);
//进行安全检查
while(k
{
//判断Finish[i]是否为true,且需求向量小于工作向量
flag1=0;
for(j=0;j{
if(*(Finish+m)!
=true)
{
if(*(Need+m*r+j)>*(Work+j))
{
flag1=0;
break;
}
flag1=1;
}
}
//若flag1==1即Finish[i]为true,且需求向量小于工作向量,则该进程可以获得资源
if(flag1==1)
{
for(j=0;j{
*(Work+j)+=*(Allocation+m*r+j);
}
*(Finish+m)=true;
*(list+k)=m;
count=0;
k++;
}
else
{
count++;
}
if(count==5)
break;
m++;
if(m==5)
m=0;
}
//若所有进程的*(Finish+i)==true,表示系统处于安全状态
for(i=0;i
{
if(*(Finish+i)!
=true)
{
flag2=0;
break;
}
else
{
flag2=1;
}
}
delete[]Work;
delete[]Finish;
//若系统处于安全状态,则输出存在的安全序列,否则安全检测算法结束
if(flag2==1)
{
cout<<"存在安全序列:
";
for(i=0;i
cout<<"P"<<*(list+i)<<"";
cout<delete[]list;
returntrue;
}
else
{
returnfalse;
}
}
intmain()
{
intp=5,r=3;//进程数为5,资源数为3
//Max为5*3的最大需求矩阵,Available为可利用资源向量,
//Allocation为5*3的分配矩阵,Need为5*3的需求矩阵,请求向量Request1
int*Max,*Available,*Allocation,*Need,*Request1;
Max=newint[p*r];
Available=newint[r];
Allocation=newint[p*r];
Need=newint[p*r];
Request1=newint[r];
//初始化Max矩阵
//753
//322
//902
//222
//433
*(Max+0*r+0)=7;*(Max+0*r+1)=5;*(Max+0*r+2)=3;
*(Max+1*r+0)=3;*(Max+1*r+1)=2;*(Max+1*r+2)=2;
*(Max+2*r+0)=9;*(Max+2*r+1)=0;*(Max+2*r+2)=2;
*(Max+3*r+0)=2;*(Max+3*r+1)=2;*(Max+3*r+2)=2;
*(Max+4*r+0)=4;*(Max+4*r+1)=3;*(Max+4*r+2)=3;
//初始化Allocation矩阵
//010
//200
//302
//211
//002
*(Allocation+0*r+0)=0;*(Allocation+0*r+1)=1;*(Allocation+0*r+2)=0;
*(Allocation+1*r+0)=2;*(Allocation+1*r+1)=0;*(Allocation+1*r+2)=0;
*(Allocation+2*r+0)=3;*(Allocation+2*r+1)=0;*(Allocation+2*r+2)=2;
*(Allocation+3*r+0)=2;*(Allocation+3*r+1)=1;*(Allocation+3*r+2)=1;
*(Allocation+4*r+0)=0;*(Allocation+4*r+1)=0;*(Allocation+4*r+2)=2;
//初始化可利用资源向量Available
//332
*(Available+0)=3;*(Available+1)=3;*(Available+2)=2;
//初始化Need矩阵,c-a
for(inti=0;i
{
*(Need+i)=*(Max+i)-*(Allocation+i);
}
//打印初始化数据
cout<<"T0时刻的系统资源分配情况:
"<print(Max,Allocation,Need,Available,p,r);
//p1请求资源矩阵为Request1(1,0,2)
*(Request1+0)=1;*(Request1+1)=0;*(Request1+2)=2;
cout<<"P1进程的请求向量为:
";
for(intj=0;j{
cout<<*(Request1+j)<<"";
}
cout<//请求资源数与最大需求资源数进行逐一比较
intflag=0;
for(inti=0;i{
if(*(Request1+i)>*(Need+1*r+i))
{
flag=0;
break;
}
else
{
flag=1;
}
}
//若请求资源数小于最大需求资源数,则进行资源分配判断,否则算法结束
if(flag==1)
{
//请求资源数与剩余资源数进行逐一比较
intflag2=0;
for(inti=0;i{
if(*(Request1+i)>*(Available+i))
{
flag=0;
break;
}
else
{
flag2=1;
}
}
//若请求资源数小于最大需求资源数,则进行试探分配,否则算法结束
if(flag2==1)
{
//系统试探着进行资源分配
for(inti=0;i{
*(Available+i)-=*(Request1+i);
*(Allocation+1*r+i)+=*(Request1+i);
*(Need+1*r+i)-=*(Request1+i);
}
//试探分配完成后,对该状态进行安全检测,若通过检测,则分配,
//否则本次试探分配作废,恢复原来资源分配状态
if(checkSafe(Need,Allocation,Available,p,r))
{
cout<<"分配资源后系统处于安全状态,可进行分配!
"<//打印分配后的数据
cout<<"为进程分配资源后,T1时刻系统资源分配情况:
"<print(Max,Allocation,Need,Available,p,r);
cout<<"";
cout<<"程序测试BY:
金凯"<cout<<"";
cout<<"测试结果:
符合银行家算法,可以防止死锁"<}
else
{
cout<<"分配资源后系统处于不安全状态,系统不分配该资源!
"<//本次试探分配作废,恢复原来资源分配状态
for(inti=0;i{
*(Available+i)+=*(Request1+i);
*(Allocation+1*r+i)-=*(Request1+i);
*(Need+1*r+i)+=*(Request1+i);
}
}
}
else
{
cout<<"请求资源出错,无足够资源可分配!
"<}
}
else
{
cout<<"请求资源出错,请求资源数不能大于需求资源数!
"<}
delete[]Max;
delete[]Available;
delete[]Allocation;
delete[]Need;
delete[]Request1;
return0;
}
注解:
该程序用的数据是教材上面给出的,为证明特殊性我在下面的运行中先输出一次原始数据,然后修改p1的请求资源数,进行了一次无法分配的输出。
修改这一段程序:
//p1请求资源矩阵为Request1(1,0,2)
*(Request1+0)=1;*(Request1+1)=0;*(Request1+2)=2;
修改为:
*(Request1+0)=2;*(Request1+1)=0;*(Request1+2)=2;
运行程序后报错:
告诉说无法分配!
即验证了该程序的有效性。
5.心得体会:
通过本次实验,我对于银行家算法有了更详尽的认识。
死锁避免方法能支持更多的进程并发执行,让在可行的情况下让进程充分利用资源,而是动态的确定是否分配资源给提出请求的进程。
在这个算法中如果一个资源的分配会导致下一步死锁,系统便拒绝本次分配。
在编程的过程中发现会用到大量的指针,用指针来操作大量的数据比较方便,但最后应该记得释放资源。
从这次实验中我发现我对于c++掌握也有所不足,程序经过了多次修改才得以完善,在以后应该注重编程方面的训练。