操作系统养成计划之篇二:死锁实战篇——银行家算法

本文详细介绍银行家算法,包括安全序列、安全状态等概念,并通过实例演示如何检测系统是否处于安全状态,最后提供修正后的源码及执行效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

banker's algorothm

银行家算法是针对避免死锁问题的经典算法

其算法以银行借贷为基础,判断并且保证系统的安全运行

介绍银行家算法需要先介绍三个概念:

1:安全序列:指一个进程序列{123... n},对于每一个进程来说,都有他之后所需的资源量不超过系统当前剩余的资源量与该进程当前所占据资源量之和。

2、安全状态

系统中所有进程可以构成一个安全序列,则可以称该系统处于安全状态,安全状态是一定没有死锁发生的。

3、不安全状态

系统中不存在一个安全序列。不安全状态不一定发生死锁。

 

算法描述(数据结构)

系统可利用资源向量:available

定义一个含有m个向量的数组,表示系统可以利用的各类(m类)资源的总数,比如available[2]=10;表示第二类资源的总数为10个;

最大需求矩阵MAX

这是一个n*m的一个数组,表示系统中n个进程对于各类资源的最大需求,如MAX[1,2]=10;表示下标为1的进程需要第二类资源10个;

分配矩阵allocation

这也是一个n*m的矩阵,表示系统中各个进程已经分配的各类资源;如allocation[1,2]=5;表示下标为1的进程已经分配第二类资源5个。

需求矩阵need

同样,这个也是一个n*m的矩阵,表示各个进程目前尚需各类资源的数目,比如need[1,2]=3;

表示下标为1的进程需要第二类资源3个。Need[n,m]=MAX[n,m]-allocation[n,m];

 

安全算法的检测

举个栗子(反正不是板个栗子)

系统中存在A,B,C 3个进程,内存资源最大需求分别为70,60,50;内存资源总量为100,若当前分配资源分别是40,20,10;则在初始时刻各资源表示如下表:

 

Max

Allocation

Need

Residue

A

70

30

30

30

B

60

20

40

 

C

50

10

10

 

可见安全序列存在,为A->B->C或者为A->C->B

若这个时候C资源请求分配10个资源,系统会假定分配给C,然后检测系统安全性

 

Max

Allocation

Need

Residue

A

70

30

30

20

B

60

20

40

 

C

50

20

30

 

则当前剩余资源不能满足任何一个进程,不存在安全序列,则系统丑拒C的请求

 

以下是源码部分,源码主体架构来自于百度百科,但经过验证发现,该源码存在严重bug,即当进程获得所有资源之后,并不会释放该资源,以下源码已修正该bug,(哎,百度啊)

以下部分均为代码,开发环境VS2008,开发语言C。

