为了处理死锁的问题,即避免死锁,引入了安全序列的思想,所谓安全序列,就是指系统按照某种序列分配资源,则每个进程都能顺利完成,只要找出一个安全序列,系统就处于安全状态。
系统处于安全状态时一定不会发生死锁;系统处于不安全状态可能会发生死锁;
但系统发生死锁时必然处于不安全状态!
因此在分配资源之前先判断这次分配是否会导致系统进入不安全状态,以此决定是否答应该进程的资源分配请求,这就是银行家算法的思想
假设系统中有n个进程、m种资源
用n*m表示进程与该进程所申请资源的矩阵,。同理用n*m的分配矩阵表示对所有进程的资源分配情况
设资源总数数组Available【】为10,5,7,的一个一维向量数组,各进程最开始所需构成的矩阵设为MAX矩阵
在满足进程需求之前,系统会先给各个进程分配一点资源,当然不会直接分配完
则Allocation矩阵表示系统分配的资源
所以MAX[I][J]-ALLOCATION【I】【J】=Need[i][j];
Need矩阵表示各个进程此时还需要的资源
假设p1进程的MAX=7,5,3系统分配给他的Allocation=0,1,0;此时系统资源还剩下3,3,2,显然满足不了p1的需求,但此时Available可满足p2与p3的Need,所以先分配给他们
此时AVAILABLE=(3,3,2)-Need(1,2,3)=(2,1,0)p2得到满足
MAX(3,2,2)+Available(2,1,0)=(5,3,2)以此类推
涉及到的数据结构:
长度为m的一维数组Available表示系统中还有多少可用资源;
n*m矩阵MAX表示各进程对资源的最大申请数;
n*m矩阵Allocation表示系统已经先给各个进程分配的资源;
MAX-Allocation=Need矩阵,表示现在各进程最多还需多少资源;
用长度为m的一维数组Request表示此次申请的各种资源数;
可用银行家算法预判本次分配是否令系统处于不安全状态;
核心思想:
如果 Request[j]<=Need[i][j](0<=j<=m) 便执行下一步;
如果 Request[j]<=Allocation[j] 便执行下一步,否则表示 尚无申请资源,pi进程进入等待
前两部确认无误后,执行算法:
Available-=Available-Request;
Allocation[i][j]=Allocation[i][j]+Request[j];
#include<pch.h>
#include<stdlib.h>
#include<stdio.h>
#define False 0
#define True 1
/*****数据结构 ****/
char NAME[100] = { 0 };//系统资源总数数组
int MAX[100][100] = { 0 };//各进程最大需求量矩阵
int Allocation[100][100] = { 0 };//系统事先分配给各进程的资源数矩阵
int Available[100] = { 0 };//目前可用资源矩阵
int Need[100][100] = { 0 };//进程还需要资源矩阵
int Request[100] = { 0 };//进程请求资源向量
int Work[100] = { 0 };//存放系统可提供资源量
int Finish[100] = { 0 };//标记系统是否有足够的的资源分配给各个进程
int Security[100] = { 0 };//存放安全序列
int M = 100;//进程最大数(矩阵的列)
int N = 100;//资源最大数 (矩阵的行)
/*****初始化数据:输入进程数量、资源种类、各种资源可利用数量******/
int i, j;
int m, n;
int number, flag;
char name;//输入资源名称
int temp[100] = { 0 };//统计已经分配的资源数量
//输入系统的总资源数目以及各资源初需个数
printf("系统可用资源种类为:");
scanf("%d", &n);//矩阵行
N = n;
for (i = 0; i < n; i++)
{
printf("资源种类%d的名称", i);
fflush(stdin);//清空输入流入缓冲区的字符
scanf("%c", &name);//随便起名
NAME[i] = name;
printf("资源%c的初始个数为:", name);
scanf("%d", &number);
Available[i] = number;
}
//输入进程数以及各个进程所需的最大资源矩阵
printf("\n请输入进程的数量");
scanf("%d", &m);//矩阵列
M = n;
printf("请输入各进程的最大需求矩阵的值【MAX】:\n");
do {
flag = False;
for (i = 0; i < M; i++)
for (j = 0; j < N; j++) {
scanf("%d", &MAX[i][j]);
if (MAX[i][j] > Available[j])
flag = True;
}
if (flag)
printf("资源的最大需求量大于系统总资源量,请从新输入!\n");
} while (flag);
do
{
flag = False;
printf("请输入各进程已被提前分配的资源数量[Allocation]:\n");
for (i = 0; i < M; i++)
{
for (j = 0; j < N; j++)
{
scanf("%d", &Allocation[i][j]);
if (Allocation[i][j] > MAX[i][j])
flag = True;
Need[i][j] = MAX[i][j] - Allocation[i][j];
temp[j] = temp[j] + Allocation[i][j];/***统计已经分配给各个进程的资源数目*/
}
}
if (flag)
printf("事先分配的资源大于系统总资源,请从新输入!\n");
while (flag);
/**求得系统中目前可利用的资源数量*/
for (j = 0; j < N; j++) {
Available[j] = Available[j] - temp[j];/**/
/
}
/******显示资源分配矩阵*****/
void showdata();/**/
{
int i, j;
printf("***************************\n");
printf("系统目前可用的资源【available】:\n");
for (i = 0; i < N; i++)
printf("%c", NAME[i]);
printf("\n");
printf("系统当前分配的资源如下:\n");
printf(" MAX Allocation Need\n");
printf("进程名 ");
//输出与当前进程同行的资源名MAX,Allocation,Need分别对应如下
for (j = 0; j < 3; j++)
{
for (i = 0; i < N; i++)
{
printf("%c", NAME[i]);
printf(" ");
}
printf("\n");
/**输出每个进程的MAX,Allocation,Need;*/
for (i = 0; i < M; i++)
printf("P%d ", i);
for (j = 0; j < N; j++)
printf("%d ", MAX[i][j]);
printf(" ");
for (j = 0; j < N; j++)
printf("%d", Allocation[i][j]);
printf(" ");
for (j = 0; j < N; j++)
printf("%d", Need[i][j]);
} printf("\n");
}
/********尝试分配资源*****/
int test(int i);//试探性的将资源分配给第i个进程;
{
for (j = 0; j < N; j++)
{
Available[j] = Available[j] - Request[j];
Allocation[i][j] = Allocation[i][j] + Request[j];
Need[i][j] = Need[i][j] - Request[j];
}
return(void)True;
}
/********试探性分配资源作废*********/
int Retest(int i);//与test操作相反;
{
for (j = 0; j < N; j++) {
Available[j] = Available[j] + Request[j];
Allocation[i][j] = Allocation[i][j] - Request[j];
Need[i][j] = Need[i][j] + Request[j];
}
return(void)True;
}
/**********安全性算法***********/
int safe();
{
int i;
int j;
int k = 0;
int m;
int apply;
//初始化work:存放系统可提供资源量数组
for (j = 0; j < N; j++)
Work[j] = Available[j];
//初始化finish :标志数组,标志系统现在是否有足够的资源提供给进程
for (i = 0; i < M; i++)
Finish[i] = False;
//开始求得安全序列
for (i = 0; i < M; i++) {
apply = 0;
for (j = 0; j < N; j++)
{
if (Finish[i] == False && Need[i][j] <= Work[j])
{
apply++;
//一直到每类资源需求数都小于系统可分配资源数才开始分配,否则一直循环等待
if (apply == N) {
for (m = 0; m < N; m++)
Work[m] = Work[m] + Allocation[i][m];//更改当前可分配资源
Finish[i] = True;
Security[k++] = 1;
i = 1; //保证每次查询都从第一个进程开始
}
}
}
}
for (i = 0; i < M; i++)
{
if (Finish[i] == False)
{
printf("系统处于不安全序列");// 剩余的可利用系统总资源数无法满足剩下任意进程的Need;进入不安全序列
return (void)False;
}
else {
printf("系统是安全的!\n");
printf("存在一个安全序列:");
for (i = 0; i < M; i++)
{
printf("P%d", Security[i]); //输出运行在安全序列的数组
if (i < M - 1)
printf("->");
}
printf("\n");
return (void)True;
}
}
/************利用银行家算法对申请资源尝试进行分配****************/
void bank();// 分配资源函数
{
int flag = True;//标志变量,判断能否进入银行家算法的下一步
int i;
int j;
printf("请输入进程P%d要申请的资源个数\n", i);
for (i = 0; i < N; i++)
{
printf("%c", NAME[j]);
scanf("%d", &Request[j]);//输入要申请的资源
}
//下面判断银行家算法的两条前提是否成立
for (j = 0; j < N; j++)
{
if (Request[j] > Need[i][j])//判断进程的申请资源数是否大于其需求数,大于则出错,无法进行下一步
{
printf("进程P%d申请的资源数大于系统目前可利用数", i);
printf("分配不合理,不予分配!");
flag = False;
break;
}
else {
if (Request[j] > Available[j])//判断申请是否大于当前可分配的资源,若大于则出错
printf("进程%d的申请资源数大于目前可用资源数", i);
printf("\n");
printf("系统尚无足够资源,不予分配!\n");
flag = False;
break;
}
}
}
//当前两个条件成立的情况下才可以尝试分配资源,然后再寻找安全序列
if (flag)
{
test(i);//根据进程需求数量试探性的分配资源
showdata(); //根据进程需求数量显示分配后的资源
if (safe()) //寻找安全数列
{
Retest(i);
showdata();
}
}
}
int main();
{//主函数
char choice;
printf("\t----------------------------------------------\n");
printf("\t|| //\n");
printf("\t|| 银行家算法的实现 //\n");
printf("\t|| //\n");
printf("\t|| //\n");
printf("\t|| 在此输入个人姓名:*****//\n");
printf("\t|| //\n");
printf("\t----------------------------------------------\n");
int();//初始化数据
showdata();//显示各种资源
if (!safe())
exit(0);
do
{
printf("********************************************\n");
printf("\n");
printf("\n");
printf("\t-----------银行家算法演示-----------------\n");
printf(" R(r):请求分配 \n");
printf(" E(e):退出 \n");
printf("\t------------------------------------------\n");
printf("请选择: ");
fflush(stdin);//还是清空输入缓冲区的字符
scanf("%c", choice);
switch (choice)
{
case 'r':
case 'R':
void bank();
break;
case 'e':
case 'E':
exit(0);
default: printf("请正确做出您的选择!\n");
break;
}
} while (choice);
}
}