操作系统:预防进程死锁的银行家算法

 

目的:陆续整理近一年的学习收获

                                          预防进程死锁的银行家算法

一:概念

 

  • 死锁概念:一组进程中,每个进程都无限等待被该组进程中另一进程所占有的资源,因而永远无法得到该资源,这种现象称为进程死锁(Deadlock),这一组进程就称为死锁进程。
  • 死锁产生的原因:
  1. 竞争资源引起进程死锁(资源分配策略)(可剥夺和非剥夺资源)
  2. 进程推进顺序不当引起死锁
  • 死锁的四个必要条件:
  1. 互斥条件设计的资源是非共享的
  2. 不可抢占条件不能强行剥夺进程拥有的资源
  3. 请求和保持条件进程在等待一新资源时继续占有已分配的资源
  4. 环路条件存在一种进程的循环链,链中的每一个进程已获得的资源同时被下一个进程所请求
  • 处理死锁的方法:
  1. 预防死锁:通过设置某些限制条件,去破坏死锁四个必要条件中的一个或多个,来防止死锁。
  2. 避免死锁:不事先设置限制条件去破坏产生死锁的条件,而是在资源的动态分配过程中,用某种方法去防止系统进入不安全状态,从而避免死锁的发生。
  3. 检测死锁:允许死锁发生,但可通过检测机构及时检测出死锁的发生,并精确确定与死锁有关的进程和资源,然后采取适当措施,将系统中已发生的死锁清除掉。
  4. 解除死锁:与检测死锁相配套,用于将进程从死锁状态解脱出来。常用的方法是撤消或挂起一些进程。以回收一些资源,再将它们分配给处于阻塞状态的进程,使之转为就绪状态
  • 避免死锁——银行家算法中的数据结构:
  1. 可利用资源向量Available:是一个含有m个元素的数组,其中的每一个元素代表一类可利用的资源数目,其初始值是系统中所配置的该类全部可用资源的数目,其数值随该类资源的分配和回收而动态地改变。如果Available[j]=K,则表示系统中现有Rj类资源K个。
  2. 最大需求矩阵Max:这是一个n×m的矩阵,它定义了系统中n个进程中的每一个进程对m类资源的最大需求。如果Max[i,j]=K,则表示进程i需要Rj类资源的最大数目为K。
  3. 分配矩阵Allocation:这也是一个n×m的矩阵,它定义了系统中每一类资源当前已分配给每一进程的资源数。如果Allocation[i,j]=K,则表示进程i当前已分得Rj类资源的数目为K。
  4. 需求矩阵Need:这也是一个n×m的矩阵,用以表示每一个进程尚需的各类资源数。如果Need[i,j]=K,则表示进程i还需要R j类资源K个,方能完成其任务。
  5. 上述三个矩阵间存在下述关系:Need[i, j]=Max[i, j]-Allocation[i, j]
  • 银行家算法:

  设Request i是进程Pi的请求向量,如果Request i[j]=K,表示进程P i需要K个R j类型的资源。当Pi发出资源请求后,系统按下述步骤进行检查:

  1. 如果Request i[j]≤Need[i,j],便转向步骤(2);否则认为出错,因为它所需要的资源数已超过它所宣布的最大值。
  2. 如果Requesti[j]≤Available[j],便转向步骤(3);否则,表示尚无足够资源,Pi须等待。
  3. 系统试探着把资源分配给进程Pi,并修改下面数据结构中的数值
  4. 系统执行安全性算法,检查此次资源分配后系统是否处于安全状态。若安全,才正式将资源分配给进程Pi,以完成本次分配;否则,将本次的试探分配作废,恢复原来的资源分配状态,让进程Pi等待。

修改值操作:Available[j]:= Available[j]-Requesti[j];
                     Allocation[i,j]:= Allocation[i,j]+Requesti[j];
                     Need[i,j]:= Need[i,j]-Request i[j];

  • 安全性算法

系统所执行的安全性算法可描述如下:

  1. 设置两个向量:第一个是工作向量Work,它表示系统可提供给进程继续运行所需的各类资源数目,它含有m个元素,在执行安全算法开始时,Work:=Available。第二个是Finish,它表示系统是否有足够的资源分配给进程,使之运行完成。开始时先做Finish[i]:=false;当有足够资源分配给进程时,再令Finish[i]:=true。
  2. 从进程集合中找到一个能满足下述条件的进程:①Finish[i]=false;②Need[i,j]≤Work[j];若找到,执行步骤(3),否则,执行步骤(4)。
  3. 当进程Pi获得资源后,可顺利执行,直至完成,并释放出分配给它的资源,故应执行: Work[j]:= Work[j]+Allocation[i,j];                                                                                                                                                         Finish[i]:=true;                                                                                                                                                                                      go to step (2);
  4. 如果所有进程的Finish[i]=true都满足,则表示系统处于安全状态;否则,系统处于不安全状态。

二:测试用例

这个例子在Abraham Silberschatz的《Operation System Concepts》上可以找到:

