在学习银行家算法之前,我们首先要了解以下几个概念:
死锁:多个进程在执行过程中,因为进程资源会造成相互等待的局面。如果没有外力作用,这些进程将永远无法向前推进。此时称系统处于死锁状态或者系统产生了死锁。
安全序列:某系统按某种顺序并发进程,并使它们都能达到获得最大资源而顺序完成序列为安全序列。
安全状态:能找到安全序列的状态称为安全状态。安全状态不会导致死锁。
不安全状态:在当前状态下不存在安全序列,则系统处与不安全状态。
注:安全状态一定不死锁,死锁一定不安全,但不安全 不一定死锁
我们需要了解到操作系统的中,进程的三态模型
这就要问了:什么是进程?
定义:系统总正在运行的一个程序,比如我们现在打开的浏览器就可以说是一个进程
接下来我们来说说进程的三种基本状态:
一、就绪状态(Ready):
进程以获得除处理器外的所需资源,等待分配处理器资源;只要分配了处理器资源,进程就可以执行。就绪进程可以按多个优先级来划分队列。例如,当一个进程由于时间片用完而进行就绪状态时,排入低优先队列;当进程有I/O操作完成而进入就绪状态时,排入高优先队列。
二、运行状态(Running):
进程占用处理器资源;处于此状态的进程的数目小于等于处理器的数目。在没有其他进程可以执行时(如所有进程都在阻塞状态),通常会自动执行系统的空闲进程。(空闲进程:Windows页面内存管理进程。)
三、阻塞状态(Blocked):
由于进程等待某种条件(如I/O操作或进程同步),在条件满足之前无法继续执行。该事件发生前即使把处理器资源分配给该进程,也无法运行。
三种状态转换如下图所示:
银行家算法
介绍:银行家算法顾名思义是来源于银行的借贷业务,一定数量的本金要满足多个客户的借贷周转,
为了防止银行家资金无法周转而倒闭,对每一笔贷款,必须考察其是否能限期归还。
在操作系统中研究资源分配策略时也有类似问题,系统中有限的资源要供多个进程使用,必须
保证得到的资源的进程能在有限的时间内归还资源,以供其它进程使用资源。如果资源分配不当,
就会发生进程循环等待资源,则进程都无法继续执行下去的死锁现象。
当一进程提出资源申请时,银行家算法执行下列步骤以决定是否向其分配资源:
1)检查该进程所需要的资源是否已超过它所宣布的最大值。
2)检查系统当前是否有足够资源满足该进程的请求。
3)系统试探着将资源分配给该进程,得到一个新状态。
4)执行安全性算法,若该新状态是安全的,则分配完成;若新状态是不安全的,则恢复原状
态,阻塞该进程。
以下是银行家算法所用到的主要数据结构:
1)可用资源向量available:它记录系统中各类资源的当前可利用数目。它是个含m个元素的数组,其中每一个元素代表一类可利用的资源数目,即Available[jJ=K,表示系统中现有j类资源K个。
2)最大需求矩阵max:它是记录每个进程对各类资源的最大需求量。这是一个n×m的矩阵,如果Max[i,j]=K,则表示进程i需要Rj类资源的最大数目为K。
3)分配矩阵allocation:它记录每个进程当前对各类资源当前的占有量。这也是一个n×m的矩阵,如果Allocation[i,j]=K,则表示进程i当前已分得Rj类资源的 数目为K。
4)需求矩阵need:它记录每个进程都各类资源尚需要的数目,等于最大需求矩阵与分配矩阵的差。
5)请求向量request:它记录某个进程对当前资源的申请量,是银行家算法的入口参数。
通过上面的学习,接下来,我们对银行家算法进行如下的描述:
由上面可以知道”请求向量request“是银行家算法的入口,所以设进程Pi先系统提出requesti资源请求
(1)如果requesti>need,进程Pi出错
(2)如果requesti>available,进程Pi阻塞
(3)系统试着把资源分配给进程Pi,并对相应数据结构做如下修改:
available-request;allocation+request,need-request
(4)系统执行安全性检测子算法,以判断试分配后系统状态是否安全
(5)如果(4)返回逻辑真值,即”安全“,则完成本次分配,返回
(6)否则,撤销本次试分配,进程阻塞
具体代码如下:
#include<iostream>
#include<stdio.h>
using namespace std;
// p 进程数,r资源种类
int p ;
int r ;
int maxs[10][10]; //最大需求矩阵
int allocation[10][10]; //分配矩阵
int need[10][10]; //需求矩阵
int available[10]; //可用资源向量
int request[10]; //请求向量当前进程对各类资源的申请量,算法的入口参数
//输入函数
void infInput()
{
int i,j;
cout<<"请输入最大需求矩阵max\n";
for(i=0; i<p; i++)
{
for(j=0; j<r; j++)
{
cin>>maxs[i][j];
}
}
cout<<"请输入分配矩阵allocation\n";
for(i=0; i<p; i++)
{
for(j=0; j<r; j++)
{
cin>>allocation[i][j];
}
}
cout<<"请输入需求矩阵need\n";
for(i=0; i<p; i++)
{
for(j=0; j<r; j++)
{
cin>>need[i][j];
}
}
cout<<"请输入可用资源向量available\n";
for(i=0; i<r; i++)
{
cin>>available[i];
}
}
//比较函数
//比较进程为m中的元素全大于n中的元素返回1,否则返回0
int compare(int m[],int n[])
{
int i;
for(i=0; i<r; i++)
{
if(m[i]<n[i])
{
return 0;
}
}
return 1;
}
//安全性检验函数,检测是否存在安全序列
int stest()
{
int i,j,k,l,flag=0;
int finish[p];
int work[r];
for(i=0; i<p; i++)
{
finish[i]=0;
//vis为1即表示available满足第i进程的资源需要
}
for(i=0; i<r; i++)
{
work[i]=available[i];
}
cout<<"分配序列:\n";
cout<<" allocation need avilable"<<endl;
for(k=0; k<p; k++)
{
for(i=0; i<p; i++)
{
if(finish[i]==1)
{
continue;
}
else
{
if(compare(work,need[i]))//available>=need
{
finish[i]=1;
cout<<'\n'<<"进程"<<i+1<<'\t';
flag=1;
for (j =0; j<r; j++)
{
printf(" %2d ", allocation[i][j]);
}
cout<<" ";
for (j = 0; j < r; j++)
{
printf(" %2d ", need[i][j]);
}
cout<<" ";
for (j = 0; j <r; j++)
{
printf(" %2d ", work[j] +allocation[i][j]);
}
for(l=0; l<r; l++)
{
work[l]=work[l]+allocation[i][l];
//进程完成,释放资源
}
break;
}
}
if(flag==1)
{
break;
}
}
}
cout<<'\n';
for(l=0; l<p; l++)
{
if(finish[l]==0)
{
return 0;//不存在安全序列
}
}
return 1;//存在安全序列
}
//申请进程后的安全性检验函数
void rtest(int n)
{
int j;
//n=n-1;
if(compare(available,request)&&compare(need[n-1],request))//available>=request 并且 need >=request
{
for(j=0; j<r; j++)
{
allocation[n-1][j]=allocation[n-1][j]+request[j];
need[n-1][j]=need[n-1][j]-request[j];
available[j]=available[j]-request[j];
}
if(stest())
{
cout<<"允许"<<n<<"进程申请资源!\n";
}
else
{
cout<<"不允许"<<n<<"进程申请资源!\n";
for(j=0; j<r; j++)
{
allocation[n-1][j]=allocation[n-1][j]-request[j];
need[n-1][j]=need[n-1][j]+request[j];
available[j]=available[j]+request[j];
}
}
}
else
{
cout<<"申请资源量越界!\n";
}
}
int main()
{
int i,n; //n-第n个资源申请
cout<<"请输入进程数:";
cin>>p;
cout<<"请输入资源种类数:";
cin>>r;
//默认状态4、3
infInput();//输入函数
if(stest()==1)
{
cout<<"存在安全序列,初始状态安全。\n";
}
else
{
cout<<"不存在安全序列,初始状态不安全。\n";
}
cout<<"请输入发出请求向量request的进程编号:";
cin>>n;
cout<<"请输入请求向量request\n";
for(i=0; i<r; i++)
{
cin>>request[i];
}
rtest(n);
return 0;
}