一、实验目的
1、了解什么是操作系统安全状态和不安全状态;
2、了解如何避免系统死锁;
3、理解银行家算法是一种最有代表性的避免死锁的算法,掌握其实现原理及实现过程。
二、实验内容
根据银行家算法的基本思想,编写和调试一个实现动态资源分配的模拟程序,并能够有效避免死锁的发生。
三、 实验原理
进程申请资源时,系统通过一定的算法判断本次申请是否不可能产生死锁(处于安全状态)。若可能产生死锁(处于不安全状态),则暂不进行本次资源分配,以避免死锁。算法有著名的银行家算法。
1、什么是系统的安全状态和不安全状态?
所谓安全状态,是指如果系统中存在某种进程序列<P1,P2,…,Pn>,系统按该序列为每个进程分配其所需要的资源,直至最大需求,则最终能使每个进程都可顺利完成,称该进程序列<P1,P2,…,Pn,>为安全序列。
如果不存在这样的安全序列,则称系统处于不安全状态。
2、银行家算法
把操作系统看作是银行家,操作系统管理的资源相当于银行家管理的资金,进程向操作系统请求分配资源相当于用户向银行家贷款。
为保证资金的安全,银行家规定:
(1) 当一个顾客对资金的最大需求量不超过银行家现有的资金时就可接纳该顾客;
(2) 顾客可以分期贷款,但贷款的总数不能超过最大需求量;
(3) 当银行家现有的资金不能满足顾客尚需的贷款数额时,对顾客的贷款可推迟支付,但总能使顾客在有限的时间里得到贷款;
(4) 当顾客得到所需的全部资金后,一定能在有限的时间里归还所有的资金。
操作系统按照银行家制定的规则设计的银行家算法为:
(1)进程首次申请资源的分配:如果系统现存资源可以满足该进程的最大需求量,则按当前的申请量分配资源,否则推迟分配。
(2)进程在执行中继续申请资源的分配:若该进程已占用的资源与本次申请的资源之和不超过对资源的最大需求量,且现存资源能满足该进程尚需的最大资源量,则按当前申请量分配资源,否则推迟分配。
(3)至少一个进程能完成:在任何时刻保证至少有一个进程能得到所需的全部资源而执行到结束。
银行家算法通过动态地检测系统中资源分配情况和进程对资源的需求情况来决定如何分配资源,并能在确保系统处于安全状态时才把资源分配给申请者,从而避免系统发生死锁。
四.实验程序及结果
#include
#include
#include
#define true 1
#define false 0
#define processNum 5
#define resourceNum 3
#define MAXINT 9999
typedef int bool;
int available[resourceNum]={3,3,2};
int maxRequest[processNum][resourceNum]={7,5,3,3,2,2,9,0,2,2,2,2,4,3,3};
int allocation[processNum][resourceNum]={0,1,0,2,0,0,3,0,2,2,1,1,0,0,2};
int need[processNum][resourceNum]={7,4,3,1,2,2,6,0,0,0,1,1,4,3,1};
bool Finish[processNum];
int safeSeries[processNum]={MAXINT, MAXINT , MAXINT , MAXINT , MAXINT};
int request[resourceNum];
bool Finish1[processNum];//已释放进程为true,未释放为false
void randon_init() //随机初始化
{
int i, j;
srand((unsigned) (time(NULL))); //随机数
//scanf("%d %d",&processNum,&resourceNum);
printf("输入进程数量上限、资源数量上限\n");
printf("%d %d",processNum,resourceNum);
printf("\n当前资源可用数目\n");
for(i = 0; i < resourceNum; i++){
available[i] = rand() % 2 + 2;
printf("%d ",available[i]);
}
printf("\n随机生成最大需求矩阵\n");
for(i = 0; i < processNum; i++){
for(j = 0; j < resourceNum; j++){
maxRequest[i][j] = (rand() % 6 + 2);
printf("%d ",maxRequest[i][j]);
}
printf("\n");
}
printf("随机生成已分配矩阵\n");
for(i = 0; i < processNum; i++){
for(j = 0; j < resourceNum; j++){
allocation[i][j] = rand() % 4 +1;
if (allocation[i][j] > maxRequest[i][j])
{
allocation[i][j] =0;
}
printf("%d ",allocation[i][j]);
}
printf("\n");
}
printf("当前需求矩阵\n");
for(i = 0; i < processNum; i++){
for(j = 0; j < resourceNum; j++){
need[i][j] = maxRequest[i][j] - allocation[i][j];
printf("%d ",need[i][j]);
}
printf("\n");
}
}
void showInfo()
{
int i,j;
printf("当前资源剩余:");
for(j = 0; j < resourceNum; j++){
printf("%d ",available[j]);
}
printf("\n");
printf(" PID\t Max\t\tAllocation\tNeed\n");
for(i = 0; i < processNum; i++){
printf(" P%d\t",i);
for(j = 0; j < resourceNum; j++){
printf("%d ",maxRequest[i][j]);
}
printf("\t\t");
for(j = 0; j < resourceNum; j++){
printf("%d ",allocation[i][j]);
}
printf("\t\t");
for(j = 0; j < resourceNum; j++){
printf("%d ",need[i][j]);
}
printf("\n");
}
}
bool isSafe()
{
int i,j,k;
int trueFinished = 0;
int work[resourceNum];
for(i = 0; i < resourceNum; i++){
work[i]=available[i];
}
for(i = 0; i < processNum; i++){
Finish[i]=false;
}
i = 0;
int temp=0,temp0=0,flag=0;
while(trueFinished != processNum){
int j =0;
if(Finish[i]!= true){
for(j = 0; j < resourceNum; j++){
if(need[i][j] > work[j]){break;}
}
}
if(j == resourceNum){
Finish[i]=true;
SafeInfo(work,i);
for(k = 0; k < resourceNum; k++){
work[k]+=allocation[i][k];
}
safeSeries[trueFinished++] = i;
}
i++;
if(i >= processNum)
{
if(flag==0)
{
temp=trueFinished;
temp0=trueFinished;
}
i = i % processNum;
if(flag==1){
temp=trueFinished;
if(temp == temp0)
break;
else
temp0=temp;
}
flag=1;
}
temp = trueFinished;
}
if(trueFinished == processNum){
printf("\n系统安全!\n\n安全序列为:");
for(i = 0; i < processNum; i++){
printf("%d ",safeSeries[i]);
}
return true;
}
printf("******系统不安全!******\n");
return false;
}
void SafeInfo(int *work, int i)
{
int j;
printf(" P%d\t",i);
for(j = 0; j < resourceNum; j++){
printf("%d ",work[j]);
}
printf("\t\t");
for(j = 0; j < resourceNum; j++){
printf("%d ",need[i][j]);
}
printf("\t ");
for(j = 0; j < resourceNum; j++){
printf("%d ",allocation[i][j]);
}
printf("\t\t");
for(j = 0; j < resourceNum; j++){
printf("%d ",allocation[i][j]+work[j]);
}
printf("\n");
}
void resource_release(int curProcess)
{
for(int i = 0; i < resourceNum; i++){
available[i] += maxRequest[curProcess][i];
maxRequest[curProcess][i] = 0;
allocation[curProcess][i]=0;
}
Finish1[curProcess] = true;
}
//银行家算法
int main()
{
int i,j,curProcess;
int wheInit = 0;
printf("是否使用内置数据?0是,1否:");
scanf("%d",&wheInit);
if(wheInit)
randon_init(); //可以不使用,选用内置的数据进行测试
printf("---------------------------------------------------------\n");
showInfo();
printf("\n系统安全情况分析\n");
printf(" PID\t Work\t\tNeed\tAllocation\tWork+Allocation\n");
if(isSafe()){
printf("\n---------------------------------------------------------\n");
printf("\n输入要分配的进程:");
scanf("%d",&curProcess);
while(!Finish1[curProcess])
{
printf("\n输入要分配给进程P%d的资源:",curProcess);
for(j = 0; j < resourceNum; j++){
scanf("%d", &request[j]);
}
for(j = 0; j < resourceNum; j++){
if(request[j] <= need[curProcess][j])continue;
else{printf("ERROR!\n");break;}
}
if(j == resourceNum){
for(j = 0; j < resourceNum; j++){
if(request[j] <= need[curProcess][j])continue;
else{printf("资源不足,等待中!\n");break;}
}
if(j == resourceNum){
for(j = 0; j < resourceNum; j++){
available[j] -= request[j];
allocation[curProcess][j] += request[j];
need[curProcess][j] -= request[j];
}
printf("\n系统安全情况分析\n");
printf(" PID\t Work\t\tNeed\tAllocation\tWork+Allocation\n");
if(isSafe()){
printf("分配成功!\n");
showInfo();
printf("P%d执行完成\n",curProcess);
resource_release(curProcess); //资源释放
showInfo();
}else{
for(j = 0; j < resourceNum; j++){
available[j] += request[j];
allocation[curProcess][j] -= request[j];
need[curProcess][j] += request[j];
}
printf("分配失败!\n");
showInfo();
}
}
}
if(Finish[curProcess]==Finish1[curProcess])
{
int r=curProcess;
printf("\n输入0-4以外的数结束,其他继续:");
scanf("%d",&curProcess);
if(r==curProcess)
{
printf("\n输入0-4以外的数或重复输入结束,该进程已完成,请重新输入:");
scanf("%d",&curProcess);
}
if(curProcess>4||curProcess<0) return 0;}
}
}
}
/*
测试一:
是否使用内置数据?0是,1否:1
输入进程数量上限、资源数量上限
5 3
当前资源可用数目
3 2 3
随机生成最大需求矩阵
5 4 6
3 6 5
3 4 4
6 7 4
5 7 7
随机生成已分配矩阵
1 3 3
3 3 2
2 1 2
3 4 1
3 4 1
当前需求矩阵
4 1 3
0 3 3
1 3 2
3 3 3
2 3 6
---------------------------------------------------------
当前资源剩余:3 2 3
PID Max Allocation Need
P0 5 4 6 1 3 3 4 1 3
P1 3 6 5 3 3 2 0 3 3
P2 3 4 4 2 1 2 1 3 2
P3 6 7 4 3 4 1 3 3 3
P4 5 7 7 3 4 1 2 3 6
系统安全情况分析
PID Work Need Allocation Work+Allocation
******系统不安全!******
测试二:
是否使用内置数据?0是,1否:1
输入进程数量上限、资源数量上限
5 3
当前资源可用数目
2 3 2
随机生成最大需求矩阵
2 3 6
6 2 6
4 2 3
3 3 6
4 4 3
随机生成已分配矩阵
1 3 1
4 0 4
2 0 2
1 3 2
1 1 3
当前需求矩阵
1 0 5
2 2 2
2 2 1
2 0 4
3 3 0
---------------------------------------------------------
当前资源剩余:2 3 2
PID Max Allocation Need
P0 2 3 6 1 3 1 1 0 5
P1 6 2 6 4 0 4 2 2 2
P2 4 2 3 2 0 2 2 2 1
P3 3 3 6 1 3 2 2 0 4
P4 4 4 3 1 1 3 3 3 0
系统安全情况分析
PID Work Need Allocation Work+Allocation
P1 2 3 2 2 2 2 4 0 4 6 3 6
P2 6 3 6 2 2 1 2 0 2 8 3 8
P3 8 3 8 2 0 4 1 3 2 9 6 10
P4 9 6 10 3 3 0 1 1 3 10 7 13
P0 10 7 13 1 0 5 1 3 1 11 10 14
系统安全!
安全序列为:1 2 3 4 0
---------------------------------------------------------
输入要分配的进程:1
输入要分配给进程P1的资源:2 2 2
系统安全情况分析
PID Work Need Allocation Work+Allocation
P1 0 1 0 0 0 0 6 2 6 6 3 6
P2 6 3 6 2 2 1 2 0 2 8 3 8
P3 8 3 8 2 0 4 1 3 2 9 6 10
P4 9 6 10 3 3 0 1 1 3 10 7 13
P0 10 7 13 1 0 5 1 3 1 11 10 14
系统安全!
安全序列为:1 2 3 4 0 分配成功!
当前资源剩余:0 1 0
PID Max Allocation Need
P0 2 3 6 1 3 1 1 0 5
P1 6 2 6 6 2 6 0 0 0
P2 4 2 3 2 0 2 2 2 1
P3 3 3 6 1 3 2 2 0 4
P4 4 4 3 1 1 3 3 3 0
P1执行完成
当前资源剩余:6 3 6
PID Max Allocation Need
P0 2 3 6 1 3 1 1 0 5
P1 0 0 0 0 0 0 0 0 0
P2 4 2 3 2 0 2 2 2 1
P3 3 3 6 1 3 2 2 0 4
P4 4 4 3 1 1 3 3 3 0
输入0-4以外的数结束,其他继续:2
输入要分配给进程P2的资源:2 2 1
系统安全情况分析
PID Work Need Allocation Work+Allocation
P0 4 1 5 1 0 5 1 3 1 5 4 6
P1 5 4 6 0 0 0 0 0 0 5 4 6
P2 5 4 6 0 0 0 4 2 3 9 6 9
P3 9 6 9 2 0 4 1 3 2 10 9 11
P4 10 9 11 3 3 0 1 1 3 11 10 14
系统安全!
安全序列为:0 1 2 3 4 分配成功!
当前资源剩余:4 1 5
PID Max Allocation Need
P0 2 3 6 1 3 1 1 0 5
P1 0 0 0 0 0 0 0 0 0
P2 4 2 3 4 2 3 0 0 0
P3 3 3 6 1 3 2 2 0 4
P4 4 4 3 1 1 3 3 3 0
P2执行完成
当前资源剩余:8 3 8
PID Max Allocation Need
P0 2 3 6 1 3 1 1 0 5
P1 0 0 0 0 0 0 0 0 0
P2 0 0 0 0 0 0 0 0 0
P3 3 3 6 1 3 2 2 0 4
P4 4 4 3 1 1 3 3 3 0
输入0-4以外的数结束,其他继续:3
输入要分配给进程P3的资源:2 0 4
系统安全情况分析
PID Work Need Allocation Work+Allocation
P1 6 3 4 0 0 0 0 0 0 6 3 4
P2 6 3 4 0 0 0 0 0 0 6 3 4
P3 6 3 4 0 0 0 3 3 6 9 6 10
P4 9 6 10 3 3 0 1 1 3 10 7 13
P0 10 7 13 1 0 5 1 3 1 11 10 14
系统安全!
安全序列为:1 2 3 4 0 分配成功!
当前资源剩余:6 3 4
PID Max Allocation Need
P0 2 3 6 1 3 1 1 0 5
P1 0 0 0 0 0 0 0 0 0
P2 0 0 0 0 0 0 0 0 0
P3 3 3 6 3 3 6 0 0 0
P4 4 4 3 1 1 3 3 3 0
P3执行完成
当前资源剩余:9 6 10
PID Max Allocation Need
P0 2 3 6 1 3 1 1 0 5
P1 0 0 0 0 0 0 0 0 0
P2 0 0 0 0 0 0 0 0 0
P3 0 0 0 0 0 0 0 0 0
P4 4 4 3 1 1 3 3 3 0
输入0-4以外的数结束,其他继续:4
输入要分配给进程P4的资源:3 3 0
系统安全情况分析
PID Work Need Allocation Work+Allocation
P0 6 3 10 1 0 5 1 3 1 7 6 11
P1 7 6 11 0 0 0 0 0 0 7 6 11
P2 7 6 11 0 0 0 0 0 0 7 6 11
P3 7 6 11 0 0 0 0 0 0 7 6 11
P4 7 6 11 0 0 0 4 4 3 11 10 14
系统安全!
安全序列为:0 1 2 3 4 分配成功!
当前资源剩余:6 3 10
PID Max Allocation Need
P0 2 3 6 1 3 1 1 0 5
P1 0 0 0 0 0 0 0 0 0
P2 0 0 0 0 0 0 0 0 0
P3 0 0 0 0 0 0 0 0 0
P4 4 4 3 4 4 3 0 0 0
P4执行完成
当前资源剩余:10 7 13
PID Max Allocation Need
P0 2 3 6 1 3 1 1 0 5
P1 0 0 0 0 0 0 0 0 0
P2 0 0 0 0 0 0 0 0 0
P3 0 0 0 0 0 0 0 0 0
P4 0 0 0 0 0 0 0 0 0
输入0-4以外的数结束,其他继续:0
输入要分配给进程P0的资源:1 0 5
系统安全情况分析
PID Work Need Allocation Work+Allocation
P0 9 7 8 0 0 0 2 3 6 11 10 14
P1 11 10 14 0 0 0 0 0 0 11 10 14
P2 11 10 14 0 0 0 0 0 0 11 10 14
P3 11 10 14 0 0 0 0 0 0 11 10 14
P4 11 10 14 0 0 0 0 0 0 11 10 14
系统安全!
安全序列为:0 1 2 3 4 分配成功!
当前资源剩余:9 7 8
PID Max Allocation Need
P0 2 3 6 2 3 6 0 0 0
P1 0 0 0 0 0 0 0 0 0
P2 0 0 0 0 0 0 0 0 0
P3 0 0 0 0 0 0 0 0 0
P4 0 0 0 0 0 0 0 0 0
P0执行完成
当前资源剩余:11 10 14
PID Max Allocation Need
P0 0 0 0 0 0 0 0 0 0
P1 0 0 0 0 0 0 0 0 0
P2 0 0 0 0 0 0 0 0 0
P3 0 0 0 0 0 0 0 0 0
P4 0 0 0 0 0 0 0 0 0
输入0-4以外的数结束,其他继续:0
输入0-4以外的数或重复输入结束,该进程已完成,请重新输入:0
*/
发现分配bug,修改后:
#include
#include
#include
#define true 1
#define false 0
#define processNum 5
#define resourceNum 3
#define MAXINT 9999
typedef int bool;
int available[resourceNum]={3,3,2};
int maxRequest[processNum][resourceNum]={7,5,3,3,2,2,9,0,2,2,2,2,4,3,3};
int allocation[processNum][resourceNum]={0,1,0,2,0,0,3,0,2,2,1,1,0,0,2};
int need[processNum][resourceNum]={7,4,3,1,2,2,6,0,0,0,1,1,4,3,1};
bool Finish[processNum];
int safeSeries[processNum]={MAXINT, MAXINT , MAXINT , MAXINT , MAXINT};
int request[resourceNum];
bool Finish1[processNum];//已释放进程为true,未释放为false
void randon_init() //随机初始化
{
int i, j;
srand((unsigned) (time(NULL))); //随机数
//scanf("%d %d",&processNum,&resourceNum);
printf("输入进程数量上限、资源数量上限\n");
printf("%d %d",processNum,resourceNum);
printf("\n当前资源可用数目\n");
for(i = 0; i < resourceNum; i++){
available[i] = rand() % 2 + 2;
printf("%d ",available[i]);
}
printf("\n随机生成最大需求矩阵\n");
for(i = 0; i < processNum; i++){
for(j = 0; j < resourceNum; j++){
maxRequest[i][j] = (rand() % 6 + 2);
printf("%d ",maxRequest[i][j]);
}
printf("\n");
}
printf("随机生成已分配矩阵\n");
for(i = 0; i < processNum; i++){
for(j = 0; j < resourceNum; j++){
allocation[i][j] = rand() % 4 +1;
if (allocation[i][j] > maxRequest[i][j])
{
allocation[i][j] =0;
}
printf("%d ",allocation[i][j]);
}
printf("\n");
}
printf("当前需求矩阵\n");
for(i = 0; i < processNum; i++){
for(j = 0; j < resourceNum; j++){
need[i][j] = maxRequest[i][j] - allocation[i][j];
printf("%d ",need[i][j]);
}
printf("\n");
}
}
void showInfo()
{
int i,j;
printf("当前资源剩余:");
for(j = 0; j < resourceNum; j++){
printf("%d ",available[j]);
}
printf("\n");
printf(" PID\t Max\t\tAllocation\tNeed\n");
for(i = 0; i < processNum; i++){
printf(" P%d\t",i);
for(j = 0; j < resourceNum; j++){
printf("%d ",maxRequest[i][j]);
}
printf("\t\t");
for(j = 0; j < resourceNum; j++){
printf("%d ",allocation[i][j]);
}
printf("\t\t");
for(j = 0; j < resourceNum; j++){
printf("%d ",need[i][j]);
}
printf("\n");
}
}
bool isSafe()
{
int i,j,k;
int trueFinished = 0;
int work[resourceNum];
for(i = 0; i < resourceNum; i++){
work[i]=available[i];
}
for(i = 0; i < processNum; i++){
Finish[i]=false;
}
i = 0;
int temp=0,temp0=0,flag=0;
while(trueFinished != processNum){
int j =0;
if(Finish[i]!= true){
for(j = 0; j < resourceNum; j++){
if(need[i][j] > work[j]){break;}
}
}
if(j == resourceNum){
Finish[i]=true;
SafeInfo(work,i);
for(k = 0; k < resourceNum; k++){
work[k]+=allocation[i][k];
}
safeSeries[trueFinished++] = i;
}
i++;
if(i >= processNum)
{
if(flag==0)
{
temp=trueFinished;
temp0=trueFinished;
}
i = i % processNum;
if(flag==1){
temp=trueFinished;
if(temp == temp0)
break;
else
temp0=temp;
}
flag=1;
}
temp = trueFinished;
}
if(trueFinished == processNum){
printf("\n系统安全!\n\n安全序列为:");
for(i = 0; i < processNum; i++){
printf("%d ",safeSeries[i]);
}
return true;
}
printf("******系统不安全!******\n");
return false;
}
void SafeInfo(int *work, int i)
{
int j;
printf(" P%d\t",i);
for(j = 0; j < resourceNum; j++){
printf("%d ",work[j]);
}
printf("\t\t");
for(j = 0; j < resourceNum; j++){
printf("%d ",need[i][j]);
}
printf("\t ");
for(j = 0; j < resourceNum; j++){
printf("%d ",allocation[i][j]);
}
printf("\t\t");
for(j = 0; j < resourceNum; j++){
printf("%d ",allocation[i][j]+work[j]);
}
printf("\n");
}
void resource_release(int curProcess)
{
for(int i = 0; i < resourceNum; i++){
available[i] += maxRequest[curProcess][i];
maxRequest[curProcess][i] = 0;
allocation[curProcess][i]=0;
}
Finish1[curProcess] = true;
}
void bank()
{
int i,j,curProcess;
int wheInit = 0;
printf("是否使用内置数据?0是,1否:");
scanf("%d",&wheInit);
if(wheInit)
randon_init(); //可以不使用,选用内置的数据进行测试
printf("---------------------------------------------------------\n");
showInfo();
printf("\n系统安全情况分析\n");
printf(" PID\t Work\t\tNeed\tAllocation\tWork+Allocation\n");
if(isSafe()){
printf("\n---------------------------------------------------------\n");
printf("\n输入要分配的进程:");
scanf("%d",&curProcess);
while(!Finish1[curProcess])
{
printf("\n输入要分配给进程P%d的资源:",curProcess);
for(j = 0; j < resourceNum; j++){
scanf("%d", &request[j]);
}
for(j = 0; j < resourceNum; j++){
if(request[j] <= need[curProcess][j])continue;
else{printf("ERROR!\n");break;}
}
if(j == resourceNum){
for(j = 0; j < resourceNum; j++){
if(request[j] <= need[curProcess][j])continue;
else{printf("资源不足,等待中!\n");break;}
}
if(j == resourceNum){
for(j = 0; j < resourceNum; j++){
available[j] -= request[j];
allocation[curProcess][j] += request[j];
need[curProcess][j] -= request[j];
}
printf("\n系统安全情况分析\n");
printf(" PID\t Work\t\tNeed\tAllocation\tWork+Allocation\n");
if(isSafe()){
printf("分配成功!\n");
showInfo();
printf("P%d执行完成\n",curProcess);
int all=1;
for(j = 0; j < resourceNum; j++){
if( allocation[curProcess][j]< maxRequest[curProcess][j]) all=0;
}
if(all)
{
resource_release(curProcess); //资源释放
showInfo();
}
}else{
for(j = 0; j < resourceNum; j++){
available[j] += request[j];
allocation[curProcess][j] -= request[j];
need[curProcess][j] += request[j];
}
printf("分配失败!\n");
showInfo();
}
}
}
if(Finish[curProcess]==Finish1[curProcess])
{
int r=curProcess;
printf("\n输入0-4以外的数结束,其他继续:");
scanf("%d",&curProcess);
if(r==curProcess)
{
printf("\n输入0-4以外的数或重复输入结束,该进程已完成,请重新输入:");
scanf("%d",&curProcess);
}
if(curProcess>4||curProcess<0) return 0;
}
else
{
printf("\n输入要分配的进程:");
scanf("%d",&curProcess);
Finish1[curProcess]=false;
}
}
}}
int main()
{
bank();
}