银行家算法的模拟和实现

最近在做操作系统的课程设计,其中实验四是“银行家算法的模拟和实现”。好在前面看过一点,有点印象。所以想尝试自己写一下,下面是我的编码过程以及个人的一点分享,如果有问题欢迎指出,也希望能和我一起交流。我的邮箱是:[email protected]

已同步到我的CSDN博客:https://blog.csdn.net/zimojiang/article/details/80861792

一、 什么是银行家算法?

银行家算法顾名思义就是模拟银行的借贷业务的一种算法,操作系统就相当于一个银行家,而进程就是客户,进程向操作系统请求资源、归还资源就相当于客户向银行借贷、还贷。这个应该是很好理解的。理解这个名词之后,下面我们看看具体深入一点,银行家能否给一名客户贷款的要求是什么呢?很简单:在它还款期间,整个银行要能进行正常的资金周转。如果可以,那好,就借款给它,如果不能就不借给他。恩,就这么干脆。

换做操作系统的资源分配,也是如此:操作系统能否响应一个进程的资源请求,要求是,在它归还分配的资源之前,系统能维持一个正常的资源周转。到底什么是正常的周转?你可能在想。正常的周转就是,系统现有的资源能够满足多个进程的需求。也就是系统处于一个安全的状态。

二 银行家算法的数据结构

上面的论述,对银行家算法应该有了一点模糊的印象了,下面就深入一步的探究,为了方便,下面先就介绍银行家算法的数据结构。操作系统的资源可以是很多种,不同的进程对资源的需求也不同。

n:进程的数量 m:资源的种类
定义:

名词 数据结构
分配矩阵 Allocation[n][m]
最大需求矩阵 Max[n][m]
需求矩阵 Need[n][m]
可利用资源 Available[m]
请求资源 Request[n][m]

进程i对资源j:
Allocation[i][j]表示进程 i已分配资源j的数量
Max[i][j]:表示进程i 对资源j的最大需求的数量
Need[i][j] :表示进程i对资源j剩下的需求(Max[i][j] - Allocation[i][j] )
Available[j]:对各个进程经过一番资源的分配后,资源j的数量。
Request[i][j]:进程i对资源j的请求数量。

:这里要区分请求和需求。可以这样理解,请求是动态、不确定的,进程对资源的请求有时多有时少)

三、银行家算法的流程

回到前面,先假设当前系统是处于一个正常周转的状态,这时一个进程i发出资源请求,系统能否分配给它要经历如下步骤:

  1. 进程 i 的资源请求过度了吗?要知道一个进程在最初始状态是声明了最大的资源请求的。用数据结构表示就是:Request[i][j] < Need[i][j]。如果满足就继续往下,不满足就拒绝分配。不满足,通俗讲就是此时进程i 的资源请求是过分的,撕毁条约,得寸进尺。
  2. 系统当前的资源情况能满足进程i的资源请求吗?经过步骤一,这时进程i的请求是合理的。但是这时也不能给它分配,要判断一下此时资源够不够?现在也不考虑资源周转的问题,当务之急是当前资源能否满足进程i的请求。如果可以,就继续往下,不可以则进程需要等待,直到系统有足够的资源再说。
  3. 系统处于安全状态吗?经过步骤一、二,进程 i 能否得到系统的资源分配还需要经过最后一道难关:系统将资源分配给该进程i 后,还能处于一个安全状态吗?或者说,系统还能进行正常的资源周转吗? 这个地方可以说是整个算法的重中之重了。粗略来讲:系统先尝试对该进程 i 进行资源分配,然后进行安全性检测, 如果系统安全则分配成功,否则则撤销分配。详细的过程我下面再讲。

四、银行家算法中的安全性检测

上面将的数据结构、算法流程其实都是很容易理解的,但就判断当前系统是否安全可能还懵懵懂懂:到底怎么进行安全性检测?
我觉得这部分应该是整个算法最关键的地方,只要干掉它,就OK了!
前面讲了系统先对该进程尝试进行资源分配(注意是尝试!),就会得到新的资源情况,更新的过程我们可以看看,对进程 i进行资源分配 Request[i][j],资源更新情况如下:

Need[i][j] = Need[i][j] - Request[i][j]
Allocation[i][j] = Allocation[i][j] + Request[i][j]
Available[j] = Available[j] - Request[i][j]

