原创 避免死锁银行家算法的模拟实现

2010-3-30 11:19 8221 6 7 分类: 软件与OS



实验题目:                                      机时: 4<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />


<实验一避免死锁银行家算法的模拟实现


目的与任务


银行家算法是避免死锁的一种重要方法,本实验要求用高级语言编写和调试一个简单的银行家算法程序。加深了解有关资源申请、避免死锁等概念,并体会和了解死锁和避免死锁的具体实施方法。


内容和要求


在了解和掌握银行家算法的基础上,能熟练的处理课本例题中所给状态的安全性问题,能编制银行家算法通用程序,将调试结果显示在计算机屏幕上,再检测和笔算的一致性。


具体程序的功能要求:


1.设定进程对各类资源最大申请表示及初值确定。
2.设定系统提供资源初始状况(已分配资源、可用资源)。
3.设定每次某个进程对各类资源的申请表示。
4.编制程序,依据银行家算法,决定其申请是否得到满足。



设计内容(原理图以及相关说明、调试过程、结果



requesti为进程p的请求向量,如果requesti[j]=K,表示进程p需要KRj资源。当系统发出请求后,系统按下述步骤开始检查:
1)、如果requesti[j]<=need[j],转向步骤2;否则报告出错,申请的资源已经大于它需要的最大值。
2)、如果requesti[j]<=available[j],转向步骤3;否则报告出错,尚无足够的资源。
3)、系统试探着把资源分配给p,并修改下列数据结构中的值:
           available[j]=available[j]-request[j]
           allocation[j]=allocation[j]+request[j]
            need[j]=need[j]-request[j]
4)、系统进行安全性算法,检查此次分配后,系统是否还处于安全状态,若安全,把资源分配给进程p;否则,恢复原来的资源分配状态,让进程p等待。
  安全性算法(略)



 

1.  为实现银行家算法,系统中需要设置若干数据结构,用来表示系统中各进程   的资源分配及需求情况。假定系统中有m个进程,n类资源


   进程数和资源数由程序中直接定义,


        #define  m  5     //总进程数


#define  n  4     //总资源数


 对于不同规模的进程和资源数,在程序中直接修改mn值即可。



2.   银行家算法中使用的数据结构如下:


  1)可利用资源Available.这是一个含有m个元素的数组,其中的每一个元素代表一类资源的空闲资源数目,其初值是系统中所配置的该类资源的数目,其数值随该类资源的分配和回收而动态的改变。如果Available[j]=k,表示系统中Rj类资源有k个。


  (2)最大需求矩阵Max。这是一个n*m的矩阵,它定义了系统中每一个进程对各类资源的最大需求数目。如果Max[ij]=k,表示进程Pi需要Rj类资源有k个。


  (3)分配矩阵Allocation。这是一个n*m的矩阵,它定义了系统中当前已分配给每一个进程的各类资源。如果Allocation[i,j]k, 表示进程Pi当前已分到 Rj类资源有k个。Allocation i表示进程Pi的分配向量,由矩阵Allocation的第i行构成。


  (4)需求矩阵Need。这是一个n*m的矩阵,它定义了系统中每一个进程还需要的各类资源的数目。如果Need [ij]=k,表示进程Pi需要Rj类资源有k个,才能完成任务。Need i表示进程Pi的需求量,由矩阵Need的第i行构成。


    因为数据结构中涉及变量太多,为方便起见,可以定义一个结构体,将这些矩阵都放在一起。



   struct bank               //定义结构体


{


      int Available[n];       //可利用资源向量


      int Max[m][n];        //最大需求矩阵


      int Allocation[m][n];   //分配矩阵


      int Need[m][n];       //需求矩阵


};


这样在后面的安全性检查操作中,只需要带入一个bank型变量即可,比较方便。





3. 实现过程


    主函数   


        void main(void)


{


        bank current;               //定义变量


           Initilize(current);            //初始化


           Safe_test(current);           //检查安全性


       while(1)      //循环执行进程申请资源和系统对申请的处理


       {


               Resoure_allocate(current);


       }


}   


其中用到的函数操作有三个


      void  Initilize(bank &);        //初始化


int   Safe_test(bank);         //检查安全性


void  Resoure_allocate(bank &); //系统对进程资源申请的处理



 Initilize函数是初始化变量的,即设置相关矩阵参数,由用户输入。


