(操作) 调度算法实验三
实验三 银行家算法模拟实验
【实验目的】
(1)为了进一步理解利用银行家算法避免死锁的问题。
(2)在了解和掌握银行家算法的基础上,编制银行家算法通用程序,将调试结果显示在计
算机屏幕上,再检测和笔算的一致性。
(3)理解和掌握安全序列、安全性算法。
【实验内容】
用C语言编写一个简单的银行家算法模拟程序,用银行家算法实现资源分配。程序能模拟多个进程共享多种资源的情形。进程可动态地申请资源,系统按各进程的申请动态地分配资源。要求程序具有显示和打印各进程的某-时刻的资源分配表和安全序列;显示和打印各进程依次要求申请的资源数量以及为某进程分配资源后的有关资源数据的情况。
【设计思路】
银行家算法是一种最有代表性的避免死锁的算法。银行家算法即把操作系统看作是银行
家,操作系统管理的资源相当于银行家管理的资金,进程向操作系统请求分配资源相当于用户向银行家贷款。
要找出这个状态下的所有可能的安全序列,前提是要是使这个系统先处于安全状态,而
系统的状态可通过以下来描述:进程剩余申请数=最大申请数-占有数;可分配资源数=总数-占有数之和;通过这个描述来算出系统是否安全,从而找出所有的安全序列。
设Request i是进程Pi的申请向量,如果Request i[j]=K,则表示进程Pi需要K个Rj类型的资源。当Pi发出资源请求后,系统按下述步骤进行检查:
(1)如果Request i[j]<=Need[i,j],便转向步骤2);否则认为出错,因为它所需要的资源数已经超过它所宣布的最大值。
(2)如果Request i[j]<=Available[i,j],便转向步骤3);否则,表示尚无足够资源,Pi需等待。
(3)系统试探着把资源分配给进程Pi,并修改下面数据结构中的数值:
Available[j]:=Available[j]-Request i[j];
Allocation[i,j]:=Allocation[i,j]+Request i[j];
Need[i,j]:=Need[i,j]-Request i[j];
(4)系统执行安全性算法,检查此次资源分配后系统是否处于安全状态。若安全,才正式将资源分配给进程Pi,以完成本次分配;否则,将本次的试探分配作废,恢复原来的资源分配状态,让进程Pi等待。
【流程框图】
【主要程序代码】
#include<stdio.h>
#include<stdlib.h>
int Available[10];
int Max[10][10];
int Allocation[10][10] = { 0 };
int Need[10][10] = { 0 };
int Work[10];
int Finish[10];
int Request[10][10];
int Pause[10];
int arr[] = { 0 };
int List[10];
int i, j;
int n;
int m;
int a;
int l, e;
int b = 0, c = 0, f = 0, g;
int z = 0;
int securitycheck()
{
printf("\n\n");
printf("安全性检测\n");
if (n == 3)
{
printf(" 工作向量 尚需求量 已分配 工作向量+已分配\n进程 ");
for (c = 1; c <= 4; c++)
{
for (j = 1; j <= n; j++)
{
printf(" %d类", j);
}
}
}
if (n == 2)
{
printf(" 工作向量 尚需求量 已分配 工作向量+已分配\n进程 ");
for (c = 1; c <= 4; c++)
{
for (j = 1; j <= n; j++)
{
printf(" %d类", j);
}
}
}
for (i = 1; i <= m; i++)
{
Pause[i] = Available[i];
Finish[i] = false;
}
for (g = 1; g <= m; g++)
{
for (i = 1; i <= m; i++)
{
b = 0;
Finish[i] == false;
for (j = 1; j <= n; j++)
{
if (Need[i][j] <= Pause[j])
{
b = b + 1;
}
if (Finish[i] == false && b == n)
{
Finish[i] = true;
printf("\nP[%d] ", i);
for (l = 1; l <= n; l++)
{
printf(" %2d ", Pause[l]);
}
for (j = 1; j <= n; j++)
{
printf(" %2d ", Need[i][j]);
}
for (j = 1; j <= n; j++)
{
printf(" %2d ", Allocation[i][j]);
}
for (j = 1; j <= n; j++)
{
printf(" %2d ", Pause[j] + Allocation[i][j]);
}
for (l = 1; l <= n; l++)
{
Pause[l] = Pause[l] + Allocation[i][l];
}
}
}
}
}
printf("\n\n");
for (i = 1; i <= m; i++)
{
if (Finish[i] == true) f = f + 1;
}
if (f == m)
{
printf("安全状态!");
printf("\n\n系统剩余资源量: ");
for (i = 1; i <= n; i++)
{
printf(" %d ", Available[i]);
}
f = 0;
return 1;
}
else
{
printf("unsafe state ");
for (i = 1; i <= n; i++)
{
Available[i] = Available[i] + Request[a][i];
Allocation[a][i] = Allocation[a][i] - Request[a][i];
Need[a][i] = Need[a][i] + Request[a][i];
}
return 0;
}
}
void initialize()
{
printf("请输入系统的资源种类数:");
scanf("%d", &n);
for (i = 1; i <= n; i++)
{
printf("第%d类资源总数:", i);
scanf("%d", &arr[i]);
}
printf("请输入进程总数:");
scanf("%d", &m);
for (i = 1; i <= m; i++)
{
for (j = 1; j <= n; j++)
{
printf("进程P[%d]对第%d类资源的最大需求量:", i, j);
scanf("%d", &Max[i][j]);
}
}
for (i = 1; i <= m; i++)
{
for (j = 1; j <= n; j++)
{
printf("进程P[%d]对第%d类资源已分配数:", i, j);
scanf("%d", &Allocation[i][j]);
Need[i][j] = Max[i][j] - Allocation[i][j];
}
}
for (i = 1; i <= n; i++)
{
for (j = 1; j <= m; j++)
{
arr[i] -= Allocation[j][i];
}
}
for (i = 1; i <= n; i++)
Available[i] = arr[i];
securitycheck();
}
void mainrequest()
{
printf("请输入申请资源的进程:");
scanf("%d", &a);
for (i = 1; i <= n; i++)
{
printf("请输入进程P[%d]对%d类资源的申请量:", a, i);
scanf("%d", &Request[a][i]);
if (Request[a][i] > Need[a][i])
{
printf("\n出错!进程申请的资源数多于它自己申报的最大需求量\n");
return;
}
if (Request[a][i] > Available[i])
{
printf("\nP[%d]请求的资源数大于可用资源数,必须等待\n", a);
return;
}
}
for (i = 1; i <= n; i++)
{
Available[i] = Available[i] - Request[a][i];
Allocation[a][i] = Allocation[a][i] + Request[a][i];
Need[a][i] = Need[a][i] - Request[a][i];
}
int ret=securitycheck();
if (ret == 1)
{
int key = 0;
for (j = 1; j <= n; j++)
{
if (Need[a][j] == 0)
{
key++;
}
}
if (key == n)
{
for (j = 1; j <= n; j++)
{
Available[j] += Allocation[a][j];
Allocation[a][j] = 0;
}
}
}
}
void mainshow()
{
printf("\n\n");
if (n == 3)
{
printf(" 已分配 最大需求量 尚需要量 \n进程");
}
if (n == 2)
{
printf(" 已分配 最大需求 尚需要量 \n进程");
}
for (i = 1; i <= 3; i++)
{
for (j = 1; j <= n; j++)
{
printf(" %d类", j);
}
}
for (i = 1; i <= m; i++)
{
printf("\nP[%d]", i);
for (j = 1; j <= n; j++)
{
printf(" %2d ", Allocation[i][j]);
}
for (j = 1; j <= n; j++)
{
printf(" %2d ", Max[i][j]);
}
for (j = 1; j <= n; j++)
{
printf(" %2d ", Need[i][j]);
}
}
printf("\n\n系统剩余资源量: ");
for (i = 1; i <= n; i++)
{
printf(" %d ", Available[i]);
}
printf("\n");
}
void menu()
{
printf("\n 银行家算法");
printf("\n1:初始化");
printf("\n2:进程进行资源申请");
printf("\n3:资源分配状态");
printf("\n4:退出程序");
printf("\n请输入你的选择: ");
}
int main()
{
int key = 0;
printf("\n\n");
while (1)
{
menu();
scanf("%d", &key);
printf("\n\n");
switch (key)
{
case 1:
initialize();
break;
case 2:
mainrequest();
break;
case 3:
mainshow();
break;
case 4:
printf("\n\n\t谢谢使用 \n");
printf("\nSee you next time !\n");
system("pause");
return 0;
}
}
system("pause");
return 0;
}
【测试结果】
1.首先进行初始化:
2.输入相关数据:
3.显示结果:
【实验总结】
银行家算法是操作系统中避免死锁的典型算法。所谓死锁:是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。由于资源占用是互斥的,当某个进程提出申请资源后,使得有关进程在无外力协助下,永远分配不到必需的资源而无法继续运行,这就产生了一种特殊现象死锁。
通过这次实验,加深了我对银行家算法的了解,掌握了如何利用银行家算法避免死锁。在实验中,难免会遇到问题,通过自己在网上查找资料、询问同学,这些问题都得到了解决,完成了本次实验。通过这次的实验,使我的理论知识更加的牢固。