《银行家算法的模拟实现》—实验报告

时间:2024.4.20

《银行家算法的模拟实现》

        --实验报告

题    目:银行家算法的模拟实现

专    业:

班    级:    

组    员: 

        

指导老师:       

一、实验目的

死锁会引起计算机工作僵死,因此操作系统中必须防止。本实验的目的在于让学生独立的使用高级语言编写和调试一个系统动态分配资源的简单模拟程序,了解死锁产生的条件和原因,并采用银行家算法有效地防止死锁的发生,以加深对课堂上所讲授的知识的理解。

二、实验内容

模拟实现银行家算法实现死锁避免。要求:初始数据(如系统在T0时刻的资源分配情况、每一种资源的总数量)从文本文件读入,文件中给出最大需求矩阵Max、分配矩阵Allocation,在程序中求得需求矩阵Need和可利用资源向量Available。

三、实验分析过程

1、整个银行家算法的思路。

  先对用户提出的请求进行合法性检查,再进行预分配,利用安全性检查算法进行安全性检查。

1)进程一开始向系统提出最大需求量. 
2)进程每次提出新的需求(分期贷款)都统计是否超出它事先提出的最大需求量. 
3)若正常,则判断该进程所需剩余剩余量(包括本次申请)是否超出系统所掌握的 
剩余资源量,若不超出,则分配,否则等待

2、算法用到的主要数据结构和C语言说明。

 (1)、可利用资源向量  INT  AVAILABLE[M]  M为资源的类型。

 (2)、最大需求矩阵    INT  MAX[N][M]  N为进程的数量。

 (3)、已分配矩阵      INT  ALLOCATION[N][M]

 (4)、还需求矩阵      INT  NEED[N][N]

 (5)、申请各类资源数量int Request[x]; //

 (6)、工作向量        int Work[x];

 (7)、int Finish[y]; //表示系统是否有足够的资源分配给进程,0为否,非0为是

3、银行家算法 (主程序)

 (1)、系统初始化。输入进程数量,资源种类,各进程已分配、还需求各资源数量,各资源可用数量等

 (2)、输入用户的请求三元组(I,J,K),为进程I申请K个J类资源。

 (3)、检查用户的请求是否小于还需求的数量,条件是 K<=NEED[I,J]。如果条件不符则提示重新输入,即不允许索取大于需求量

 (4)、检查用户的请求是否小于系统中的可利用资源数量,条件是K<=AVALIABLE[I,J]。如果条件不符则申请失败,阻塞该进程,重新进行进程动态资源申请(使用goto语句)

 (5)、进行资源的预分配,语句如下:

       AVALIBLE[I][J]= AVALIBLE[I][J]-K;

 ALLOCATION[I][J]= ALLOCATION[I][J]+K;

 NEED[I][J]=NEED[I][J]-K;

 (6)、系统调用安全性检查算法(checksafe()函数)进行检查,如果检查通过,则不用回收,否则进行回收,进程资源申请失败进入等待。

4、安全性检查算法(checksafe()子函数)

 (1)、设置两个临时变量。

       FINISH[N]记录进程模拟执行的结束状态,初值为0,如果可以模拟执行结束,则可设为1,也可设为其它非零值以表示执行的先后次序。

       WORK[M]记录模拟执行中资源的回收情况,初值为AVAILABLE[M]的值。

 (2)、在进程中查找符合以下条件的进程。

           条件1:FINISH[I]=0

           条件2:NEED[I][J]〈=WORK[J]

 (3)、如果查找成功则进行资源的模拟回收,语句如下:

           WORK[J]=WORK[J]+ALLOCATION[I][J];

           FINISH[I]=1 或查找到的顺序号

(4)、如果查找不成功,则检查所有进程的FINISH[],如果有一个为0,则系统不为0,返回不成功标志。否则返回成功标志。

四、系统流程图


五、程序源代码

#include <iostream.h>

#include<stdio.h>

#include<stdlib.h>

const unsigned short c=3;//资源类数

