死锁的检测与解除
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
死锁的检测与解除
--操作系统实验报告
题目:死锁的检测与解除
指导老师:
班级:
姓名:
学号:
时间:
实验二 死锁的检测与解除
一、实验目的
系统为进程分配资源时并不一定能满足进程的需求,因此检测系统的安全性是非常有必要的。
安全性的检测在之前的实验中用银行家算法得以实现,此次实验增加了另一个问题:即当系统死锁时如何解除死锁。
通过此次实验,可以深刻的体会死锁的检测与解除的方法。
二、实验内容
编程实现死锁的检测与解除,并上机验证。
实验环境:Microsoft Visual Studio 2010
三、算法描述
程序中的数据结构:
1) 可用资源向量Available : 这是一个含有m 个元素的数组,其中的每一个元素代表一类可利用资源数目。
2) 最大需求矩阵Max : 它是一个n m ⨯的矩阵,定义了系统中n 个进程中得每一个进程对m 类资源的最大需求。
3) 可分配矩阵Allocation : 这也一个n m ⨯的矩阵,定义了系统中每一类资源当前已分配给每一进程的资源数。
4) 需求矩阵Need : 这表示每一个进程尚需的各类资源数。
5) 综上所述:[][][][][][]Need i j Max i j Allocation i j =-。
该程序是在银行家算法的基础上添加了死锁的解除模块得来的,死锁的解除采用的方法是:找到已分配资源最大的死锁进程,剥夺其已分配资源,再次检测是否发生死锁。
1) 设i request 是进程i P 的请求向量,如果[]i request j K =,表示进程i P 需要K 个j R 类型起源。
当i P 发出资源请求后,进行检查,如果合格,修改Available 、Allocation 、Need 的值。
2) 用安全性算法检查是否存在安全序列,如果存在,输出安全序列;如果不存在,即为死锁,进行解锁操作。
3) 统计[,]Allocation i j 的值,找出占用资源最多的进程i P ,将其撤销,回收占用的资源,修改一下的数据结构中的值:
[]:[]+[,]Available j Available j Allocation i j =;
[,]:0Allocation i j =;
用安全性算法进行检查,如果仍有死锁,重复步骤3,知道解锁为止。
4) 输出安全序列。
程序主要包括四大模块,一是输入数据模块,二是资源请求模块,三是检测死锁模块,四是对死锁进行解除模块。
程序流程图如下:
否
四、程序清单及简单注释
// 死锁的检测与解除.
#include<iostream>
#include<stdio.h>
#include<iomanip>
#define TRUE 1
#define FALSE 0
using namespace std;
int number=0;//定义全局变量,number为请求资源的进程号
int num=0;//num为安全序列中进程的个数
int Input();
int output();
//******输出未解锁之前的资源分配情况*******
int output(int **max,int **need,int *work,int **allocation,int m,int n)
{ int i,j,mark=1;
cout<<"该时刻的资源分配情况如下:"<<endl;
cout<<endl;
cout<<" 各个矩阵:| max | allocation | need | available |"<<endl;
cout<<endl;
cout<<"Process | Rescource | ";
for(i=0;i<4;i++)
{
for(j=0;j<n;j++)
{
cout<<"["<<j<<"]";
cout<<" ";
}
cout<<"| ";
}
cout<<endl;
cout<<endl;
cout<<"-----------------------------------------------------------"<<endl;
for(i=0;i<m;i++)
{
cout<<" P["<<i<<"] ";
cout<<"| ";
for(j=0;j<n;j++)
{
cout<<max[i][j]<<" ";
}
cout<<"| ";
for(j=0;j<n;j++)
{
cout<<allocation[i][j]<<" ";
}
cout<<"| ";
for(j=0;j<n;j++)
{
cout<<need[i][j]<<" ";
}
cout<<"| ";
if(mark==1)
{
for(j=0;j<n;j++)
{
cout<<work[j]<<" ";
}
cout<<"| ";
mark=0;
}
cout<<endl;
}
cout<<endl;
getchar();
return 0;
}
//********输出解锁之后的资源分配情况***********
int output2(int **need,int **allocation,int *work,int *ss,int *finish,int *p,int m,int n) { int i,j,mark=1,tag;
cout<<"该时刻的资源分配情况如下:"<<endl;
cout<<endl;
cout<<" 各个矩阵:| need | allocation | work | wor+allocation | finish |"<<endl;
cout<<endl;
cout<<"Process | Rescource | ";
for(i=0;i<4;i++)
{
for(j=0;j<n;j++)
{
cout<<"["<<j<<"]";
cout<<" ";
}
cout<<"| ";
}
cout<<endl;
cout<<endl;
cout<<"-----------------------------------------------------------"<<endl;
for(i=0;i<num;i++)
{
tag=ss[i];
cout<<"P["<<tag<<"] ";
cout<<"| ";
for(j=0;j<n;j++)
cout<<need[tag][j]<<" ";
cout<<"| ";
for(j=0;j<n;j++)
cout<<allocation[tag][j]<<" ";
cout<<"| ";
for(j=0;j<n;j++)
cout<<work[j]<<" ";
cout<<"| ";
for(j=0;j<n;j++)
{
cout<<work[j]+allocation[tag][j]<<" ";
work[j]=work[j]+allocation[tag][j];
}
cout<<"| ";
if(finish[tag]=1)
cout<<"TRUE"<<" ";
else
cout<<"FALSE"<<" ";
cout<<"| ";
cout<<endl;
}
getchar();
return 0;
}
//*************输入所有相关的信息*************
int Input(int **max,int **need,int *work,int **allocation,int *available,int *request,int m,int n,int flag)
{
int j;
cout<<"请输入请求资源的进程号:";
cin>>number;
cout<<endl;
if(number>=n)
{
return FALSE;
}
else
{
for(j=0;j<n;j++)
{
cout<<"进程P["<<number<<"]对["<<j<<"]类资源的请求数为:";//输入请求向量request
cin>>request[j];
cout<<endl;
}
for(j=0;j<n;j++)
{
if(request[j]>need[number][j]||request[j]>available[j])//判断请求向量的合法性flag=FALSE;
}
return flag;
}
}
//***********可用资源与需求矩阵的比较************
int check(int **need,int *work,int N,int i)
{
int j,c=0;
for(j=0;j<N;j++)
{
if(need[i][j]>work[j])
{
c++;}
}
if(c>0) return FALSE;
else if(c==0) return TRUE;
}
//*******************系统安全性的检测******************
int judge(int **need,int *work,int **allocation,int *finish,int *p,int *ss,int m,int n) { int i,j,k=0,count=0,flag=TRUE,mark=0,tag=0;
while(flag==TRUE)
{ flag=FALSE;
for(i=0;i<m;i++)
{
if(finish[i]==FALSE&&check(need,work,n,i)==TRUE)
{
for(j=0;j<n;j++)
work[j]=work[j]+allocation[i][j];//进程请求成功,完成作业后回收allocation的资源
finish[i]=TRUE;
p[i]=TRUE;
flag=TRUE;
ss[tag++]=i;//存储进程,用于输出安全序列
break;
}
}
}//while(flag==TRUE)
if(flag==FALSE)
{
for(i=0;i<m;i++)
if(finish[i]==FALSE)
{
k++;
}
}
if(k>0)
{
cout<<endl;
cout<<"检测结果:存在死锁进程!"<<endl;
cout<<endl;
return FALSE;
}
if(k==0)
{ cout<<endl;
cout<<"检测结果:不存在死锁进程!"<<endl;
cout<<endl;
cout<<"输出安全序列为:";
for(i=0;i<tag;i++)
cout<<"P["<<ss[i]<<"]"<<" ";
cout<<endl;
getchar();
cout<<endl;
return TRUE;
}
}
//********************解锁***********************
void unlock(int **need,int *available,int *work,int **allocation,int *finish,int *p,int *ss,int m,int n)
{
//统计死锁进程的资源数,找出最大的死锁进程,进行撤销
int *sum=new int[m],i,j,k=0,count2=0,flag;
int *temp=new int[n];//用于暂存work数组里的值,间接调用request函数
for(i=0;i<n;i++)
temp[i]=work[i];
for(i=0;i<m;i++)
{
if(finish[i]==FALSE)
{
for(j=0;j<n;j++)
sum[i]=sum[i]+allocation[i][j];//寻找占用资源最多的进程
}
}
count2=sum[0];
for(i=0;i<m;i++)
{
if(sum[i]>count2)
{
count2=sum[i];
k=i; //k标记的数组位置即为已分配资源最多的进程
}
}
cout<<"撤销占用资源最大的进程P["<<k<<"]"<<endl;
for(i=0;i<n;i++)
{
work[i]=work[i]+allocation[k][i];
}
finish[k]=TRUE;//完成对该进程的操作
p[k]=FALSE;//不再对该进程进行判断
num--;
flag=judge(need,work,allocation,finish,p,ss,m,n);//再次进行判断是否存在安全序列
if(flag==TRUE)
{
cout<<endl;
cout<<"成功解除死锁!"<<endl;
output2(need,allocation,work,ss,finish,p,m,n);
for(i=0;i<n;i++)
{
allocation[number][i]=allocation[number][i]-available[i]+temp[i];
need[number][i]=need[number][i]+available[i]-temp[i];
}//恢复请求进程原始的资源分配
finish[k]=FALSE;//初始化对该进程的操作
p[k]=TRUE;//初始化对该进程进行判断
num++;//恢复撤销进程之前的情况
for(j=0;j<n;j++)
work[j]=available[j];//初始化work数组
cout<<endl;
getchar();
}
else
unlock(need,available,work,allocation,finish,p,ss,m,n);
}
//*******************主函数***************
void main()
{
int i,j,m,n,count=0,s=0;
int flag=FALSE;
char name;
cout<<endl<<endl<<"\t\t\t\t死锁的检测与解除"<<endl<<endl;
cout<<"请输入进程数m:";
cin>>m;
num=m;
cout<<endl;
cout<<"请输入资源数n:";
cin>>n;
cout<<endl;
int **max=new int *[m];
int **need=new int *[m];
int **allocation=new int *[m];
int *request=new int[n];
int *available=new int[n];
int *finish=new int[m];
int *p=new int[m];
int *work=new int[n];
int *ss=new int[m];
for(i=0;i<m;i++)
{
max[i]=new int[n];
need[i]=new int[n];
allocation[i]=new int[n];
}
cout<<"请输入各个进程对各种资源的最大需求max:"<<endl;
cout<<endl;
for(i=0;i<m;i++)
for(j=0;j<n;j++)
{
cout<<"进程P["<<i<<"] 对["<<j<<"]类资源的最大需求为:";//输入max矩阵
cin>>max[i][j];
cout<<endl;
}
cout<<"请输入已分配的矩阵allocation:"<<endl;
cout<<endl;
for(i=0;i<m;i++)
for(j=0;j<n;j++)
{
cout<<"进程P["<<i<<"] 已分配到的["<<j<<"]类资源为:";//输入allocation 矩阵
cin>>allocation[i][j];
if(allocation[i][j]>max[i][j])
{
cout<<endl;
cout<<"输入数据大于最多需求数,重新输入!"<<endl;
j--;
}
else need[i][j]=max[i][j]-allocation[i][j];
cout<<endl;
}
cout<<"请输入可分配的资源available:"<<endl;
cout<<endl;
for(i=0;i<n;i++)
{
cout<<"["<<i<<"]类可分配的资源为:";//输入available向量
cin>>available[i];
work[i]=available[i];
cout<<endl;
}
for(i=0;i<m;i++)
{
finish[i]=FALSE;//输入finsish向量
p[i]=FALSE;
}
output(max,need,work,allocation,m,n);//输出目前的资源分配情况
cout<<endl;
i=0;
while(flag==FALSE&&i<n)//进程多次请求资源
{ flag=TRUE;
for(j=0;j<n;j++)
work[j]=available[j];
for(j=0;j<m;j++)
{
ss[j]=0;
}//初始化缓存数组ss
for(j=0;j<m;j++)
{
finish[j]=FALSE;
p[j]=FALSE;
}//初始化各进程分配情况
flag=Input(max,need,work,allocation,available,request,m,n,flag);
if(flag==TRUE)
{
for(j=0;j<n;j++)
{
available[j]=available[j]-request[j];
work[j]=available[j];
need[number][j]=need[number][j]-request[j];
allocation[number][j]=allocation[number][j]+request[j];
}//修改请求资源后的资源分配情况
cout<<"输出此时的资源分配情况:"<<endl;
cout<<endl;
output(max,need,work,allocation,m,n);
flag=judge(need,work,allocation,finish,p,ss,m,n);
if(flag==TRUE)
{
output2(need,allocation,work,ss,finish,p,m,n);
}
else
{
cout<<"存在死锁进程!"<<endl;
cout<<endl;
cout<<"输出死锁的进程:";
for(i=0;i<m;i++)
{
if(finish[i]==FALSE)
cout<<"P["<<i<<"]"<<" ";
}
cout<<endl;
cout<<"是否要进行解锁!解锁请输入'Y',不解锁请输入'N':";
cin>>name;
cout<<endl;
if(name=='Y')
{
unlock(need,available,work,allocation,finish,p,ss,m,n);
}
else
{
cout<<"程序运行结束!"<<endl;
break;
}
}//else
flag=FALSE;
}
else
{
cout<<endl;
if(number<n)
{
cout<<"请求的资源数超过所拥有的资源数,进程P["<<number<<"]等待!"<<endl;
cout<<endl;
}
else
{
cout<<"不存在进程P["<<number<<"]!"<<endl;
}
}
i++;
}//while(flag==FALSE&&i<n)
getchar();
}
五、实验结果
开始输入:
输入最大需求矩阵max:
输入已分配矩阵allocation:
输入可用资源向量available:
此时资源分配情况如下:
进程P[1]请求资源:(请求成功)
进程P[1]请求资源:(请求资源数超过可用资源)
进程P[2]请求资源:(发生死锁)
检测到死锁产生,进行解锁:
如果一次解锁不成功,则继续剥夺下一个已分配资源最多的死锁进程的资源,直到死锁解除。
经检查,实验结果符合要求。
六、实验小结
通过这次实验,我对死锁的各方面理解都有了更深层次的认识。
一开始,对于死锁的解除,我只是从第一个进程开始剥夺其资源,也不管它是不是发生了死锁,一直剥夺到死锁解除为止。
然后,我又对程序进行改进,让其可以判断死锁进程与非死锁进程,然后从第一个死锁进程开始剥夺已分配资源。
到最后,我又对程序进一步完善,让其判断一下在死锁进程中,哪个的已分配资源最多,就先剥夺它的资源,直到死锁解除。
通过以上这几次对程序的改进,我不仅对死锁的解除有了更进一步的理解,也加深了对编程理念的认识。
一种好的编程习惯、编程理念不仅可以帮助减少工作量,更可以帮助编程人员对程序的思想进行全面理解,对程序需求进行全面理解。