Safe_test函数是检查当前系统安全性的,安全则返回1,不安全返回0


Resoure_allocate函数里的操作包括:


a.进程申请资源 


b.假设系统可以响应该请求,将分配资源给该进程,修改相关数据 


c.检查系统是否安全,若安全在,则可以分配资源,若不安全,不能分配资源,并收回分配的资源。






4. 安全性检查


  程序中安全性算法的描述如下:


(1) 设置如下两个工作向量:


Work:表示系统可提供给进程继续运行的各类资源的空闲资源数目,它含有m个元素,执行安全性算法开始时,WorkAvailable


Finish:表示系统是否有足够的资源分配给进程,使之运行完成。开始时,Finishi)=false;当有足够的资源分配给进程Pi时,令Finishi)=true


(2) 从进程集合中找到一个能满足下列条件的进程:


Finishi)=false


Need i<= Work;,


如果找到了就执行步骤(3),否则执行步骤(4)。


(3) 当进程Pi获得资源后,可执行直到完成,并释放出分配给它的资源,故应执行


Work = Allocation iWork;


Finishi)=false


然后转向第(2)步骤。


(4) 若所有进程中的Finishi)都是true,则表示系统处于安全状态;否则,系统处于不安全状态。


 此过程由一个安全性检查函数实现


int Safe_test(bank x)


{


int i,j;


int safeprocess[m]; //安全序列向量


int work[n];        //空闲资源矩阵


int Finish[m];      //进程完成标志矩阵


for(i=0;i<n;i++)    //开始时可利用资源向量就是空闲资源矩阵


    work=x.Available;  


    for(i=0;i<m;i++)    //初始化标志矩阵为false


    Finish=false;


      


    int k=0;    //安全序列排列号


for(i=0;i<m;i++)       //每次都从第一个进程开始做循环


{


      if(Finish==false)


  {


for(j=0;j<n;j++)


{


if(x.Need[j]>work[j]) //判断当前进程需求矩阵能否得到满足


break;               //不满足则跳出


}  


if(j==n)      //i个进程满足执行条件


{


                    safeprocess[k++]=i;   //将进程号存入安全序列向量


for(int q=0;q<n;q++)  //修改空闲资源矩阵


   work[q]+=x.Allocation[q];


        Finish=true;       //标志该进程可完成


i=-1;     //下次检查从第一个进程重新查起


}


  }


}


    for(i=0;i<m;i++)    //检查标志数组,若有一个为false则找不到安全序列


   if(!Finish)


   { 


   cout<<"找不到安全序列,系统处于不安全状态!\n";


   return 0;


   }


cout<<"找到安全序列:";    //找到安全序列并显示该序列


for(i=0;i<m;i++)cout<<"进程"<<safeprocess+1<<" ";


cout<<"\n系统处于安全状态.\n";


return 1;


}



      


5. 对进程申请资源的处理


   当某一进程提出资源申请时,系统须做出判断,能否将所申请资源分配给该进程。


Request i是进程Pi的请求向量,Request ij)=k表示进程Pi请求分配 Rj类资源有k个。当Pi发出资源请求后,系统按照下述步骤进行检查:


(1) 如果Request i<= Need i,则转向第二步;否则出错,因为进程所需要的资源数已超过它所宣布的最大值;


(2) 如果Request i<=Available,则转向步骤(3);否则,表示系统中尚无足够的资源满足进程Pi的申请,让进程Pi等待。


(3) 假设系统把申请的资源分配给进程Pi,则对应下面的数据结构进行修改:


Available= Available Request i;


 Allocation i= Allocation iRequest i;


Need i= Need i Request i;


(4) 系统执行安全性算法,检查此次资源分配后,系统是否处于安全状态。若安全,就将资源分配给Pi,满足其资源申请要求;否则,让进程等待,并恢复原来的资源分配状态。


 整个过程由一个函数实现


      





void Resoure_allocate(bank &x)