const unsigned short t=5;//进程数

void print();//用于打印输出表格的函数

void input();//用于输入的函数

void tryfenpei(int i);//试分配函数;

void refenpei(int i);//恢复数据函数

void checksafe(int s);//安全检测函数

int temp[t];

int work[c];

//定义初始化数组

int need[t][c],request[c],available[c];

int max[t][c]={3, 5, 7 ,9 ,11,6 ,8 ,2 ,9, 5,6 ,3 ,5 ,7 ,4};

int allocation[t][c]={1 ,2 ,5 ,4, 8,5 ,4, 1 ,8 ,3 ,3 ,2 ,4, 3, 1};

int total[c]={17,21,25};

int in;//用户选择的进程号

/*------------------main函数-----------------------------*/

int main(int argc,char *argv[])

{

       int i;

       char ch='Y';

       int l=0,m=0,a;

       for( i=0;i<t;i++)

              {

                     for(int j=0;j<c;j++)

                            need[i][j]=max[i][j]-allocation[i][j];

              }

              for( m=0;m<c;m++)

              {

                     a=0;

                     for(int l=0;l<t;l++)

                            a+=allocation[l][m];

                     available[m]=total[m]-a;

              }

             

       do {

              if(ch=='Y'||ch=='y')

              {

                     cout<<"ok,现在开始进入实验……"<<endl;

                  cout<<"请输入需要请求的进程号(0-4):";

                     while(cin>>in)

                     {

                            if(!(0<=in&&in<=4))

                            {

                                   cout<<"这里没有该进程,请重新输入~"<<endl;

                            }

                            else break;

                     }

                     cout<<"您输入的是 "<<"p["<<in<<"]"<<" 进程"<<endl;

                     cout<<"该进程需求量为: ";

                     for(i=0;i<c;i++)

                     {

                            need[in][i]=max[in][i]-allocation[in][i];

                            cout<<need[in][i]<<" ";}

                    

                     cout<<endl;

                     cout<<endl;

                     cout<<"请输入请求资源向量:";//输入格式为x

                     for(i=0;i<c;i++)

                     {

                            while(cin>>request[i])

                            {

                                   if(request[i]<0) cout<<"sorry,输入的数字无效~"<<endl;

                                   else if(request[i]>need[in][i])

                                          cout<<"超出进程需求量~"<<endl<<endl;

                       if(request[i]>available[i])

                              cout<<"系统没有足够多的可用资源量满足进程需要~"<<endl<<endl;

                       else break;

                            }

                     }

     cout<<"输入成功~,您输入的是:"<<request[0]<<"  "

                    <<request[1]<<"  "<<request[2];

        cout<<"等待已久的银行家算法开始执行~"<<endl;

        tryfenpei(in);//分配函数

        cout<<"试分配完成~"<<endl;

        cout<<"现在进入安全性检测……"<<endl;

        checksafe(in);//安全性检测函数

        cout<<"您还想继续银行家算法的实验吗~?(y-继续n终止)";

              }

        else if(ch=='N'||ch=='n')

        {

               cout<<"感谢您的使用,Bye~"<<endl<<"退出ing……"<<endl;

               break;

        }

        else

               cout<<"输出无效!请重新输入"<<endl;

       }

while (cin>>ch);

return 0;

}

/*-------输出函数-------*/

void print()