#include<string.h>
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
//*************** Initialize  variable   start **********************//
#define process 5   //define process number
#define resource 3    //define resource category number
#define false 0
#define true 1
#define runing 0   //process execution status
#define over 1
int max[process][resource]={{8,5,4},{1,4,2},{7,0,3},{2,2,2},{4,4,3}};
int available[resource]={12,6,7};
int allocation[process][resource]={{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0}};
int need[process][resource]={{8,5,4},{1,4,2},{7,0,3},{2,2,2},{4,4,3}};
int request[resource]={0,0,0};
//*************** Initialize  variable   end **********************//
/*  Declare functions  we defineded start   */
void showdata();
void changdata(int);
void rstordata(int);
void process_over();
int chkerr();
/*  Declare functions  we defineded end   */
void main()        //main function
{
 int i=0,j=0;
 char flag;
 showdata();//show message about Initialzed
enter:
 {
  printf("请输入需申请资源的进程号(从0到");
  printf("%d",process-1);
  printf("):");
  scanf("%d",&i);
 }
 if(i<0||i>=process)
 {
  printf("输入的进程号不存在,重新输入!\n");
  goto enter;
 }
err:
 {
  printf("请输入进程");
  printf("%d",i);
  printf("申请的资源数\n");
  printf("类别:ABC\n");
  printf("");
  for(j=0;j<resource;j++)
  {
   scanf("%d",&request[j]);
   if(request[j]>need[i][j])
   {
    printf("%d",i);
    printf("号进程");
    printf("申请的资源数>进程");
    printf("%d",i);
    printf("还需要");
    printf("%d",j);
    printf("类资源的资源量!申请不合理,出错!请重新选择!\n");
    goto err;
   }
   else
   {
    if(request[j]>available[j])
    {
     printf("进程");
     printf("%d",i);
     printf("申请的资源数大于系统可用");
     printf("%d",j);
     printf("类资源的资源量!申请不合理,出错!请重新选择!\n");
     goto err;
    }
   }
  }
 }
 changdata(i);
 if(chkerr())
 {
  rstordata(i);
  showdata();
 }
 else
 {
  process_over(i);
  showdata();
 }
 printf("\n");
 printf("按'y'或'Y'键继续,否则退出\n");
 flag=getch();
 if(flag=='y'||flag=='Y')
 {
  goto enter;
 }
 else
 {
  exit(0);
 }
}
/*    Display status of resource used:showdata function start */
void showdata()
{
 int i,j;
 printf("系统可用资源向量:\n");
 printf("***Available***\n");
 printf("资源类别:A B C\n");
 printf("资源数目:");
 for(j=0;j<resource;j++)
 {
  printf("%d  ",available[j]);
 }
 printf("\n");
 printf("\n");
 printf("各进程还需要的资源量:\n");
 printf("******Need******\n");
 printf("资源类别:A B C\n");
 for(i=0;i<process;i++)
 {
  printf("");
  printf("%d",i);
  printf("号进程:");
  for(j=0;j<resource;j++)
  {
   printf("%d  ",need[i][j]);
  }
  printf("\n");
 }
 printf("\n");
 printf("各进程已经得到的资源量:\n");
 printf("***Allocation***\n");
 printf("资源类别:A B C\n");
 for(i=0;i<process;i++)
 {
  printf("");
  printf("%d",i);
  printf("号进程:");
  for(j=0;j<resource;j++)
  {
   printf("%d  ",allocation[i][j]);
  }
  printf("\n");
 }
 printf("\n");
}
/*    Display status of resource used:showdata function start */
/*Change variable value start*/
void changdata(int k)
{
 int j;
 for(j=0;j<resource;j++)
 {
  available[j]=available[j]-request[j];
  allocation[k][j]=allocation[k][j]+request[j];
  need[k][j]=need[k][j]-request[j];
 }
}
/*Change variable value end*/
/*restord variable value function start */
void rstordata(int k)
{
 int j;
 for(j=0;j<resource;j++)
 {
  available[j]=available[j]+request[j];
  allocation[k][j]=allocation[k][j]-request[j];
  need[k][j]=need[k][j]+request[j];
 }
}
/*restord variable value function end */
/*safety inspectionn function start*/
int chkerr()
{
 int WORK[resource],FINISH[process],temp[process];//temp[]:process execution sequence
 int i,j,m,k=0,count;
 for(i=0;i<process;i++)
  FINISH[i]=false;
 for(j=0;j<resource;j++)
  WORK[j]=available[j];
 for(i=0;i<process;i++)
 {
  count=0;
  for(j=0;j<resource;j++)
   if(FINISH[i]==false&&need[i][j]<=WORK[j])
    count++;
  if(count==resource)//All process:need<=work
  {
   for(m=0;m<resource;m++)
    WORK[m]=WORK[m]+allocation[i][m];
   FINISH[i]=true;
   temp[k]=i;
   k++;
   i=-1;
  }
 }
 for(i=0;i<process;i++)
  if(FINISH[i]==false)
  {
   printf("系统不安全!!!本次资源申请不成功!!!\n");
   return 1;
  }
  printf("\n");
  printf("经安全性检查,系统安全,本次分配成功。\n");
  printf("\n");
  printf("本次安全序列:");
  for(i=0;i<process;i++)//display safety execution sequence
  {
   printf("进程");
   printf("%d",temp[i]);
   if(i<process-1)
    printf("->");
  }
  printf("\n");
  return 0;
}
/*safety inspectionn function end*/
/*=====Release resource when process over start===== */

void process_over(int k)
{
 int j;
 int flag=over;
  for(j=0;j<resource;j++)
  { 
   if(need[k][j]!=0)
    flag=runing;
  }
  if(flag==over)
  {
   printf("进程");
   printf("%d",k);
   printf("已获得所有资源,执行完毕,释放所占用资源\n");
   for(j=0;j<resource;j++)
   {
    available[j]=available[j]+allocation[k][j];
    need[k][j]=allocation[k][j];
    allocation[k][j]=0;
  }
 }
};
/*=====Release resource when process over end===== */

以下为该代码执行后效果截图:
以上为对于银行家算法学习整理心得,若有错误,望指正!
Thanks for your reading!

