银行家算法 C语言
前言
操作系统实验记录–银行家算法
一、实验目的
1)掌握安全性检测原理
2)掌握银行家算法
二、实验要求
1、要求学生进一步掌握如何 死锁的避免,进一步熟练使用数 组进行程序的设计及实现。
2、实现银行家算法、安全性检测算法。
3. 实验环境
1)每人一组,独立完成实验内容。
2)个人电脑1台,linux系统,安装gcc和vi等软件。
三、银行家算法中的数据结构:
1)可利用资源向量Available
2)最大需求矩阵Max
3)分配矩阵Allocation
4)需求矩阵Need。
安全性算法:
为每个进程分配所需要的资源,直至满足全部进程都能够顺利执行,不产生死锁。即能够找到满足全部进程执行的安全序列(路径)。
银行家算法:
如果进程申请的资源没有超过范围,先假定将该资源分配给该进程,而后更新相关数据机构,判断分配资源后系统是否安全。如果安全,则可以分配,反之则不分配。
四、算法流程图
一、银行家算法是什么?
必须学会1
必须学会2
看完之后,请日思夜想,你已经是一个银行家,在偌大事务中,你首先要解决的是银行家算法。怎么来衡量自己对该算法是否过关:
1.你的“巨有钱银行”面临了什么问题?提示:项目人申请借款,借吗?
2.借款的标准是什么?提示:申请是否合理,借了之后会不会倒闭?
二、C语言代码(ubuntu下运行,已成功)
关于写代码的经验,模仿别人的代码,把知识装进自己的脑子里。先熟悉整个代码逻辑,一个一个函数地去理解,先知道该函数的大概作用,然后在debug的过程中(也就是把每个函数调通的过程,可以使用printf()函数来调),加深理解。后面就可以很好地用起来了,百炼成钢!
1.实现效果
2.代码及详细注释
//银行家算法完整版
# include <stdio.h>
# include <stdlib.h>
char NAME[100] = {0}; //资源名称
int Available[100]={0}; //可用资源数
int Max[50][100]={0}; //各个进程最大需求资源
int Need[50][100] = {0}; //各个矩阵实时所需资源
int Allocation[50][100] = {0}; //实时分配资源
int Request[50]={0}; //请求分配资源
int N=100; //设定的最大资源数
int M=50; //设定的最大进程数
//初始设定,包括初始的资源名称,资源数,进程数
//各个进程最大需求资源,和对各个进程初始分配的资源数
void init(){
int i=0,j=0,m=0,n=0; //i,j用来做循环,n,m分别用来更新最大资源数和进程数
int number=0,flag=0; //number用作记录单个资源数,falg标识数据是否异常,1为异常
char name=' ' ; //记录进程名的变量
int temp[100]={0}; //记录各类资源的使用情况
printf("系统可用资源种类为(<100):\n");
scanf("%d",&n);
N = n;
for(i=0;i<n;i++){
printf("资源%d的名称:\n",i+1);
getchar(); //这里地方一定要有,不然读不到name
scanf("%c",&name);
NAME[i] = name;
printf("资源%c的初始个数为:\n",name);
scanf("%d",&number);
Available[i] = number;
}
printf("\n请输入进程的数量(<50):");
scanf("%d",&m);
M = m;
printf("\n请输入各进程的最大需求矩阵的值[Max]:\n");
do{
flag = 0;
for(i=0;i<M;i++){
for(j = 0;j <N;j++){
scanf("%d",&Max[i][j]);
if(Max[i][j]>Available[j]){
flag = 1;
}
}
}
if(flag){
printf("\n资源最大需求量大于系统中资源最大量,请重新输入\n");
}
}while(flag);//获取合理的数据后退出
do{
flag = 0;
printf("请输入各进程已经分配的资源量[Allocation]:\n");
for(i=0;i<M;i++){
for(j = 0;j<N;j++){
scanf("%d",&Allocation[i][j]);
if(Allocation[i][j]>Max[i][j]){
flag = 1;
}
Need[i][j] = Max[i][j] - Allocation[i][j];
temp[j] += Allocation[i][j];
}
}
if(flag){
printf("分配的资源大于最大需求量,请重新输入!\n");
for(j = 0;j <N;j++){
temp[j] = 0; //这一步很重要,+=要及时清零
}
}
}while(flag);//获取合理数据
for(j = 0;j<N;j++){
Available[j] = Available[j] - temp[j];
//更新可用资源,减去分配给进程的资源
}
}
//输出初始化后的数据,调整格子的时候,让非制表符去适应制表符
//先在脑子里考虑整体,一个一个试t有点浪费时间
void showdata(){
int i,j;
printf("***************************************************************\n");
printf("系统目前可用的资源[Available]:\n");
for(i=0;i<N;i++){
printf("%c\t",NAME[i]);
}
printf("\n");
for(j=0;j<N;j++){
printf("%d\t",Available[j]);
}
printf("\n");
printf("系统当前的资源分配情况如下:\n");
printf("\tMax Allocation Need\n");
printf("进程名 ");
for(j=0;j<3;j++){
for(i = 0;i<N;i++){
printf("%c ",NAME[i]);
}
printf("\t ");
}
printf("\n");
//把数据数出来以后要检查一下,三个矩阵有加减关系
for(i = 0;i < M;i++){
printf("P%d\t",i+1);
for(j =0;j<N;j++){
printf("%d ",Max[i][j]);
}
printf("\t ");
for(j =0;j<N;j++){
printf("%d ",Allocation[i][j]);
}
printf("\t ");
for(j=0;j<N;j++){
printf("%d ",Need[i][j]);
}
printf("\n");
}
}
//预分配
void test(int i){
for(int j=0;j<N;j++){
Available[j] = Available[j] - Request[j];
Allocation[i][j] = Allocation[i][j] + Request[j];
Need[i][j] = Need[i][j] - Request[j];
}
}
//取消分配
void Retest(int i){
for(int j =0;j<N;j++){
Available[j] = Available[j] + Request[j];
Allocation[i][j] = Allocation[i][j] - Request[j];
Need[i][j] = Need[i][j] + Request[j];
}
}
int Safe()
{
int i,j,m,apply,k=0; //这里必须给k赋值为0,因为后面没有k的初始化
int Security[50]={0}; //安全序列
int Finish[50] = {0}; //完成标志
int Work[100] = {0}; //可用资源的替身
for(j = 0;j<N;j++){
Work[j] = Available[j];
}
for(i = 0;i <M;i++){
Finish[i] = 0; //一开始所有的都没完成
}
for(i=0;i<M;i++){
apply=0; //用来记录i进程中,是否所有资源都可需要
for(j =0;j<N;j++){
if(Finish[i]==0 && Need[i][j]<=Work[j]){
//保证i进程需要的资源,现有资源都能满足
//并且i资源还没有完成
apply++;//这个是判断是不是所有资源都能被满足
if(apply==N){
for(m=0;m<N;m++){
Work[m]=Work[m] + Allocation[i][m];
//i进程被c完成,回收分配给它的资源
}
Finish[i] = 1;//标志进程完成
Security[k++] = i+1; //先操作,后加
//记录安全序列,+1是因为要从1开始
i = -1; //从头找起,尽量去完成所有任务
}
}
}
}
for(i = 0;i <M;i++){
if(Finish[i]==0){
printf("系统不安全\n");
return 0;
}
}
printf("系统是安全的!\n");
printf("存在一个安全序列:");
for(i=0;i<M;i++){
printf("P%d",Security[i]);//输出安全序列
if(i<M-1){
printf("->");
}
}
printf("\n");
return 1;
}
void bank(){
int flag = 1; //申请资源是否合理标识
int i=0,j=0;
printf("请输入请求分配资源的进程号(1-%d):",M);
scanf("%d",&i);
printf("请输入进程P%d要申请的资源个数:\n",i);
for(j = 0;j<N;j++){
printf("%c----",NAME[j]);
scanf("%d",&Request[j]);
}
i = i-1;//涉及到输出的进程从1开始,看上去更自然,涉及矩阵从0开始
for(j =0;j<N;j++){
if(Request[j]>Need[i][j]){
printf("进程P%d申请的资源大于它需要的资源",i+1);
printf("分配不合理,不予分配!\n");
flag = 0;
break;
}
else if(Request[j]>Available[j]){
printf("进程%d申请的资源大于现有的资源",i+1);
printf("分配不合理,不予分配!\n");
flag = 0;
break;
}
}
if(flag){ //合理只是第一个条件,接下来就是看是否安全
test(i);
if(Safe){
printf("准了!!");
showdata();
}
else if(!Safe()){
Retest(i);
showdata();
}
}
}
int main(){
char choice;
printf("\t--------------------------------------------\n");
printf("\t|| ||\n");
printf("\t|| 银行家算法的实现 ||\n");
printf("\t|| ||\n");
printf("\t|| ||\n");
printf("\t--------------------------------------------\n");
init();
showdata();
if(!Safe()) {exit(0);}//避免一开始的要求就死锁
do{
printf("**********************************************\n");
printf("\n");
printf("\n");
printf("\t---------------银行家算法演示---------------\n");
printf(" R(r):请求分配 \n");
printf(" E(e):退出 \n");
printf("\t--------------------------------------------\n");
printf("请选择:\n");
getchar(); //获取字符,程序就等着键盘
scanf("%c",&choice);
switch(choice){
case'r':
case'R':
bank();
break;
case'e':
case'E':
exit(0);
}
}while(choice);
return 0;
}