操作系统实验报告

实验2 银行家算法的实现



一、实验内容

银行家算法的实现。


二、实验目的

银行家算法是一种最有代表性的避免死锁的算法。在避免死锁方法中允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次分配资源的安全性,若分配不会导致系统进入不安全状态,则分配,否则等待。通过编写一个模拟动态资源分配的银行家算法程序,帮助学生进一步深入理解死锁、产生死锁的必要条件、安全状态等重要概念,并掌握避免死锁的具体实施方法。


三、实验原理

3.1、银行家算法中的数据结构

(1)可利用资源向量(Available)

是个含有m个元素的数组,其中的每一个元素代表一类可利用的资源数目。如果Available[j]=K,则表示系统中现有Rj类资源K个。

(2)最大需求矩阵(Max)

这是一个n×m的矩阵,它定义了系统中n个进程中的每一个进程对m类资源的最大需求。如果Max[i,j]=K,则表示进程i需要Rj类资源的最大数目为K。

(3)分配矩阵(Allocation)

这也是一个n×m的矩阵,它定义了系统中每一类资源当前已分配给每一进程的资源数。如果Allocation[i,j]=K,则表示进程i当前已分得Rj类资源的数目为K。

(4)需求矩阵(Need)

这也是一个n×m的矩阵,用以表示每一个进程尚需的各类资源数。如果Need[i,j]=K,则表示进程i还需要Rj类资源K个,方能完成其任务。
Need[i,j]=Max[i,j]-Allocation[i,j]

3.2、银行家算法

设Requesti是进程Pi的请求向量,如果Requesti[j]=K,表示进程Pi需要K个Rj类型的资源。当Pi发出资源请求后,系统按下述步骤进行检查:

(1)如果Requesti[j]≤Need[i,j],便转向步骤(2);否则认为出错,因为它所需要的资源数已超过它所宣布最大值。

(2)如果Requesti[j]≤Available[j],便转向步骤(3);否则,表示尚无足够资源,Pi须等待。

(3)系统试探着把资源分配给进程Pi,并修改下面数据结构中的数值:

Available[j]=Available[j]-Requesti[j];
Allocation[i,j]=Allocation[i,j]+Requesti[j];
Need[i,j]=Need[i,j]-Requesti[j];

系统执行安全性算法,检查此次资源分配后,系统是否处于安全状态。若安全,才正式将资源分配给进程Pi,以完成本次分配;否则,将本次的试探分配作废,恢复原来的资源分配状态,让进程Pi等待。

3.3、安全性算法

(1)设置两个向量:

工作向量Work: 它表示系统可提供给进程继续运行所需的各类资源数目,它含有m个元素,在执行安全算法开始时,Work=Available;
工作向量Finish: 它表示系统是否有足够的资源分配给进程,使之运行完成。开始时先做Finish[i]=false; 当有足够资源分配给进程时, 再令Finish[i]=true。

(2)从进程集合中找到一个能满足下述条件的进程:

Finish[i]=false;
Need[i,j]≤Work[j];若找到,执行 (3),否则,执行 (4)。

(3)当进程Pi获得资源后,可顺利执行,直至完成,并释放出分配给它的资源,故应执行:

Work[j]= Work[j]+ Allocation[i,j];
Finish[i]= true;
go to step 2;

(4)如果所有进程的Finish[i]=true都满足, 则表示系统处于安全状态;否则,系统处于不安全状态。


四、算法流程图

流程图


五、源程序及注释

#include <bits/stdc++.h>
using namespace std;
#define processNum 5//进程数 
#define resourceNum 3//资源类别 

int p;//初始状态
int work[resourceNum];//系统中的可用资源 
int Request[resourceNum];//请求的各类资源
bool Finish[processNum];//判断各类资源是否用完
int Available[resourceNum];//可利用资源
int Max[processNum][resourceNum];//最大的需求
int Need[processNum][resourceNum];//需求矩阵 
int Allocation[processNum][3];//分配矩阵 

void init(){

	cout <<"手动输入测试数据" << endl; 
	for(int i = 0; i < resourceNum; i++)
		cin >> Available[i];//输入可利用资源
	for(int i = 0; i < processNum; i++)
		for(int j = 0; j < resourceNum; j++)
			cin >> Max[i][j];//输入可利最大的需求
	for(int i = 0; i < processNum; i++)
		for(int j = 0; j < resourceNum; j++)
			cin >> Need[i][j];//输入需求矩阵
	for(int i = 0; i < processNum; i++)
		for(int j = 0; j < 3; j++)
		cin >> Allocation[i][j];//输入分配矩阵
}

/*测试数据 
3 3 2
7 5 3 3 2 2 9 0 2 2 2 2 4 3 3
7 4 3 1 2 2 6 0 0 0 1 1 4 3 1
0 1 0 2 0 0 3 0 2 2 1 1 0 0 2
*/
 
//输出初始化的信息表
void print1(){

    cout <<"系统剩余资源数:"<< endl;
    for(int j = 0;j < resourceNum;j++)
        cout << Available[j] << "\t";
    cout << endl;
    cout << "——————前资源分配状态——————" << endl;
    cout << "process——Max——Allocation——Need" << endl;
    for(int i = 0;i < processNum;i++){
    	cout << "p" << i << "\t";
        for(int j = 0;j < resourceNum;j++)
        	cout <<  Max[i][j] << " ";//输出进程需要的最大需求量 
        cout << "\t";
        for(int j = 0;j < resourceNum;j++)
        	cout <<  Allocation[i][j] << " ";//输出进程的各类资源的分配
        cout << "\t";
        for(int j = 0;j < resourceNum;j++)
        	cout <<  Need[i][j] << " ";//输出各类资源仍需要的资源数目 
        cout << endl;
    }
}