{


bank temp=x;         //临时变量存储x的初值


int Request[n];      //请求向量


    int number;          //进程号    


int i;


cout<<"请输入要申请资源的进程序号:\n";


cin>>number;         


cout<<"请输入请求向量:\n";


    for(i=0;i<n;i++) cin>>Request; //输入请求向量


    for(i=0;i<n;i++)


{


if(Request>x.Need[number-1])   //所需资源数大于需求量


{


cout<<"进程所需要的资源数已超过它所宣布的最大值,系统不予分配资源!\n";


return ;


}


if(Request>x.Available)        //所需资源数大于可利用资源


{


            cout<<"系统中无足够的资源满足进程的申请,系统不予分配资源!\n";


return ;


}


}


    for(i=0;i<n;i++)      //假设系统将申请资源数分配给该进程,对数据进行相关修改


{


         x.Available            -= Request;


 x.Need[number-1]       -= Request;


         x.Allocation[number-1] += Request;


}


    if(Safe_test(x))    //安全性检查结果为安全


{


cout<<"系统可以为该进程分配资源.\n";


return ;


}


    else                //安全性检查结果为不安全


{


cout<<"系统不为该进程分配资源\n";


x=temp;      //将相关矩阵修改过来,表示资源不分配资源


return ;


}


}        



四 .实验结果      


【例1】某系统有ABCD4类资源供5个进程共享,进程对资源的需求和分配情况如下表所示。现在系统中ABCD类资源分别还剩1520个,请按银行家算法回答下列问题:




进程


已占资源


最大需求数


A


B


C


D


A


B


C


D


P1


0


0


1


2


0


0


1


2


P2


1


0


0


0


1


7


5


0


P3


1


3


5


4


2


3


5


6


P4


0


6


3


2


0


6


5


2


P5


0


0


1


4


0


6


5


6



(1) 现在系统是否处于安全状态


(2) 如果现在进程P2提出需要(0420)个资源的请求,系统能否满足它的请求?



运行结果












【例2】用银行家算法考虑下列系统状态 


进程   分配矩阵          最大需求矩阵       资源总数矩阵


 A    3  0  1  1         4  1  1  1         6  3  4  2


 B    0  1  0  0         0  2  1  2


 C    1  1  1  0         4  2  1  0


 D    1  1  0  1         1  1  1  1


 E    0  0  0  0         2  1  1  0


问系统是否安全?若进程B请求(0,0,1,0),可否立即分配?此后进程E也请求(0,0,1,0),可否分配给它?





运行结果:








