银行家算法是操作系统课程里面为数不多的几个算法之一,理解银行家算法对理解进程的死锁有很大的帮助。而银行家算法本身并没有太复杂的计算,只是在理解上有一个问题稍微难一点。
算法在执行过程中要求
1:每次在“未执行完”进程中找到一个可以满足要求的进程来执行
2:如果当前状态下所有进程都能够执行完,才表示该状态是安全的。
上面的第二点比较容易被忽视。下面是算法源码,源码中注释比较多,在这里就不啰嗦了。
#include
"
StdAfx.h
"
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
#include
"
Afx.h
"
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
#define
MAX_PROCESSES 10
//
最大进程数目
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
//
查找一个可执行完进程,并返回进程编号,返回 -1 表示没有进程可以执行
//
nPn ---- 进程数目
//
pA ---- 进程已申请资源数
//
pM ---- 进程请求的最大资源数
//
nL ---- 当前剩余的资源数目
//
finished ---- 已经执行完成的进程
static
int
S_PreExcute(
int
nPn,
const
int
*
pA,
const
int
*
pM,
int
nL,
const
int
*
finished)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
for (int i=0; i<nPn; i++)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if (!finished[i] && // 第一个条件:进程没有执行完
(pM[i]-pA[i]) <= nL) // 第二个条件:剩余资源可以满足该进程的执行
return i;
}
return -1;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
//
判断当前的状态是否安全,同时给出安全序列
//
返回值:返回当前能够执行完的进程数目。
//
nPn ---- 进程数目
//
pA ---- 进程已申请资源数
//
pM ---- 进程请求的最大资源数
//
nT ---- 系统中所有资源数
//
safety_seq ---- 进程执行的安全序列
int
S_SafeTest(
int
nPn,
const
int
*
pA,
const
int
*
pM,
int
nT,
int
*
safety_seq)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
int nFN = 0; // 已执行完的进程数量
int *finished = new int[nPn]; // 进程能执行完标志
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
int nL = nT; // 系统剩余资源数
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
for (int i=0; i<nPn; i++)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
finished[i] = FALSE; // 初始化进程"能执行完"标志
nL -= pA[i]; // 初始化系统剩余资源数
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
while (nFN < nPn)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
// 找到一个可执行完进程
int nPid = S_PreExcute(nPn, pA, pM, nL, finished);
if (nPid < 0) // 查找失败
break;
else // 查找成果
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
nL += pA[nPid]; // 修改剩余资源数
safety_seq[nFN++] = nPid; // 添加到安全序列
finished[nPid] = TRUE; // 修改进程执行完标志
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
delete []finished;
return nFN;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
void
Test_BanksAlgorithm_single()
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
int T = 10; // 系统拥有的资源数
#define PN 3 // 系统中进程数
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
int A[PN] = ...{2, 3, 3}; // 进程已申请资源数
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
int M[PN] = ...{4, 8, 6}; // 进程最大需求资源数
int SQ[PN]; // 安全序列
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
int fn = S_SafeTest(PN, A, M, T, SQ);
if (fn == PN)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
printf("Status Safety! Safety Sequence: ");
for (int i=0; i<fn; i++)
printf("%d ", SQ[i]);
printf(" ");
}
else
printf("Status Unsafety! ");
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)