操作系统课程设计_银行家算法
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
《操作系统》课程考查试卷
课程名称(Subject):
系别(Department):
专业(Major):
姓名(Name):
学号(Student’s Number)
摘要
Dijkstra提出的银行家算法,是最具代表性的避免死锁的算法。
本文对如何用银行家算法来处理操作系统给进程分配资源做了详细的说明,包括需求分析、概要设计、详细设计、关键代码、程序运行以及总结。
首先做了需求分析,解释了什么是银行家算法,并指出它在资源分配中的重要作用。
然后给出了银行家算法的概要设计,包括算法思路、步骤,以及要用到的主要数据结构、函数模块及其之间的调用关系等。
在概要设计的基础上,又给出了详细的算法设计,实现概要设计中定义的所有函数,对每个函数写出核心算法,并画出了流程图。
接着对编码进行了测试与分析(并在最后附上c语言编写的程序代码)。
最后对整个设计过程进行了总结。
关键词:操作系统银行家算法、c语言
目录
一、设计题目.............................................................................................................................
二、设计内容.............................................................................................................................
三、设计过程.............................................................................................................................
3.1需求分析.......................................................................................................................
3.2概要设计.......................................................................................................................
3.3详细设计.......................................................................................................................
3.4关键代码.......................................................................................................................
3.5程序运行.......................................................................................................................
四、总结.....................................................................................................................................
五、参考文献.............................................................................................................................
一、设计题目
《银行家算法》
二、设计内容
操作系统的基本特征是并发与共享。
系统允许多个进程并发执行,并且共享系统的软、硬件资源。
为了最大限度的利用计算机系统的资源,操作系统应采用动态分配的策略,但是这样就容易因资源不足,分配不当而引起“死锁”。
而我本次课程设计就是得用银行家算法来避免“死锁”。
银行家算法就是一个分配资源的过程,使分配的序列不会产生死锁。
此算法的中心思想是:按该法分配资源时,每次分配后总存在着一个进程,如果让它单独运行下去,必然可以获得它所需要的全部资源,也就是说,它能结束,而它结束后可以归还这类资源以满足其他申请者的需要。
三、设计过程
3.2概要设计
银行家算法是一种最有代表性的避免死锁的算法。
要解释银行家算法,必须先解释操作系统安全状态和不安全状态。
安全状态:如果存在一个由系统中所有进程构成的安全序列P1,…,Pn,则系统处于安全状态。
安全状态一定是没有死锁发生。
不安全状态:不存在一个安全序列。
不安全状态不一定导致死锁。
那么什么是安全序列呢?安全序列:一个进程序列{P1,…,Pn}是安全的,如果对于每一个进程Pi(1≤i≤n),它以后尚需要的资源量不超过系统当前剩余资源量与所有进程Pj (j < i )当前占有资源量之和。
银行家算法:我们可以把操作系统看作是银行家,操作系统管理的资源相当于银行家管理的资金,进程向操作系统请求分配资源相当于用户向银行家贷款。
操作系统按照银行家制定的规则为进程分配资源,当进程首次申请资源时,要测试该进程对资源的最大需求量,如果系统现存的资源可以满足它的最大需求量则按当前的申请量分配资源,否则就推迟分配。
当进程在执行中继续申请资源时,先测试该进程已占用的资源数与本次申请的资源数之和是否超过了该进程对资源的最大需求量。
若超过则拒绝分配资源,若没有超过则再测试系统现存的资源能否满足该进程尚需的最大资源量,若能满足则按当前的申请量分配资源,否则也要推迟分配
3.3详细设计
1.银行家算法的思路
先对用户提出的请求进行合法性检查,即检查请求的是不大于需要的,是否不大于可利用的。
若请求合法,则进行试分配。
最后对试分配后的状态调用安全性检查算法进行安全性检查。
若安全,则分配,否则,不分配,恢复原来状态,拒绝申请。
2.银行家算法中用到的主要数据结构
可利用资源向量 int Available[j] j为资源的种类。
最大需求矩阵 int Max[i][j] i为进程的数量。
分配矩阵 int Allocation[i][j]
需求矩阵 int need[i][j]= Max[i][j]- Allocation[i][j]
申请各类资源数量 int Request i[j] i进程申请j资源的数量
工作向量 int Work[x] int Finish[y]
3.银行家算法bank()
进程i发出请求申请k个j资源,Request i[j]=k
(1)检查申请量是否不大于需求量:Request i[j]<=need[i,j],若条件不符重新输入,不允许申请大于需求量。
(2)检查申请量是否小于系统中的可利用资源数量:Request i[j]<=available[i,j],若条件不符就申请失败,阻塞该进程,用goto语句跳转到重新申请资源。
(3)若以上两个条件都满足,则系统试探着将资源分配给申请的进程,并修改下面数据结构中的数值:
Available[i,j]= Available[i,j]- Request i[j];
Allocation[i][j]= Allocation[i][j]+ Request i[j];
need[i][j]= need[i][j]- Request i[j];
(4)试分配后,执行安全性检查,调用safe()函数检查此次资源分配后系统是否处于安全状态。
若安全,才正式将资源分配给进程;否则本次试探分配作废,恢
(5)用do{…}while 循环语句实现输入字符y/n判断是否继续进行资源申请。
4.安全性检查算法(safe()函数)
(1)设置两个向量:
工作向量Work,它表示系统可提供给进程继续运行所需的各类资源数目,在执行安全性算法开始时,Work= Available。
Finish,它表示系统是否有足够的资源分配给进程,使之运行完成。
开始时先做Finish[i]=0;当有足够的资源分配给进程时,再令Finish[i]=1。
(2)在进程中查找符合以下条件的进程:
条件1:Finish[i]=0;
条件2:need[i][j]<=Work[j]
若找到,则执行步骤(3)否则,执行步骤(4)
(3)当进程获得资源后,可顺利执行,直至完成,并释放出分配给它的资源,故应执行:
Work[j]= Work[j]+ Allocation[i][j];
Finish[i]=1;
goto step 2;
(4)如果所有的Finish[i]=1都满足,则表示系统处于安全状态,否则,处于不安全状态。
3.4关键代码
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
# define m 50
int no1; //进程数
int no2; //资源数
int allocation[m][m],need[m][m],available[m],max[m][m];
char name1[m],name2[m]; //定义全局变量void main()
{
void check();
void print();
int i,j,p=0,q=0;
char c;
int request[m],allocation1[m][m],need1[m][m],available1[m];
printf("**********************************************\n");
printf("* 银行家算法的设计与实现 *\n");
printf("**********************************************\n");
printf("请输入进程总数:\n");
scanf("%d",&no1);
printf("请输入资源种类数:\n");
scanf("%d",&no2);
printf("请输入Max矩阵:\n");
for(i=0;i<no1;i++)
for(j=0;j<no2;j++)
scanf("%d",&max[i][j]); //输入已知进程最大资源需求量
printf("请输入Allocation矩阵:\n");
for(i=0;i<no1;i++)
for(j=0;j<no2;j++)
scanf("%d",&allocation[i][j]); //输入已知的进程已分配的资源数
for(i=0;i<no1;i++)
for(j=0;j<no2;j++)
need[i][j]=max[i][j]-allocation[i][j]; //根据输入的两个数组计算出need矩阵的值
printf("请输入Available矩阵\n");
for(i=0;i<no2;i++)
scanf("%d",&available[i]); //输入已知的可用资源数
print(); //输出已知条件
check(); //检测T0时刻已知条件的安全状态
if(r==1) //如果安全则执行以下代码
{
do{
q=0;
p=0;
printf("\n请输入请求资源的进程号(0~4):\n");
scanf("%d",&i);
if(i>=no1)
{
printf("输入错误,请重新输入:\n");
continue;
}
else break;
}
printf("\n请输入该进程所请求的资源数request[j]:\n");
for(j=0;j<no2;j++)
scanf("%d",&request[j]);
for(j=0;j<no2;j++)
if(request[j]>need[i][j]) p=1;
//判断请求是否超过该进程所需要的资源数
if(p)
printf("请求资源超过该进程资源需求量,请求失败!\n");
else
{
for(j=0;j<no2;j++)
if(request[j]>available[j]) q=1;
//判断请求是否超过可用资源数
if(q)
printf("没有做够的资源分配,请求失败!\n");
else //请求满足条件
{
for(j=0;j<no2;j++)
{
available1[j]=available[j];
allocation1[i][j]=allocation[i][j];
need1[i][j]=need[i][j];
//保存原已分配的资源数,仍需要的资源数和可用的资源数
available[j]=available[j]-request[j];
allocation[i][j]+=request[j];
need[i][j]=need[i][j]-request[j];
//系统尝试把资源分配给请求的进程
}
print();
check(); //检测分配后的安全性
if(r==0) //如果分配后系统不安全
{
for(j=0;j<no2;j++)
{
need[i][j]=need1[i][j];
//还原已分配的资源数,仍需要的资源数和可用的资源数
}
printf("返回分配前资源数\n");
print();
}
}
}printf("\n你还要继续分配吗?Y or N ?\n");
//判断是否继续进行资源分配
c=getche();
}while(c=='y'||c=='Y');
}
}
void check() //安全算法函数
{
int k,f,v=0,i,j;
int work[m],a[m];
bool finish[m];
r=1;
for(i=0;i<no1;i++)
finish[i]=false; // 初始化进程均没得到足够资源数并完成for(i=0;i<no2;i++)
work[i]=available[i];//work[i]表示可提供进程继续运行的各类资源数
k=no1;
do{
for(i=0;i<no1;i++)
{
if(finish[i]==false)
{
f=1;
for(j=0;j<no2;j++)
if(need[i][j]>work[j])
f=0;
if(f==1) //找到还没有完成且需求数小于可提供进程继续运行的资源数的进程
{
finish[i]=true;
a[v++]=i; //记录安全序列号
for(j=0;j<no2;j++)
work[j]+=allocation[i][j]; //释放该进程已分配的资源
}
k--; //每完成一个进程分配,未完成的进程数就减1 }while(k>0);
f=1;
for(i=0;i<no1;i++) //判断是否所有的进程都完成
{
if(finish[i]==false)
{
f=0;
break;
}
}
if(f==0) //若有进程没完成,则为不安全状态
{
printf("系统处在不安全状态!");
r=0;
}
else
{
printf("\n系统当前为安全状态,安全序列为:\n");
for(i=0;i<no1;i++)
printf("p%d ",a[i]); //输出安全序列
}
}
void print() //输出函数
{
int i,j;
printf("\n");
printf("*************此时刻资源分配情况*********************\n");
printf("进程名/号 | Max | Allocation | Need |\n"); for (i = 0; i < no1; i++)
{
printf(" p%d/%d ",i,i);
for (j = 0; j < no2; j++)
{printf("%d ",max[i][j]);}
for (j = 0; j < no2; j++)
{printf(" %d ",allocation[i][j]);}
for (j = 0; j < no2; j++)
{printf(" %d ",need[i][j]);}
}
printf("\n");
printf("各类资源可利用的资源数为:");
for (j = 0; j < no2; j++)
{printf(" %d",available[j]);}
printf("\n");
}
3.5程序运行
1、程序初始化
2、检测系统资源分配是否安全结果
四、总结
在这次作业之后我更加了解关于死锁的问题,知道了银行家的算法的具体思想,以后要多动手、动脑才行。
五、参考文献
[1] 《计算机操作系统》西安电子科技大学出版社,汤小丹、梁红兵、哲凤屏、汤子瀛
[2] 《操作系统》浙江大学出版社,李善平主编。