假设现在有5个进程P0—P1,有三种资源ABC,系统目前的资源调配情况如下面这张列表:

   操作系统:预防进程死锁的银行家算法_第1张图片

我们先通过安全状态检测算法看一看目前的系统状态是否是安全的:

因为Need[P1] < Available,所以 Available = 3 3 2 + 2 0 0 = 5 3 2, Finish[P1] = true

这时Available就成了5 3 2,继续往下找

发现Need[P3] < Available,所以 Available = 5 3 2 + 2 1 1 = 7 4 3, Finish[P3] = true

在接下来

Need[P4] < Available, Available = 7 4 3 + 0 0 2 = 7 4 5,Finish[P4] = true

Need[P0] < Available, Available = 7 4 5 + 0 1 0 = 7 5 5,Finish[P0] = true

Need[P2] < Available, Available = 7 5 5 + 3 0 2 = 10 5 7,Finish[P2] = true

算到这里Finish中所有的元素都已经置为了true,也就是说所有的进程都已经执行完毕了,目前系统处于安全状态

如果现在P1发出一个请求Request = 1 0 2

因为1 0 2既小于Need[P1]又小于Available,所以我们调用资源请求算法,计算之后的结果如下:

Available = 3 3 2 - 1 0 2 = 2 3 0

Allocation = 2 0 0 + 1 0 2 = 3 0 2

Need = 1 2 2 - 1 0 2 = 0 2 0
操作系统:预防进程死锁的银行家算法_第2张图片

用红色标出的数据就是与前一状态不同的部分

然后我们在调用安全状态检测算法检查变化后的系统是否处于安全状态就可以了,步骤和一面完全一样

 

三:程序设计

  • 定义进程结构体
typedef struct{
 char ID;//进程程名
 int Max[MaxNum];//进程所需所有资源
int Allocation[MaxNum];//进程已分配资源
int Need[MaxNum];//进程还需要资源
int Available[MaxNum];////系统可分配资源
}PRO;
  • 定义参数以及方法
static int n;//行,进程数
static int m;//列,资源数


static int Request[MaxNum];//指定执行进程所需资源
static int SafeOrder[MaxNum];//安全执行顺序

void Enter();//初始化,输入进程已分配资源、仍需资源、系统可分配资源,计算出进程所需最大资源
bool Safe();//判断当前是否安全
void banker();//银行家算法
void display();//显示结果
  • 安全性算法 
//判断当前状态是否安全
bool Safe(){
    int work[MaxNum];
    bool Finish[MaxNum];//是否安全
    for (int i=0;i P"<
  • 银行家算法
//执行银行家算法,检测执行某一进程后是否安全
void banker(){
    int i,j;
    int chooseP;


        bool RequestNeed = false;
        bool RequestAvailable = false;
        cout<>chooseP;
        cout<<"输入请求: ";
        while(RequestNeed==false){
            for (int i=0;i>Request[i];
            }
            for (i=0;i  pro[chooseP].Need[i]){
                    cout<<"所需要的资源数已超过它所宣布的最大值,请重新输入"<  pro[0].Available[i]){
                    cout<<"尚无足够资源,请重新输入"<
  •  四:实验结果

操作系统:预防进程死锁的银行家算法_第3张图片

五:实验源码

#include 
#include 
#include 
using namespace std;

#define MaxNum 20

typedef struct{
 char ID;//进程程名
 int Max[MaxNum];//进程所需所有资源
int Allocation[MaxNum];//进程已分配资源
int Need[MaxNum];//进程还需要资源
int Available[MaxNum];////系统可分配资源
}PRO;
static PRO pro[MaxNum];  //进程结构体

static int n;//行,进程数
static int m;//列,资源数


static int Request[MaxNum];//指定执行进程所需资源
static int SafeOrder[MaxNum];//安全执行顺序

void Enter();//初始化,输入进程已分配资源、仍需资源、系统可分配资源,计算出进程所需最大资源
bool Safe();//判断当前是否安全
void banker();//银行家算法
void display();//显示结果

int main(){
    Enter();
    Safe();
    banker();
    return 0;
}

//初始化,输入进程已分配资源、仍需资源、系统可分配资源,计算出进程所需最大资源
void Enter(){
    int i,j;

    cout<<"请输入进程数: ";
    cin>>n;

    cout<<"请输入资源数: ";
    cin>>m;

    //初始化进程名
    for (i=0;i>pro[0].Available[i];
    }

    cout<<"请输入Allocation: "<>pro[i].Allocation[j];
        }
    }

    cout<<"请输入 Need: "<>pro[i].Need[j];
        }
    }

    for (i=0;i P"<>chooseP;
        cout<<"输入请求: ";
        while(RequestNeed==false){
            for (int i=0;i>Request[i];
            }
            for (i=0;i  pro[chooseP].Need[i]){
                    cout<<"所需要的资源数已超过它所宣布的最大值,请重新输入"<  pro[0].Available[i]){
                    cout<<"尚无足够资源,请重新输入"<

 

你可能感兴趣的:(操作系统)