void print2(int i){

    int j;
    if(Need[i][0] == 0 && Need[i][1] == 0 && Need[i][2] == 0){
   	    for(int k = 0; k  < resourceNum; k++){
      		work[k] += Allocation[i][k];
      		Available[k] += Allocation[i][k];
        }
    }
    cout << "p" << i << "\t";  
    for(j = 0; j < resourceNum; j++)
    	cout <<  work[j];//输出系统中的可用资源 
    cout << "\t"    
    for(j = 0; j < resourceNum; j++)
    	cout <<  Need[i][j];//输出各类资源仍需要的资源数目 
    cout << "\t";
    for(j = 0; j < resourceNum; j++)
    	cout <<  Allocation[i][j];//输出进程的各类资源的分配
    cout << "\t";
    for(j = 0; j < resourceNum; j++)
    	cout <<  work[j];
    cout << "\t";
    for(j = 0; j < resourceNum; j++)
        if(!Finish[i])	break;
	if(j == resourceNum)	cout << "True\t" << endl;
    else	cout << "False\t" << endl;
}

//进程不安全,回收预分配的资源
void recycle(){

    int j;
    for(j = 0;j < resourceNum;j++){
        Need[p][j] += Request[j];
        Available[j] += Request[j];
        Allocation[p][j] -= Request[j];
    }
    cout << "系统进程资源状态不改变!" <<endl;
}

//检测分配是否安全
void Test_safety(){

    int i,j,te;
    int finish = 0,Done = 0; //Done一轮遍历下完成的,finish总共完成的
    int safeseries[processNum] = {-1,-1,-1,-1,-1};
    //初始化
    for(i = 0;i < processNum;i++)
        Finish[i] = false;
    for(j = 0;j < resourceNum;j++)
        work[j] = Available[j]; //初始值等于Available;
    // 查找未完成进程,且当前进程尚需资源不大于系统剩余资源;
    i = 0;

    while(finish != processNum){
        j = 0;
        if(Finish[i] == false){//如果这个进程的还需要的各类资源还大于系统当前的资源的;      
          	for(j = 0;j < resourceNum;j++)
                if(Need[i][j] > work[j]) break;
        }

        if(j == resourceNum){//此时代表当前的系统资源可以满足这个进程
		//那么可以对这个进程的资源进程回收。 
            Finish[i] = true;//代表该进程已经被完成。 
            print2(i);
            safeseries[finish++] = i; //记录下安全序列
            for(j = 0;j < resourceNum;j++)//开始资源的回收 
                work[j] += Allocation[i][j];
        }
        i++; //下一个进程
        //一轮遍历后,判断是否还有可分配进程
        if(i >= processNum){
            i = i % processNum;
            if(Done == finish)	break;//判断本轮完成进程是否等于上一轮,是则代表没有可执行进程          
            else Done = finish; //否则将本轮完成进程数赋值给Done
        }
    }

    if(finish == processNum){
        printf("进程P%d请求通过,此时安全序列为:",p);
        for(i = 0;i < processNum;i++)
        	cout << safeseries[i];
        cout << endl;
        print1(); //打印出此刻系统资源分配状态
    }else{
        recycle();
        printf("进程死锁,进程P%d请求无法通过!\n",p);
        print1();
    }
}

void judge_assign(){

    int j;
    for(j = 0;j < resourceNum;j++){
        //当前请求资源加上已分配资源不能大于最大需求资源;
        if(Request[j] + Allocation[p][j] > Max[p][j]){
        	cout <<"当前请求资源+已分配资源>最大需求资源:无法满足!错误!"<< endl;
            break;
        }
        //当前请求资源不能大于系统现有资源;
        if(Request[j] > Available[j]){
        	cout <<"当前请求资源>系统现有资源:无法满足!错误!"<< endl;
            break;
        }
    }

    if(j == resourceNum){
        //尝试分配资源
        for(j = 0;j < resourceNum;j++){
            Need[p][j] -= Request[j];
            Available[j] -= Request[j];
            Allocation[p][j] += Request[j];
        }
        //检查此时系统的安全性     
    	cout << "——————安全序列——————" << endl;
    	cout << "process——Work——Need——Allocation——work+allocation——finish"<< endl;
        Test_safety();
    }
}

int main(){

	init();
    print1();
    cout << "——————此时安全序列——————" << endl;
    cout << "process——Work——Need——Allocation——work+allocation——finish"<< endl;
    Test_safety();
    while(1){
    	cout << "存在进程0,1,2,3,4,资源类别0,1,2\n请依次输入请求资源的进程和进程请求的A,B,C类资源数\n例如:1 0 0 1" << endl;
        cin >> p;
        for(int i = 0;i < resourceNum;i++)
            cin >> Request[i];       
        judge_assign();//尝试分配资源给进程
    }
    return 0;
}

六、打印的程序运行时初值和运行结果

初值
运行结果


七、实验小结

通过本次实验初步实现了对银行家算法的模拟,要求实现的功能较多,故实际实践起来有一定困难,实验课上时间内未完成,在课余时间修改调试。程序中大多使用全局数组为了方便程序调用,因而没有实现手动输入控制进程个数和资源种类个数,只能对宏定义进行修改达到目的。空闲时间会进一步对细节方面进行完善和优化。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值