(0<=i

然后资源更新后的系统进行安全性检测,具体我们先看一个例子:

Process Allocation Need Available
P0 0 0 3 2 0 0 1 2 1 6 2 2
P1 1 0 0 0 1 7 5 0
P2 1 3 5 4 2 3 5 6
P3 0 3 3 2 0 6 5 2
P4 0 0 1 4 0 6 5 6

问:该状态是不是安全状态?

我们是先找出一个进程,使得系统可利用的资源能够它的所有资源需求
可以看到只有P0满足要求,就把p0加入安全队列中,然后将它以前占用的所有资源收回。这个时候,Available = Available + Allocation
即:Available: 1 6 2 2 + 0 0 3 2 = 1 6 5 4
Need中减少P0进程
Need= \begin{bmatrix} 1&7&5&0\\ 2&3 &5& 6\\ 0& 6& 5& 2\\ 0 &6 &5& 6 \end{bmatrix}
又接着找一个进程,看是否满足:系统可利用的资源满足它的所有资源需求。
可以看到,P3 Need= 0 6 5 2 满足要求,P4 Need = 0 6 5 6 也满足要求,将P3加入安全队列中。这里我们可以任意选择一个,我们选择P3,Available = Available + Allocation,将P3的分配资源Allocation归还。P3 Allocation = 0 3 3 2
所以Available: 1 6 5 4 + 0 3 3 2 = 1 9 8 6
Need= \begin{bmatrix} 1&7&5&0\\ 2&3 &5& 6\\ 0 &6 &5& 6 \end{bmatrix}
继续,可以看到P1、P4满足要求,选择P1,将P1加入安全队列中
P1 Allocation =1 0 0 0
所以Available: 1 9 8 6 + 1 0 0 0 = 2 9 8 6
Need= \begin{bmatrix} 2&3 &5& 6\\ 0 &6 &5& 6 \end{bmatrix}
可以看到P2 、P4都满足要求,选择P2,将P2加入安全队列中
P2 Allocation =1 3 5 4
所以Available: 2 9 8 6 + 1 3 5 4 =3 |12|13|10
选择P4,将P4加入安全队列中
P2 Allocation =0 0 1 4
Available:3 |12|13|10 + 0 0 1 4 =3 |12|14|14

到此为止,所有的进程都加入安全队列中,说明整个系统是处于安全状态的,如果没有进程加入安全队列中,说明系统是不安全的,可能会发生死锁,银行家算法是避免死锁而出名的一种算法,由此可见一斑。

五、尝试编程

当在(四)中描述算法的逻辑后,聪明的你应该有思路了,想尝试实现这个算法了。写完后想检测对比一下,我前面找到了一个小例子:银行家算法例子讲解
我自己按照上面的思路实现了这个算法,如果有问题,欢迎评论留言。
源代码如下,有注释。

#include 
#include
#include
#define max 50
int Allocation[max][max];
int Available[max];
int resources[max];
int Max[max][max];
int Need[max][max];
int resourcesSize;//资源总数
int processSize;//进程总数
bool isSecurity;//系统是否安全
bool checkSecurity();

void initialize()
{

    printf("请输入资源总数\n");
    scanf("%d",&resourcesSize);
    printf("输入各个资源的数量:\n");
    for(int i = 0;i Max[process][j]){
            printf("进程%d对资源%d的请求不合理,超出所宣布的最大值!",process,j);
            return false;
        }
    }
    //没有大于最大请求,但是当前系统可能还没有这么资源分配他们
    for(int j = 0;j Available[j])
            {
                printf("系统还没有足够的资源%d响应进程%d的请求",j,process);
            }
    }
    //尝试分配
    printf("尝试分配资源\n");
    for(int j = 0;j

六、总结

安全性检测这部分应该是银行家算法的重中之重了,将逻辑搞清楚应该是不难的。具体的思路是:如果找到一个进程,使得当前可利用资源(Available)能够满足它的需求(Need),就先对其分配资源,然后收回分配给它之前的资源(Allocation),接着更新Available(Available+=Allocation),然后将其加入安全性序列。继续找一个进程,重复上面操作。需要注意的是,必须要循环多次,因为前面没有符合条件的进程可能因为后面的资源更新又符合条件了。最后,临界条件是如果循环一遍后,还是找不到符合条件的进程,那么说明系统不安全,退出循环,反之如果所有的进程都加入安全性序列,就说明此系统是安全的,退出循环。
我处理的一个细节是:循环判断的时候,要跳过之前加入安全性序列的进程。

我没有注意的一点是:上面过程,要防止修改Available,需要使用一个临时数组,否则一旦判断出此系统是不安全的,Available是无法恢复的。这一点很重要!当时我就忽略了这一点。感谢博客:https://www.cnblogs.com/Lynn-Zhang/p/5672080.html。

你可能感兴趣的:(银行家算法的模拟和实现)