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