{

       int i,j;

       cout<<"更新数据中..."<<endl;

       cout<<"|-------|------------|-----------|----------|-----------|"<<endl;

       cout<<"|-------|最大需求矩阵|已分配矩阵-|-需求矩阵-|可利用资源-|"<<endl;

       cout<<"| 资源  |    Max     | Allocation|   Need   | available |"<<endl;

       cout<<"|       | A   B   C  | A   B   C |  A  B  C |  A  B  C  |"<<endl;

       cout<<"|进程   |            |           |          |           |"<<endl;

       cout<<"|-------|------------|-----------|----------|-----------|"<<endl;

       for(i=0;i<5;i++)

       {

              cout<<"|   p"<<i<<"  | ";

       for(j=0;j<3;j++) {

              cout<<max[i][j]<<"  "; }

       cout<<" | ";

       for(j=0;j<3;j++)  {

              cout<<"  "<<allocation[i][j];  }

    cout<<"  | ";

       for(j=0;j<3;j++)  {

              cout<<"  "<<need[i][j];   }

       cout<<"  |";

    if(i==0)   {

              for(j=0;j<3;j++)    {

                     cout<<"  "<<available[j];   }

              cout<<"  |";    }

       if(i>0)

       {cout<<"          |";  }

    cout<<endl;  }

cout<<"|-------|------------|-----------|----------|-----------|"<<endl;

}

/*--------试分配函数-------*/

void tryfenpei(int i)

{

       for(int f=0;f<c;f++)

       {

              available[f]=available[f]-request[f];

              allocation[i][f]=allocation[i][f]+request[f];

              need[i][f]=need[i][f]-request[f];

       }

}

/*--------恢复数据函数-------*/

void refenpei(int i)

{

       for(int f=0;f<c;f++)

       {

              available[f]=available[f]+request[f];

              allocation[i][f]=allocation[i][f]-request[f];

              need[i][f]=need[i][f]+request[f];

       }

}

int com(int *p,int *q)

{

       int i;

       for(i=0;i<c;i++)

              if(p[i]>q[i])

                     return 0;

              return 1;

}

/*--------安全检测函数---------*/

void checksafe(int s)

{

       int flag,temp[t],i,j,l,k=0;

       bool finish[t];

       for(i=0;i<t;i++)

              finish[i]=false;

       for(j=0;j<c;j++)

              work[j]=available[j];

       cout<<"|-------|-----------------|----------|"<<endl;

       cout<<"| resource |-Work+Allocation-|--Finish--|"<<endl;

       cout<<"|    |   A    B    C   |    T/F   |"<<endl;

       cout<<"|programme  |                 |          |"<<endl;

       cout<<"|-------|-----------------|----------|"<<endl;

       for(i=0;i<t;i++)

       {

              l=0;

              for(j=0;j<c;j++)

              {

                     if(need[i][j]>work[j])

                            l=1;

                     break;

              }

              if(finish[i]==false&&l==0)

              {

              cout<<"|  p"<<i<<"  | ";

                     for(j=0;j<c;j++)

                     {

                            work[j]=work[j]+allocation[i][j];

                         if(work[j]>9)

                            cout<<"  "<<work[j]<<"  ";

                         else

                            cout<<"  "<<work[j]<<"  ";

                     }

              cout<<" ";

              cout<<"|";

              cout<<"   ";

              finish[i]=true;

              cout<<"true  ";

              cout<<"|";

              temp[k]=i;//cout<<'temp="<<temp[k]<<endl;

              k++;

              i=-1;  //从用户选择的进程开始对每个进程都要检测

              cout<<endl;

               }

      }

cout<<"|-------|-----------------|----------|"<<endl<<endl;

for(i=0;i<t;i++)

{

       if(finish[i]==false)

              flag=1;

if(flag==1)

{

       cout<<"系统不安全!本次资源申请不成功感!"<<endl;

       cout<<"正在恢复原来的数据..."<<endl;

       refenpei(in);

       cout<<"恢复数据成功!正在打印输出..."<<endl;

       print();

}

else

{

       cout<<"找到一个安全系列:";

       for(i=0;i<t;i++)

              cout<<"P"<<temp[i]<<"--->";

       cout<<endl<<"已通过安全性测试!"<<endl<<endl<<endl;

       cout<<"开始给第"<<"p]"<<in<<"]"<<"进程分配资源..."<<endl;

       cout<<"分配完成!打印输出..."<<endl<<endl;

       print();

       cout<<endl;

}

}

}

五、程序运行结果及分析

1、运行结果

输入初值,进行安全性测试,结果安全序列,依次为P4-P0-P1-P2-P3分配资源:

     

