银行家算法实验报告.docx
- 文档编号:10811082
- 上传时间:2023-02-23
- 格式:DOCX
- 页数:23
- 大小:240.18KB
银行家算法实验报告.docx
《银行家算法实验报告.docx》由会员分享,可在线阅读,更多相关《银行家算法实验报告.docx(23页珍藏版)》请在冰豆网上搜索。
银行家算法实验报告
银行家算法
一、课题内容和要求
内容:
银行家算法是操作系统中一种最有代表性的用来避免死锁的算法。
该算法在资源分配前进行安全性检测,保证系统处于安全状态,从而避免死锁。
此次课程设计的主要内容是实现算法模拟银行家算法,模拟实现动态资源分配,编写和调试一个系统动态资源的简单模拟银行家算法程序程序,观察死锁产生的条件,并使用适当的算法,有效的防止和避免死锁的发生。
从而,加深了解有关资源申请、避免死锁等概念,并体会和了解死锁和避免死锁的具体实施方法。
要求:
Ø模拟一个银行家算法;
Ø了解算法中用的各种数据结构;
Ø系统的初始状态信息从文本文件读取;
Ø判断是否存在安全序列,输出任意一个安全序列即可;
Ø判断系统是否可以满足进程的请求。
二、需求分析
银行家算法在避免死锁方法中允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次分配资源的安全性,若分配不会导致系统进入不安全状态,则分配,否则等待。
为实现银行家算法,系统必须设置若干数据结构。
本次课程设计的目的是通过编写和调试一个系统动态分配资源的简单模拟程序,观察死锁产生的条件,并采用适当的算法,有效地防止和避免死锁地发生。
总体要求如下:
①了解算法中用的各种数据结构;②系统的初始状态信息从文本文件读取;③判断是否存在安全序列,输出任意一个安全序列即可;④判断系统是否可以满足进程的请求。
【要了解银行家算法,必须先了解操作系统安全状态和不安全状态。
安全序列是指一个进程序列{P1,…,Pn}是安全的,即对于每一个进程Pi(1≤i≤n),它以后尚需要的资源量不超过系统当前剩余资源量与所有进程Pj(j
安全状态:
如果存在一个由系统中所有进程构成的安全序列P1,…,Pn,则系统处于安全状态。
安全状态一定是没有死锁发生。
不安全状态:
不存在一个安全序列。
不安全状态不一定导致死锁。
】
3、概要设计
v银行家算法的原理
我们可以把操作系统看作是银行家,操作系统管理的资源相当于银行家管理的资金,进程向操作系统请求分配资源相当于用户向银行家贷款。
为保证资金的安全,银行家规定:
(1)当一个顾客对资金的最大需求量不超过银行家现有的资金时就可接纳该顾客;
(2)顾客可以分期贷款,但贷款的总数不能超过最大需求量;
(3)当银行家现有的资金不能满足顾客尚需的贷款数额时,对顾客的贷款可推迟支付,但总能使顾客在有限的时间里得到贷款;
(4)当顾客得到所需的全部资金后,一定能在有限的时间里归还所有的资金.
操作系统按照银行家制定的规则为进程分配资源,当进程首次申请资源时,要测试该进程对资源的最大需求量,如果系统现存的资源可以满足它的最大需求量则按当前的申请量分配资源,否则就推迟分配。
当进程在执行中继续申请资源时,先测试该进程本次申请的资源数是否超过了该资源所剩余的总量。
若超过则拒绝分配资源,若能满足则按当前的申请量分配资源,否则也要推迟分配。
v银行家算法中用到的主要数据结构:
1.可利用资源向量Available
intAvailable[j]//如果Available[j]=K,则表示系统中现有Rj类资源K个。
2.最大需求矩阵Max
intMax[i][j]//如果Max[i,j]=K,则表示进程i需要Rj类资源的最大数目为K。
3.分配矩阵Allocation
intAllocation[i][j]//如果Allocation[i,j]=K,则表示进程i当前已分得Rj类资源的数目为K。
4.需求矩阵Need
intneed[i][j]=Max[i][j]-Allocation[i][j]//如果Need[i,j]=K,则表示进程i还需要Rj类资源K个,方能完成其任务。
5.申请各类资源数量intRequesti[j]//i进程申请j资源的数量
6.工作向量intWork[x]intFinish[y]
v银行家算法的实现:
Ø初始化
由用户输入数据,分别对可利用资源向量矩阵AVAILABLE、最大需求矩阵MAX、分配矩阵ALLOCATION、需求矩阵NEED赋值。
Ø银行家算法
在避免死锁的方法中,所施加的限制条件较弱,有可能获得令人满意的系统性能。
在该方法中把系统的状态分为安全状态和不安全状态,只要能使系统始终都处于安全状态,便可以避免发生死锁。
银行家算法的基本思想是分配资源之前,判断系统是否是安全的;若是,才分配。
它是最具有代表性的避免死锁的算法。
设进程cusneed提出请求REQUEST[i],则银行家算法按如下规则进行判断。
(1)如果REQUEST[cusneed][i]<=NEED[cusneed][i],则转
(2);否则,出错。
(2)如果REQUEST[cusneed][i]<=AVAILABLE[cusneed][i],则转(3);否则,出错。
(3)系统试探分配资源,修改相关数据:
AVAILABLE[i]-=REQUEST[cusneed][i];
ALLOCATION[cusneed][i]+=REQUEST[cusneed][i];
NEED[cusneed][i]-=REQUEST[cusneed][i];
(4)系统执行安全性检查,如安全,则分配成立;否则试探险性分配作废,系统恢复原状,进程等待。
(5)用do{…}while循环语句实现输入字符y/n判断是否继续进行资源申请。
Ø安全性检查算法safe()函数
(1)设置两个工作向量Work=AVAILABLE;FINISH
(2)从进程集合中找到一个满足下述条件的进程,FINISH==false;NEED<=Work;如找到,执行(3);否则,执行(4)
(3)设进程获得资源,可顺利执行,直至完成,从而释放资源。
Work+=ALLOCATION;Finish=true;GOTO2
(4)如所有的进程Finish=true,则表示安全;否则系统不安全。
v算法流程图:
四.详细设计
v程序结构
程序共有以下几个部分:
Ø主程序main()
逐个调用初始化、显示状态、安全性检查、银行家算法函数,使程序有序的进行。
Ø初始化init()
用于程序开始进行初始化输入数据:
进程数量、资源种类、各种资源可利用数量、各进程的各种资源已分配数量、各进程对各类资源最大需求数等。
Ø银行家算法bank()
进行银行家算法模拟实现的模块,调用其他各个模块进行银行家算法模拟过程。
Ø当前安全性检查safe()
用于判断当前状态安全性,根据不同地方的调用提示处理不同。
v函数声明
voidinit(); //系统初始化函数
voidsafe();//安全性算法函数
voidbank();//银行家算法函数
voidmain();//主函数
v数据结构
程序使用的一些变量:
intm;//m资源种类数
intn;//进程数
intAvailable[x];//各种资源可利用的数量
intAllocation[y][y];//各进程当前已分配的资源数量
intMax[y][y];//各进程对各类资源的最大需求数
intNeed[y][y];//还需求矩阵
intRequest[x];//申请各类资源的数量
intWork[x];//工作向量,表系统可提供给进程运行所需各类资源数量
intFinish[y];//表系统是否有足够的资源分配给进程,0为否,1为是
intp[y];//存储安全序列
inti,j;//全局变量,主要用于循环语句中
intjc;//任选一个进程
intall=0;//定义变量all,如果all==0,表示进程已经运行完,如果all>=1,表示还有进程没有运行完
constintx=10,y=10;//定义常量
v源代码
#include
#include
#include
usingnamespacestd;//定义标识符
#defineTRUE1//定义TRUE=1
#defineFALSE0//定义FLASE=0
voidbank(vector
intsafe(vector
voidinit();//声明初始化函数
/*************************************主函数main()**************************************************************/
voidmain()
{
init();//设定初值
intsafe(vector
}
/**************************************初始化函数init()*********************************************************/
voidinit()
{
intm;//m资源类数
intn;//进程数
cout<<"输入资源类数"< cin>>m; vector cout<<"输入各类资源总数: "< FILE*fp; fp=fopen("All.txt","r+");//r+指以可读写方式打开文件,该文件必须存在 cout<<"从All.txt文件中读入数据,并输出"< for(inti=0;i { fscanf(fp,"%d",&All[i]); cout< } fclose(fp); cout<<"\n输入进程数"< cin>>n; vector /***********************************************************************************************************/ fp=fopen("Max.txt","r+"); cout<<"从Max.txt文件中读入数据,并输出"< for(i=0;i { for(intj=0;j { fscanf(fp,"%d",&Max[i][j]); cout< } cout< } fclose(fp); cout<<"输入已分配的Allocation"< vector vector /************************************************************************************************/ fp=fopen("Allocation.txt","r+"); cout<<"Allocation.txt从文件中读入数据,并输出"< for(i=0;i { for(intj=0;j { fscanf(fp,"%d",&Allocation[i][j]); Need[i][j]=Max[i][j]-Allocation[i][j];//在初始化Max时,同时初始化Need数组 All[j]=All[j]-Allocation[i][j];//在初始化Max时,同时修改All数组 cout< } cout< } fclose(fp); intsafe(vector cout<<"此状态安全! "< bank(All,Need,Allocation,n,m);//调用银行家算法bank()函数 } /*******************************************银行家算法bank()函数******************************************************/ voidbank(vector { vector intall=0; //定义变量all,如果all==0,表示进程已经运行完,如果all>=1,表示还有进程没有运行完 for(inti=0;i for(intj=0;j all+=Need[i][j]; if(0==all) { cout<<"所有进程已经运行完,结束"< exit(0); } intjc;//任选一个进程 charagain; all=0;//重新初始化all, while (1) { while(all==0) { all=0; //如果all==0,表示进程已经运行完,如果all>=1,表示还有进程没有运行完 //循环直至all>0,即找到一个未运行完的进程 cout<<"任选一个进程作为当前进程0--"< cin>>jc; for(intj=0;j { all+=Need[jc][j]; } if(0==all) { cout<<"此进程已经运行,重新输入"< } } cout<<"输入该进程的请求向量"< for(i=0;i { cin>>Request[i]; while(Request[i]>Need[jc][i]||Request[i]>All[i]) { cout<<"请求向量无法满足"< break; } } ///////////////////////////////////////////////////////////////////////////// //////////////////系统试探着把资源分配给该进程/////////////////////////////// for(i=0;i { All[i]=All[i]-Request[i]; Allocation[jc][i]=Allocation[jc][i]+Request[i]; Need[jc][i]=Need[jc][i]-Request[i]; } intbb=0; bb=safe(All,Need,Allocation,n,m);//调用安全性算法,判断此次资源分配后,系统是否处安全状态 if(1==bb) { cout<<"系统成功分配资源"< } else { cout<<"系统未能成分配资源,收回预分配资源"< for(i=0;i { All[i]=All[i]+Request[i]; Allocation[jc][i]=Allocation[jc][i]-Request[i]; Need[jc][i]=Need[jc][i]+Request[i]; } } cout<<"您还想再次请求分配吗? 是请按y/Y,否请按其它键"< cin>>again; if(again=='y'||again=='Y') { all=0; continue; } break; } } /**************************************安全性算法safe()函数*********************************************************/ intsafe(vector { vector Work=All;//Work代表可用资源数,把总资源数ALL当做可用资源数Available intlen=-1;//记录安全序列的进程个数,如果len==n,即表示所有的finish[i]=true,处于安全状态 for(inti=0;i Finish[i]=FALSE;//令0~m-1个进程的标记Finish[i]均初始为0 for(i=0;i { intneeded=1;//Need[i][j]的标记,初始化为1 for(intj=0;j { if(Need[i][j]<=Work[j])//判断需求量是否大于可用资源数(ALL) { needed=needed*TRUE;//是,则将needed标记为1 } elseneeded=needed*FALSE;//否则,将needed标记为0 } if((Finish[i]==FALSE)&&needed==1)//判断是否该进程处于非安全状态(Finish[i]==0)并且该进程Need[i][j]<=Work[j](可分配) { for(j=0;j { Work[j]=Work[j]+Allocation[i][j];//新的可用资源数(ALL)=当前可用资源数(ALL)+已分配给进程的资源数 } Finish[i]=TRUE;//表示该进程处于安全状态,i为进程号 len=len+1;//表示安全序列又增加了一个进程 count[len]=i;//给安全序列数组赋值(内容为进程号),以len做下标 i=-1;//////////给处于非安全状态的进程重新从0编号(如果没有i=-1,那么i++后不为0,无法重新开始) } } if(len==n-1) { cout<<"系统是安全的"< cout<<"安全序列"< for(i=0;i<=len;i++) { cout< if(i! =len) { cout<<"-->"; } } cout< returnTRUE; } else { cout<<"系统是不安全的"< returnFALSE; } } 五、测试数据及其结果分析 1.初始化结果 2.检测系统资源分配是否安全结果: 3.结果分析: 结果正确,符合本次课程设计要求 6、调试过程中的问题 第一次完成编程后,运行时候只能手动输入相应矩阵,这样如果遇见很大的矩阵会增加很长的输入时间。 经过查阅资料,进行调试之后,实现了从文件中读入数据,这样大大减少了工作量。 设计程序时候要考虑到方便用户的操纵控制并减少用户的记忆负担。 在友好度方面,进行了不断的改进,以确保用户能清晰地看清程序的运行结果,运行过程。 但是我并没有去美化界面设计,不过操作起来还算是简单清晰。 在调试程序时候,还出现了一些死循环,导致程序无法运行。 本程序涉及的模块较多,一定要要注意实参的调用以及返回值的控制,不然在运行时极容易出错。 仔细分析原来是程序少了system("pause")的语句。 注意: 有些指令C里可以用,但C++不能运用。 所以平时要注意积累。 在设计程序中遇见不懂得问题,一定要请教老师或者查阅资料,往往一个错误会导致一连串的错误。 我在开始做的时候,就没有把握好程序模块之间调用的先后,一度导致了程序难以运行。 后来我画出了程序实现的流程图,清晰明了地掌握了程序的脉络,编写起来也轻松多了。 个人认为此次设计的代码还是可以优化的,但是由于知识有限,希望可以通过将来的学习,继续完善本段代码。 7、参考文献和查阅的资料 Ø参考文献: [1]《操作系统教程》[M].黄刚、徐小龙、段卫华人民邮电出版社,2009 [2]《Linux环境下C编程指南》[M].杨树青,王欢.清华大学出版社,2007 [3]《C++面对对象程序设计教程》[M].陈维兴,林小茶.清华大学出版社,2004 [4]《C语言程序设计教程》[M].杨路明.北京: 北京邮电大学出版社,2005 [5]《数据结构--使用C++语言描述》第二版陈慧南主编人民邮电出版社,2008 [6]XX 八、程序设计总结 银行家算法是一种能有效避免死锁的算法,是一个分配资源的过程,使分配的序列不会产生死锁。 其基本原理已经在《操作系统教程》这门课学过并且基本掌握。 但是用编程算法来实现,还是第一次,所以一开始没啥头绪。 后来又重新研究了一下书本上的
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 银行家 算法 实验 报告