设计一个按时间片轮转法实现进程调度的程序。 [提示]: (1) 假定系统有五个进程,每一个进程用一个进程控制块PCB来代表。进程控制块的格式为: 进程名 指针 要求运行时间 已运行时间 状态 其中, 进程名——作为进程的标识,假设五个进程的进程名分别为P1,P2,P3,P4,P5。 指针——进程按顺序排成循环队列,用指针指出下一个进程的进程控制块的首地址,最后一个进程的指针指出第一个进程的进程控制块首地址。 要求运行时间——假设进程需要运行的单位时间数。 已运行时间——假设进程已经运行的单位时间数,初始值为“0”。 状态——有两种状态,“就绪”和“结束”,初始状态都为“就绪”,用“R”表示。当一个进程运行结束后,它的状态为“结束”,用“E”表示。 (2) 每次运行所设计的进程调度程序前,为每个进程任意确定它的“要求运行时间”。 (3) 把五个进程按顺序排成循环队列,用指针指出队列连接情况。另用一标志单元记录轮到运行的进程。例如,当前轮到P2执行,则有: 标志单元中内容为K2 , K1 P1 K2 P2 K3 P3 K4 P4 K5 P5 K2 K3 K4 K5 K1 2 3 1 2 4 1 0 0 0 0 R R R R R PCB1 PCB2 PCB3 PCB4 PCB5 (4) 进程调度总是选择标志单元指示的进程运行。由于本实习是模拟进程调度的功能,所以,对被选中的进程并不实际的启动运行,而是执行: 已运行时间+1 来模拟进程的一次运行,表示进程已经运行过一个单位的时间。 请同学注意:在实际的系统中,当一个进程被选中运行时,必须置上该进程可以运行的时间片值,以及恢复进程的现场,让它占有处理器运行,直到出现等待事件或运行满一个时间片。在这时省去了这些工作,仅用“已运行时间+1”来表示进程已经运行满一个时间片。 (5) 进程运行一次后,应把该进程的进程控制块中的指针值送到标志单元,以指示下一个轮到运行的进程。同时,应判断该进程的要求运行时间与已运行时间,若该进程的要求运行时间¹已运行时间,则表示它尚未执行结束,应待到下一轮时再运行。若该进程的要求运行时间=已运行时间,则表示它已经执行结束,应指导它的状态修改成“结束”(E)且退出队列。此时,应把该进程的进程控制块中的指针值送到前面一个进程的指针位置中。 (6) 若“就绪”状态的进程队列不为空,则重复上面的(4)和(5)的步骤,直到所有的进程都成为“结束”状态。 (7) 在所设计的程序中应有显示或打印语句,能显示或打印每次选中进程的进程名以及运行一次后进程队列的变化。 (8) 为五个进程任意确定一组“要求运行时间”,运行进程调度程序,显示或打印逐次被选中的进程名以及进程控制块的动态变化过程。 模拟多资源银行家算法 实习检查: (1)程序运行后,由检查教师输入系统初态(包括进程名和各进程已获得资源、尚需资源及当前系统可用资源情况。注意:进程数目和资源种类由检查教师动态确定); (2)由检查教师输入此时某一进程申请各资源情况,使用银行家算法,检测该请求是否安全。若安全,则显示分配后的资源分配矩阵、进程资源需求矩阵,当前可用资源情况,以及安全序列。若不安全,给出警告信息! 作业调度采用FCFS、SJF、响应比高者优先算法模拟设计作业调度程序。 [提示]: (1)每个作业的JCB中包括作业名、提交时刻、要求运行时间; (2)假设第一个作业提交时,系统中无正在执行的作业,即第一个作业一提交系统便调度该作业。 要求: 输入:一批作业中各作业的作业名、提交时刻、要求运行时间; 选择不同的作业调度程序运行; 输出:相应作业调度算法下,各作业的等待时间、周转时间、带权周转时间,这批作业的调度顺序、平均周转时间和平均带权周转时间。
银行家算法是避免死锁的一种重要方法,本程序用java编程语言对其进行了实现。 当用户申请一组资源时,系统必须做出判断,如果把这些资源分出去,系统是否还处于安全状态。 若是,就可以分出这些资源;否则,该申请暂不予满足。 1.数据结构 假设有M个进程N类资源,则有如下数据结构: MAX[M*N] M个进程对N类资源的最大需求量 AVAILABLE[N] 系统可用资源数 ALLOCATION[M*N] M个进程已经得到N类资源的资源量 NEED[M*N] M个进程还需要N类资源的资源量 2.银行家算法 设进程I提出请求Request[N],则银行家算法按如下规则进行判断。 (1)如果Request[N]<=NEED[I,N],则转(2);否则,出。 (2)如果Request[N]<=AVAILABLE,则转(3);否则,出。 (3)系统试探分配资源,修改相关数据: AVAILABLE=AVAILABLE-REQUEST ALLOCATION=ALLOCATION+REQUEST NEED=NEED-REQUEST (4)系统执行安全性检查,如安全,则分配成立;否则试探险性分配作废,系统恢复原状,进程等待。 3.安全性检查 (1)设置两个工作向量WORK=AVAILABLE;FINISH[M]=FALSE (2)从进程集合中找到一个满足下述条件的进程, FINISH[i]=FALSE NEED<=WORK 如找到,执行(3);否则,执行(4) (3)设进程获得资源,可顺利执行,直至完成,从而释放资源。 WORK=WORK+ALLOCATION FINISH=TRUE GO TO 2 (4)如所有的进程Finish[M]=true,则表示安全;否则系统不安全。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值