实验小结(问题、收获和体会



在避免死锁的方法中,允许进程动态地申请资源,系统在进行资源分配之前,先计算资源分配的安全性。若此次分配不会导致系统进入不安全状态,便将资源分配给进程,否则进程等待。银行家算法是死锁避免算法中的一种,通过上面这个例子,我们看到银行家算法确实能保证系统时时刻刻都处于安全状态,但它要不断检测每个进程对各类资源的占用和申请情况,需花费较多的时间。本次实验为时两天多,总体上来说实验是比较成功的。由于时间仓促,做的不是很完美,敬请谅解。


源程序:


#include<iostream.h>


/***********************************************************************
                        数据定义与函数原型说明
***********************************************************************/
#define m 5     //总进程数
#define n 4     //总资源数


struct bank               //定义结构体
{
    int Available[n];     //可利用资源向量
    int Max[m][n];        //最大需求矩阵
    int Allocation[m][n]; //分配矩阵
    int Need[m][n];       //需求矩阵
};
void Initilize(bank &);   //初始化
int Safe_test(bank);      //检查安全性
void Resoure_allocate(bank &); //系统对进程资源申请的处理


/***********************************************************************
                            主函数
***********************************************************************/
void main(void)
{
 bank current;                  //定义变量
    Initilize(current);            //初始化
    Safe_test(current);           //检查安全性
 while(1)      //循环执行进程申请资源和系统对申请的处理
 {
      Resoure_allocate(current);
    }
}
/***********************************************************************
                             初始化
***********************************************************************/
void Initilize(bank &x)           
{
 int i,j;
    cout<<"初始化过程,输入相关数据:\n";
    cout<<"输入最大需求矩阵Max:"<<'\n'; 
 for(i=0;i<m;i++)             //设置最大需求矩阵
 {
  for(j=0;j<n;j++)
  {
   cin>>x.Max[j];
  }
 }
 cout<<"输入分配矩阵Allocation:"<<'\n';
    for(i=0;i<m;i++)              //设置分配矩阵
 {
  for(j=0;j<n;j++)
  {
   cin>>x.Allocation[j];
  }
 }
 for(i=0;i<m;i++)              //设置需求矩阵
 {
  for(j=0;j<n;j++)
  {
   x.Need[j]=x.Max[j]-x.Allocation[j];
  }
 }
    cout<<"输入可利用资源向量:"<<'\n';
 for(i=0;i<n;i++)             //设置可利用资源向量
 {
  cin>>x.Available;
 }
}
/***********************************************************************
                             检查安全性
***********************************************************************/
int Safe_test(bank x)
{
 int i,j;
 int safeprocess[m]; //安全序列向量
 int work[n];        //空闲资源矩阵
 int Finish[m];      //进程完成标志矩阵
 for(i=0;i<n;i++)    //开始时可利用资源向量就是空闲资源矩阵
     work=x.Available
    for(i=0;i<m;i++)    //初始化标志矩阵为false
     Finish=false;
     
    int k="0";    //安全序列排列号
 for(i=0;i<m;i++)       //每次都从第一个进程开始做循环
 {
       if(Finish==false)
    {
    for(j=0;j<n;j++)
    {
     if(x.Need[j]>work[j]) //判断当前进程需求矩阵能否得到满足
      break;               //不满足则跳出
    } 
    if(j==n)      //第i个进程满足执行条件
    {
                    safeprocess[k++]=i;   //将进程号存入安全序列向量
     for(int q="0";q<n;q++)  //修改空闲资源矩阵    
        work[q]+=x.Allocation[q];
           Finish=true;       //标志该进程可完成
     i=-1;     //下次检查从第一个进程重新查起
    }
    }
 }
    for(i=0;i<m;i++)    //检查标志数组,若有一个为false则找不到安全序列
    if(!Finish)
    {
     cout<<"找不到安全序列,系统处于不安全状态!\n";
     return 0;
    }
 cout<<"找到安全序列:";    //找到安全序列并显示该序列
 for(i=0;i<m;i++)cout<<"进程"<<safeprocess+1<<" ";
 cout<<"\n系统处于安全状态.\n";
 return 1;
}
/***********************************************************************
                         系统对进程资源申请的处理
***********************************************************************/
void Resoure_allocate(bank &x)
{
 bank temp="x";         //临时变量存储x的初值
 int Request[n];      //请求向量
    int number;          //进程号   
 int i;
 cout<<"请输入要申请资源的进程序号:\n";
 cin>>number;        
 cout<<"请输入请求向量:\n";
    for(i=0;i<n;i++) cin>>Request; //输入请求向量
    for(i=0;i<n;i++)
 {
  if(Request>x.Need[number-1])   //所需资源数大于需求量
  {
   cout<<"进程所需要的资源数已超过它所宣布的最大值,系统不予分配资源!\n";
   return ;
  }
  if(Request>x.Available)        //所需资源数大于可利用资源
  {
            cout<<"系统中无足够的资源满足进程的申请,系统不予分配资源!\n";
   return ;
  }
 }
    for(i=0;i<n;i++)      //假设系统将申请资源数分配给该进程,对数据进行相关修改
 {
         x.Available            -= Request;
   x.Need[number-1]       -= Request;
         x.Allocation[number-1] += Request;
 }
    if(Safe_test(x))    //安全性检查结果为安全
 {
  cout<<"系统可以为该进程分配资源.\n";
  return ;
 }
    else                //安全性检查结果为不安全
 {
  cout<<"系统不为该进程分配资源\n";
  x=temp;      //将相关矩阵修改过来,表示资源不分配资源
  return ;
 }
}       
/***********************************************************************/
                        

文章评论1条评论)

登录后参与讨论

用户377235 2012-3-12 11:16

请问,在此程序的基础上,可不可以把资源数和进程数,修改成键盘输入的?
相关推荐阅读
用户212744 2010-04-06 17:56
迷宫求解堆栈实现
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />一、上机实验的问题和要求:迷宫问题(...
用户212744 2010-03-30 11:31
c语言快速傅里叶变换
#include<stdio.h>#include <math.h>class complex                  //定义一个类,实现复数的所有操作{doubl...
用户212744 2010-03-30 11:25
先进先出FIFO页面置换算法
实验题目:                                      机时: 4<?xml:namespace prefix = o ns = "urn:schemas-micr...
用户212744 2010-03-30 11:10
二叉树简单操作
一、上机实验的问题和要求:<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />要求采用二...
用户212744 2010-03-30 11:08
循环链表求解约瑟夫环
一、上机实验的问题和要求:<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />约瑟夫环(...
我要评论
1
6
关闭 站长推荐上一条 /2 下一条