一.程序模块及流程
(1)本程序中重要模块主要包括以下模块:
1初始化void Init()
2安全性算法int Safety_Algorithm()
3试分配process* Attempt()
4测试void TestBanker()
(2)执行流程:
此银行家算法运用了链表来实现,首先建立进程链表块,每一个节点代表一个进程信息,每个进程的资源信息为数据结构中的数据信息。
1进行进程的初始化,存储当前的进程信息
2将信息打印输出在屏幕上
3调用安全性算法,检测当前系统是否处于安全状态,若处于安全状态,则进行下一步,若不安全则程序结束
4调用试分配函数,进行试分配,若试分配成功,修改相关数据结构,打印当前系统资源情况表,进行下一步,否则,重新接收其他请求向量。
5再次调用安全性算法,检查试分配以后的系统安全性,若安全则打印安全性序列和系统资源情况表,并选择是否继续操作。否则之前的试分配失败,返回试分配之前的数据结构,输出系统资源情况表,接收下一个进程请求。
二.主要函数说明:
void Insret_Tail(process **head, process node);//链表尾插
void Init(process **head, int m); //初始化系统资源
void Print(process *head, int *avail, int m);//打印当前系统资源情况表
void PrintSafety(process *head, int *safety, int work[][M], int m, int n);//打印试分配后安全状态的资源情况表
process* Location(process* head, int pro_num);//进程定位
process* Attempt(process* head, int *request, int *avail, int m);//试分配
process* CurRun(process* head, int*finish, int*work, int m, int n);//找到当前可执行进程(通过安全检查的进程)
void Change(process* p, int* work, int* finish, int record[][M], int m);//修改进程书信息
int Safety_Algorithm(process* head, int *avail, int *safety, int Record[][M], int m, int n);//安全性算法
void Back(process* p, int *request, int *avail, int m);//试分配失败后恢复分配前系统资源
void TestBanker();//测试函数
三.程序设计流程图:
四.测试结果:
五.源代码:
//banker.h
#include<windows.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define M 50 // 系统资源的种类
#define N 50 // 最大进程数
int n = 0;
typedef struct my_process
{
int num; //进程标号
int Max[M]; // 表示某个进程对某类资源的最大需求
int Allocation[M]; // 表示某个进程已分配到某类资源的个数
int Need[M]; // 表示某个进程尚需要某类资源的个数
struct my_process* next; //指向下一个进程节点
}process;
void Insret_Tail(process **head, process node) //尾插法建立进程链表
{
process* p = (process*)malloc(sizeof(process));
process* last = NULL;
memcpy(p, &node, sizeof(process)); //动态创建进程结点
p->next = NULL;
if (NULL == *head)
{
*head = p;
}
else //找表尾
{
last = *head;
while (last->next != NULL)
{
last = last->next;
}
last->next = p; //插入链尾
}
}
void Init(process **head, int m)//初始化系统资源
{
int n1 = n;
int i, j = 0;
for (int z = 0; z < n1; z++)
{
process node;
node.num = j++;
printf("请输入第 %d个进程信息 :\n", z + 1);
printf("最大需求矩阵: ");
for (i = 0; i<m; i++)
{
scanf_s("%d", &node.Max[i]);
}
printf("分配矩阵: ");
for (i = 0; i<m; i++)
{
scanf_s("%d", &node.Allocation[i]);
}
printf("\n");
for (i = 0; i<m; i++)
{
node.Need[i] = node.Max[i] - node.Allocation[i];
}
Insret_Tail(head, node); //插入链尾
}
}
void Print(process *head, int *avail, int m)//打印初始系统资源
{
process* p = NULL;
int count = 0;
int i, j;
char ch;
p = head;
if (NULL == p)
{
printf("当前无进程 !\n");
return;
}
else
{
printf("资源分配情况表:\n");
printf("\n |num| |Max| |Allocation| | Need | |Available| \n");
printf("\t");
for (i = 0; i<4; i++)
{
ch = 'A';
for (j = 0; j<m; j++)
{
printf("%4c", ch++);
}
printf("\t");
}
printf("\n");
while (p != NULL)
{
count++;
printf("%8d", p->num);
for (j = 0; j<m; j++)
{
printf("%4d", p->Max[j]);
}
printf("\t");
for (j = 0; j<m; j++)
{
printf("%4d", p->Allocation[j]);
}
printf("\t");
for (j = 0; j<m; j++)
{
printf("%4d", p->Need[j]);
}
printf("\t");
if (count == 1)
{
for (j = 0; j<m; j++)
{
printf("%4d", avail[j]);
}
}
printf("\n");
p = p->next;
}
printf("\n");
}
}
void PrintSafety(process *head, int *safety, int work[][M], int m, int n) //打印试分配后的系统资源状态
{
process* p = NULL;
int i, j;
p = head;
if (NULL == p)
{
exit(0);
}
else
{
printf("\n |Work+| ");
printf("\n|Process| |Work| |Need| |Allocation| |Allocation| |Finish|\n");
puts("");
for (i = 0; i<n; i++)
{
p = head;
while (p != NULL)
{
if (p->num == safety[i])
{
printf("%8d", p->num);
for (j = 0; j<m; j++)
{
printf("%4d", work[p->num][j]);
}
printf("\t");
for (j = 0; j<m; j++)
{
printf("%4d", p->Need[j]);
}
printf("\t");
for (j = 0; j<m; j++)
{
printf("%4d", p->Allocation[j]);
}
printf("\t");
for (j = 0; j<m; j++)
{
printf("%4d", work[p->num][j] + p->Allocation[j]);
}
for (j = 0; j<m - 2; j++)
{
printf("\ttrue");
}
break;
}
else
{
p = p->next;
}
}
puts("");
}
}
}
process* Location(process* head, int pro_num) //进程定位函数,找到当前请求进程在进程链表中的位置,以便后面对其操作
{
process *p = NULL;
p = head;
if (NULL == p)
{
printf("error !\n"); //异常,当前链表为空
return p;
}
else
{
while (p != NULL)
{
if (p->num == pro_num)
{
break;
}
else
{
p = p->next;
}
}
if (NULL == p) //无此进程,输入错误
{
printf("无此进程 !\n");
return p;
}
else
{
return p;
}
}
}
process* Attempt(process* head, int *request, int *avail, int m)//试分配
{
int num, i;
process* p = NULL;
printf("请输入进程编号: \n");
scanf_s("%d", &num);
p = Location(head, num);
if (NULL == p)
{
printf("无此进程!\n");
return p;
}
printf("请输入该进程的请求向量: \n");
for (i = 0; i<m; i++)
{
scanf_s("%d", &request[i]);
}
for (i = 0; i<m; i++) //请求的合法性检验
{
if (request[i] <= p->Need[i])
{
continue;
}
else
{
printf("该请求系统不能满足 !\n");
return NULL;
}
}
for (i = 0; i<m; i++)
{
if (request[i] <= avail[i])
{
continue;
}
else
{
printf("该请求系统不能满足 !\n");
return NULL;
}
}
for (i = 0; i<m; i++) //试分配,修改相关数据结构
{
avail[i] = avail[i] - request[i];
p->Allocation[i] = p->Allocation[i] + request[i];
p->Need[i] = p->Need[i] - request[i];
}
return p;
}
process* CurRun(process* head, int*finish, int*work, int m, int n)//找当前可执行的进程
{
int i = 0, j = 0, count = 0;
process* p = NULL;
while (1)
{
if (finish[i] != -1) //表示该进程未执行安全性检查
{
p = Location(head, finish[i]); //定位该进程
if (p != NULL)
{
for (j = 0; j<m; j++)
{
if (p->Need[j]>work[j])
{
break;
}
else
{
continue;
}
}
if (j == m)
{
return p;
}
else
{
i++; //当前进程检查没有通过,则进行下一个进程的检查
}
}
}
else
{
i++; //当前进程已经检查过,则进行下一个进程的检查
}
if (i == n)
{
return NULL; //遍历所有进程都未找到,则跳出返回NULL
}
}
}
void Change(process* p, int* work, int* finish, int record[][M], int m) //修改相关数据结构
{
int i;
for (i = 0; i<m; i++)
{
record[p->num][i] = work[i];
work[i] = work[i] + p->Allocation[i];
}
finish[p->num] = -1; //表示该进程已通过安全性检查
}
int Safety_Algorithm(process* head, int *avail, int *safety, int Record[][M], int m, int n)//安全性算法
{
int *work = NULL;
int *finish = NULL;
process *p = NULL;
process *pro = NULL;
int i, count = 0;
work = (int*)malloc(m*sizeof(int)); //当前系统可供给进程的各个资源数目
finish = (int*)malloc(n*sizeof(int)); //标志数组
p = head;
for (i = 0; i<m; i++)
{
work[i] = avail[i];
}
i = 0;
while (p != NULL)
{
finish[i] = p->num;
p = p->next;
i++;
}
i = 0;
while (count<n)
{
pro = CurRun(head, finish, work, m, n);
if (pro != NULL) //Need[i,j]<=work[j],即当前系统可以满足该进程
{
Change(pro, work, finish, Record, m);
count++;
safety[i] = pro->num;
i++;
}
else
{
printf("当前系统处于不安全状态 !\n");
break;
}
}
if (count == n)
{
printf("当前系统处于安全状态,存在一个安全序列 :\n");
for (i = 0; i<n; i++)
{
printf("%d,", safety[i]); //打印安全序列
}
puts("");
}
free(finish);
free(work);
finish = NULL;
work = NULL;
if (count == n)
{
return 1; //找到安全序列则返回1
}
else
{
return 0; //未找到安全序列则返回0
}
}
void Back(process* p, int *request, int *avail, int m) //若试分配失败,则恢复试分配前的资源状态
{
int i;
{
for (i = 0; i<m; i++)
{
p->Allocation[i] -= request[i];
p->Need[i] += request[i];
avail[i] += request[i];
}
}
}
#include"banker.h"
void TestBanker()
{
int i, flag = 0, count = 0;
char ch;
int mM;
int *p = NULL; //进程链头指针数组
int Available[M] = { 0 };/*其中每一个数组元素表示当前某类资源的可用数目,初始化为系统所提供的资源的最大数目*/
int Request[M] = { 0 };
int Record_work[N][M] = { 0 };
int Safety[N] = { 0 }; //存储安全序列,以便后面排序
process *head = NULL;
process *pro = NULL;
printf("请输入进程个数:");
scanf_s("%d", &n);
printf("请输入资源数目:");
scanf_s("%d", &mM);
printf("\n请初始化当前可用资源\n");
for (i = 0; i<mM; i++)
{
scanf_s("%d", &Available[i]);
}
Init(&head, mM);
Print(head, Available, mM);
do
{
flag = Safety_Algorithm(head, Available, Safety, Record_work, mM, n);
if (1 == flag)
{
printf("当前系统是安全的,可进行试探分配 !\n");
do
{
pro = Attempt(head, Request, Available, mM); //通过则试分配
if (NULL != pro)
{
printf("试分配成功 !\n");
Print(head, Available, mM);
break;
}
else // 否则,退到上一级
{
printf("当前请求系统不能满足 ! 请重新输入请求向量(Y/y),或者退出(N/n)\n\n");
printf("您是否要继续操作 (Y/N):\n");
getchar();
scanf_s("%c", &ch);
if (ch == 'N' || ch == 'n')
{
exit(0);
}
}
} while (ch == 'Y' || ch == 'y');
}
else //未通过安全性算法
{
printf("当前系统不安全,不能响应任何进程的请求 !\n");
return;
}
flag = Safety_Algorithm(head, Available, Safety, Record_work, mM, n);
if (1 == flag)
{
printf("分配成功!当前资源分配状态如下表 :\n");
PrintSafety(head, Safety, Record_work, mM, n);
printf("您是否还要继续操作 (Y(y)/N(y))\n");
getchar();
scanf_s("%c", &ch);
}
else
{
printf("当前系统处于不安全状态,恢复原来的资源分配状态 ! :\n");
Back(pro, Request, Available, mM);
Print(head, Available, mM);
printf("您是否还要继续操作 (Y(y)/N(y))\n");
getchar();
scanf_s("%c", &ch);
}
} while (ch == 'Y' || ch == 'y');
}
int main()
{
TestBanker();
system("pause");
return 0;
}