资源不足,无法继续实验:

2、出现问题及解决方案

本程序考虑了程序功能实现、格式显示合理化、输入错误异常处理等各个方面的设计,尽可能使程序设计的更加完美。在长期的设计调试过程中遇到过许多问题,通过网上搜索、查询资料、调试试验等方法一一解决。下面大致罗列一些主要问题:

(1)、关于某些判断算法优劣问题:

在程序中很多地方都会用到循环判断是否符合条件的算法,在设计这些算法时有很多方法,而有的算法可以更节省时间。如下安全性算法中寻找寻找符合Finish[i]==0条件的进程的例子:

/* 算法一:

           for (j=0; j<m; j++)

                 if (Work[j]>=Need[i][j]) counter=counter+1;//记数

           if(counter==m){…

*/ //算法二:

           for (j=0; j<m; j++)

                 if (Work[j]>=Need[i][j]); //可用大于等于需求

                else{

                      counter=1;

                      break;

                 }

           if(counter!=1){…

显然算法二要优于算法一。本程序中还有很多类似的地方。这里主要考虑的是一个程序的优化设计问题。

(2)、关于某些系统函数调用时的执行顺序:

在调用一些系统函数如getch() 、system("pause")等时发现其执行顺序的一些问题。如类似:

cout<<" =================================="<<endl;

cout<<" \n\n\n"<<endl;

system("pause");//暂停

调试时发现此时:在Microsoft Visual C++ 6.0中先执行system("pause") 再输出显示,而在调试器Bloodshed Dev-C++中则顺序执行;但当把cout<<" \n\n\n"<<endl; 改为 cout<<endl<<endl<<endl; 其他不变时,则在两中调试器中均为顺序执行,即先显示后暂停。

查找了一下相关帮助:

     在OSTREAM.H中有这样的一个inline函数:

     inline _CRTIMP ostream& __cdecl endl(ostream& _outs) { return _outs << '\n' << flush; }。也就是说

     endl= return _outs << '\n' << flush;

     endl除了写'\n'进外,还调用flush函数,刷新缓冲区,把缓冲区里的数据写入文件或屏幕。如果考虑效率就用'\n'

(3)、关于设置暂停的方法:

在有些地方需要暂停一下以便于用户查看信息等,总结了下大致可用以下几中方法:

方法一:

#include <stdlib.h>

system("pause");//暂停一下并显示“输入任意键继续…”

方法二:

#include <stdio.h>

getchar();//须按回车键结束,不是任意键

方法三:

#include <conio.h>

getch();//等待键盘输入,不返回任何值,无任何显示

方法四:

使用 char* tt=new char; cin>>tt; 方式,要求键盘输入一个与程序无关的变量

六、心得体会

     “银行家算法的模拟实现”是本学期操作系统课程唯一的课程设计。在设计此程序的过程中,我们遇到过许多问题,也学到了很多东西。本程序的设计实现主要是用C++语言实现,通过对程序算法的设计优化、输出显示的格式设计、输入过程中的异常处理等一些设计过程中的问题的考虑解决,在C++学习上也有了很大的进步。程序设计过程中开始遇到的最大的问题是算法的结构设计问题,课本上只给了设计要求及简单的算法,要真正实现还需要考虑很多方面。在算法的数据结构设计上考虑了很长时间。在程序设计中先后参考了很多网络资料,也参考了一些别人写的的程序,综合这些算法思想和自己的思路对程序做了很好的设计方式,对一些算法的优越性等也作了一些考虑。此外考虑最多的就是异常错误处理的设计。一个好的程序必须能在各种环境下都有其相应的处理方式,至少能应对一些常见的可能发生的错误。比如一般的要求输入为数字时,如果输入了一个非数字字符,程序就会立即出错无法继续运行,本程序针对这个问题设计了一个shuzi();函数进行处理,处理方式为:接受键盘输入的字符为字符串,然后对字符串的每个字符进行判断是否为数字,如果有非数字字符出现则提示出错并要求重新输入。又如在判断是否继续时要求输入Y/N时,按一般的方式,如果输入为多个字符,则多余的字符会保存在缓冲区,到下次要求输入时输入而导致出错,对此问题设计处理方式为接受输入字符保存为串然后只取其首字符进行判断。还有很多类似的错误处理。还有在设置程序的显示优化时,发现暂停函数在不同的情况下执行顺序不同,如此等等。

更多相关推荐:
计算机操作系统银行家算法实验报告

计算机操作系统实验报告一实验名称银行家算法二实验目的银行家算法是避免死锁的一种重要方法通过编写一个简单的银行家算法程序加深了解有关资源申请避免死锁等概念并体会和了解死锁和避免死锁的具体实施方法三问题分析与设计1...

银行家算法+实验报告

淮海工学院计算机工程学院实验报告书课程名操作系统原理题目银行家算法班级学号511021012姓名操作系统原理实验报告1一实验目的银行家算法是操作系统中避免死锁的典型算法本实验可以加深对银行家算法的步骤和相关数据...

银行家算法实验报告

计算机学院操作系统课程设计报告设计题目银行家算法的实现姓名学号班级06网络工程班完成日期20xx年6月13日银行家算法分析设计与实现一设计理论描述本设计的目的是通过编写和调试一个系统动态分配资源的简单模拟程序观...

操作系统实验报告(银行家算法c语言描述)

洛阳理工学院实验报告17273747576777

银行家算法实验报告

计算机操作系统实验报告何美西109253030212一实验名称银行家算法二实验目的银行家算法是避免死锁的一种重要方法通过编写一个简单的银行家算法程序加深了解有关资源申请避免死锁等概念并体会和了解死锁和避免死锁的...

银行家算法实验报告

银行家算法银行家算法姓名学号报告日期操作系统实验三1银行家算法一实验目的通过实验加深对多实例资源分配系统中死锁避免方法银行家算法的理解掌握Windows环境下银行家算法的实现方法同时巩固利用WindowsAPI...

操作系统银行家算法实验报告

银行家算法开发语言及实现平台或实验环境CMicrosoftVisualStudio60实验目的1进一步理解利用银行家算法避免死锁的问题2在了解和掌握银行家算法的基础上编制银行家算法通用程序将调试结果显示在计算机...

操作系统实验报告(银行家算法c语言描述)

实验原理n个并发进程共享m个系统资源的系统进程可动态申请资源和释放资源系统按各进程的申请动态的分配资源先对用户提出的请求进行合法性检查再进行预分配利用安全性检测算法进行安全性检测如果系统分配资源系统进入安全状态...

操作系统原理与linux-银行家算法实验报告

计算机科学与技术系实验报告课程名称操作系统原理与linux实验名称银行家算法20xx年04月6日实验三银行家算法一实验目的1进一步理解利用银行家算法避免死锁的问题2在了解和掌握银行家算法的基础上编制银行家算法通...

银行家算法实验报告(操作系统)

计算机操作系统题目银行家算法设计目的1加深了解有关资源申请避免死锁等概念2体会和了解死锁和避免死锁的具体实施方法知识需求1死锁的相关知识2银行家算法3系统安全性检查实验内容1设计进程对各类资源最大申请表示及初值...

操作系统实验四银行家算法

操作系统实验实验四银行家算法学号1215108019姓名李克帆班级12电子2班华侨大学电子工程系实验目的1理解银行家算法2掌握进程安全性检查的方法与资源分配的方法实验内容与基本要求编制模拟银行家算法的程序并以下...

银行家算法课程设计报告(毕业论文格式)

操作系统课程设计报告题目银行家算法的设计与实现院系专业班级学生学号指导教师20xx年12月关键路径的算法设计与实现摘要Dijkstra的银行家算法是最有代表性的避免死锁的算法该算法由于能用于银行系统现金贷款的发...

银行家算法实验报告(37篇)