写在前面
此项目为计算机操作系统课程设计,题目为编程序模拟银行家算法,是经过多方参考最终实现的简陋课设,以及相应的课程设计报告资料,可供同样需要完成相关课设的小伙伴参考使用。
链接: https://pan.baidu.com/s/1a-YKiG8peTqMhe9JopShBg?pwd=yg3k
提取码: yg3k 复制这段内容后打开百度网盘手机App,操作更方便哦
此链接为本次课设相关报告和源代码(后文也有贴出)资料,PPT是随便乱写的,做不得数,看看就行。网盘链接设置的永久有效,若失效可联系俺要链接。
温馨提示:网上找的资料,该改改就改改,如有雷同,dddd,希望各位课程设计能通过并获得理想成绩。
1.1.1 背景和意义
银行家算法是荷兰学者Dijkstra为银行系统设计的,以确保银行在发放现金贷款时,不会发生不能满足所有客户需要的情况。后来该算法被用在操作系统中,用于避免死锁,它以银行借贷系统的分配策略为基础,判断并保证系统的安全运行。
在银行中,客户申请贷款的数量是有限的,每个客户在第一次申请贷款时要声明完成该项目所需的最大资金量,在满足所有贷款要求时,客户应及时归还。银行家在客户申请的贷款数量不超过自己拥有的最大值时,都应尽量满足客户的需要。在这样的描述中,银行家就好比操作系统,资金就是资源,客户就相当于要申请资源的进程。
银行家算法是一种最有代表性的避免死锁的算法。在避免死锁方法中允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次分配资源的安全性,若分配不会导致系统进入不安全状态,则分配,否则等待。
我们可以把操作系统看作是银行家,操作系统管理的资源相当于银行家管理的资金,进程向操作系统请求分配资源相当于用户向银行家贷款。
为保证资金的安全,银行家规定:
(1) 当一个顾客对资金的最大需求量不超过银行家现有的资金时就可接纳该顾客;
(2) 顾客可以分期贷款,但贷款的总数不能超过最大需求量;
(3) 当银行家现有的资金不能满足顾客尚需的贷款数额时,对顾客的贷款可推迟支付,但总能使顾客在有限的时间里得到贷款;
(4) 当顾客得到所需的全部资金后,一定能在有限的时间里归还所有的资金.
操作系统按照银行家制定的规则为进程分配资源,当进程首次申请资源时,要测试该进程对资源的最大需求量,如果系统现存的资源可以满足它的最大需求量则按当前的申请量分配资源,否则就推迟分配。当进程在执行中继续申请资源时,先测试该进程本次申请的资源数是否超过了该资源所剩余的总量。若超过则拒绝分配资源,若能满足则按当前的申请量分配资源,否则也要推迟分配。
1.1.2 任务概述
用C语言模拟银行家算法对死锁的避免。对于进程死锁的避免问题,分为两种状态:安全状态和非安全状态。在避免死锁的方法中,允许进程动态申请资源分配之前,预先计算此次资源分配的安全性。如果此次分配不会导致系统进入不安全状态,则将资源分配给进程。否则,让进程进入等待状态。
所谓安全状态是指系统能够按照某种进程顺序,来为每个进程P分配所需的资源,直至满足每个进程对资源的最大需求,使每个进程都可以顺利地完成。如果系统无法找到这样一个序列,则系统处于不安全状态。只要系统处于安全状态,系统就可以避免进入死锁状态。
1.1.3 设计环境
(1) 硬件:PC机,要求能运行Windows XP、Windows7或Windows 10操作系统。
(2) 软件:
操作系统:Windows系列。
数据库系统:无
编译软件:Visual Studio 2019
程序设计语言:C语言
2.2 系统整体功能图
2.2.1 功能模块图
银行家算法系统中包括七个模块,分别为初始化模块,主函数模块和安全检测模块。其中初始化模块包括默认初始化功能和自定义初始化功能;主函数模块包括用户帮助和回收分配失败的资源;其他功能模块包括请求资源分配、检测是否存在安全序列以及查看系统分配结果的功能。具体如图2.1所示。
图2.1 银行家算法功能模块图
2.7 程序运行结果
2.7.1 运行界面截图和结果分析
使用默认初始化功能,即参考例题的初始化,输出整理出来的进程相关信息和资源信息。运行结果如图2.5所示。
图2.5 默认初始化功能截图
使用自定义初始化功能,同样参考例题输入系统进程数m、资源数n、各类资源总数All、各进程最大需求资源数MAX,进程已经占有的资源数Allocate,输出系统剩余资源数Available。运行结果如图2.6所示。
图2.6 自定义初始化功能截图
(1)t0时刻是否为安全状态。
根据默认的初始化进程及其相关资源数据,选择功能5对当前状态进行安全检测,运行结果如图2.7所示。
图2.7 默认初始化安全检测截图
(2)若在t0时刻进程P1请求资源(1,0,2),是否能实施分配?
对指定进程分配资源,首先调用安全序列检测函数,检测是否存在安全序列,若存在则可以分配,打印输出安全序列,并为其分配资源,打印输出当前系统分配资源结果图。运行结果如图2.8所示。
图2.8 默认初始化P1请求分配资源截图
(3)在(2)的基础上,若进程P4请求资源(3,3,0),是否能实施分配?
对指定进程分配资源,首先调用安全序列检测函数,检测是否存在安全序列,不存在则不可以分配,并回收预分配的资源。运行结果如图2.9所示。
图2.9 默认初始化P4请求分配资源截图
2.7.2 性能分析
本次制作的银行家算法模拟系统,实现的功能比较齐全,利用的数据结构主要为二维数组和一维数组,可读性和理解性比较强。
能够成功的实现避免死锁的功能,银行家算法可以进行资源的预分配处理,但是一旦资源分配以后,系统从安全的状态变为不安全的状态就可能会导致系统报错,其本质就是:如果进程x请求分配一定的资源,系统分配之后剩余的资源无法满足之后任何一个进程的需求的话,那么该系统就会处于不安全状态。所以在请求分配资源时,设计了安全序列检测,存在安全序列则同意分配资源,否则不同意分配资源并回收预分配的资源,令系统处于安全状态。
该系统具有五大功能,分别为:初始化系统、请求分配资源、查看系统分配结果、当前状态安全性检查和退出系统。实现了较好的人机交互界面。
本系统仍然存在不足,例如实现的人机交互界面比较单一,美观性不强。系统实现的过程较为简单,部分特殊情况没有考虑到位等。这就需要在以后的学习中不断反思和完善此系统,在此过程中收获许多。
附源代码
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#pragma warning(disable:4996)
#define FALSE 0
#define TRUE 1
#define M 10 //最大进程数
#define N 10 //最大资源类数
int m;//进程数
int n;//资源数目
int id; //进程ID号
int All[N]; //资源总数
int Available[N]; //剩余资源数
int Available_max[N]; //剩余资源数
int MAX[M][N]; //最大需求矩阵
int Need[M][N]; //需求矩阵
int Need_t[M][N]; //需求矩阵
int Allocate[M][N]; //分配矩阵
int Request[N]; //请求资源
int Work[N]; //工作向量
int Finish[M]; //进程完成标志
int work_allocation[M][N];
void init_system();
void print_infor();
int try_allocate();
void return_back();
int is_safe();
int flag = 0;
int safe[M];
void default_system() {
int i = 0, j = 0;
char ch;
int temp;
m = 5;
n = 3;
All[0] = 10;
All[1] = 5;
All[2] = 7;
MAX[0][0] = 7, MAX[0][1] = 5, MAX[0][2] = 3,
MAX[1][0] = 3, MAX[1][1] = 2, MAX[1][2] = 2,
MAX[2][0] = 9, MAX[2][1] = 0, MAX[2][2] = 2,
MAX[3][0] = 2, MAX[3][1] = 2, MAX[3][2] = 2,
MAX[4][0] = 4, MAX[4][1] = 3, MAX[4][2] = 3;
Allocate[0][0] = 0, Allocate[0][1] = 1, Allocate[0][2] = 0,
Allocate[1][0] = 2, Allocate[1][1] = 0, Allocate[1][2] = 0,
Allocate[2][0] = 3, Allocate[2][1] = 0, Allocate[2][2] = 2,
Allocate[3][0] = 2, Allocate[3][1] = 1, Allocate[3][2] = 1,
Allocate[4][0] = 0, Allocate[4][1] = 0, Allocate[4][2] = 2;
memset(Work, 0, sizeof(Work));
memcpy(Work, Available, 3);
/*Need*/
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
{
Need[i][j] = MAX[i][j] - Allocate[i][j];
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
Need_t[i][j] = Need[i][j];
}
}
for (i = 0; i < n; i++) {
int sum = 0;
for (j = 0; j < m; j++) {
sum = sum + Allocate[j][i];
}
Available[i] = All[i] - sum;
}
printf("系统初始化为:\n进程数目:5 \n资源总数:3 \n各类资源总数:10 5 7\n");
printf(" MAX Allocation Available\n");
printf(" A B C A B C A B C \n");
printf(" P0 7 5 3 0 1 0 ");
for (i = 0; i < n; i++) { printf("%d ", Available[i]); }
printf("\n P1 3 2 2 2 0 0 \n");
printf(" P2 9 0 2 3 0 2 \n");
printf(" P3 2 2 2 2 1 1 \n");
printf(" P4 4 3 3 0 0 2 \n");
for (int t = 0; t < n; t++)
Available_max[t] = Available[t];
printf("\n\n\n");
}
void init_system() {
int i=0,j=0;
char ch;
int temp;
printf("请输入进程数目:\n");
scanf("%d",&m);
printf("请输入资源种数:\n");
scanf("%d",&n);
printf("请输入各类资源总数:\n");
for(;i<n;i++)
scanf("%d",&All[i]);
printf("输入各进程对各资源的最大需求:\n");
for(i=0;i<m;i++)
{
printf("进程P%d:\n",i);
for(j=0;j<n;j++)
{
scanf("%d",&MAX[i][j]);
}
}
ch = getchar();
printf("是否输入分配矩阵?(y/n)");
while(scanf("%c",&ch))
{
if(ch == 'n')
{
memset(Allocate,0,sizeof(Allocate));
memset(work_allocation,0,sizeof(work_allocation));
break;
}
else if(ch == 'y')
{
printf("请输入T时刻资源的分配矩阵:\n");
for(i=0;i<m;i++)
{
printf("进程P%d:\n",i);
for(j=0;j<n;j++)
{
scanf("%d",&Allocate[i][j]);
}
}
break;
}
else
printf("重新输入!\n");
}
memset(Work,0,sizeof(Work));
memcpy(Work,Available,3);
/*初始时刻 Need*/
for(i=0;i<m;i++)
for(j=0;j<n;j++)
{
Need[i][j] = MAX[i][j] - Allocate[i][j];
}
for(int i=0;i<m;i++) {
for(int j=0;j<n;j++) {
Need_t[i][j]=Need[i][j];
}
}
for(i=0;i<n;i++){
int sum = 0;
for(j=0;j<m;j++){
sum = sum + Allocate[j][i];
}
Available[i]=All[i]-sum;
}
printf("当前可用的资源为:\n");
for(i=0;i<n;i++){
printf("%d ",Available[i]);
}
printf("\n");
}
int try_allocate()
{
for(int i=0;i<m;i++) {
int temp1=0;
for(int j=0;j<n;j++) {
if(Need[i][j]==0)
temp1++;
}
if(temp1==n)
for(int j=0;j<n;j++){
Available[j]=Available_max[j]+Need_t[i][j];
Available_max[j]=Available[j];
}
}
printf("当前可用资源数:\n");
for(int i=0;i<n;i++){
printf("%d ",Available[i]);
}
printf("\n");
int i,temp,j;
int ret = 1;
printf("\t MAX Need Allocation \n");
for(j=0;j<3;j++)
{
printf("\t ");
for(i = 0 ; i < n; i++)
printf("%c ",(char)('A'+i));
}
printf("\n**************************************************\n");
for(int k=0;k<m;k++)
{
if(flag == 1)
i = safe[k];
else i = k;
printf("P%d\t",i);
for(j=0;j<n;j++)
printf("%3d",MAX[k][j]);
printf("\t");
for(j=0;j<n;j++)
printf("%3d",Need[i][j]);
printf("\t");
for(j=0;j<n;j++)
printf("%3d",Allocate[i][j]);
printf("\t");
printf("\n");
}
printf("请输入请求进程号:\n");
while(scanf("%d",&id))
{
if(id<0|id>m)
printf("进程不存在!\n");
else break;
}
printf("请输入请求资源数:\n");
for(i=0;i<n;i++)
{
scanf("%d",&Request[i]);
}
printf("开始为进程P%d分配资源:\n",id);
for(i=0;i<n;i++)
{
if(Request[i]>Need[id][i])
{
printf("进程请求资源数大于所需资源数,不予分配!\n");
ret = 0;
}else if(Request[i] > Available[i])
{
printf("进程请求资源数大于可用资源数,无法分配!\n");
ret = 0;
}
Available[i] -= Request[i];
Allocate[id][i] += Request[i];
Need[id][i] -= Request[i];
}
return ret;
}
void print_infor()
{
int i,j,k;
printf("\t Work Need Allocation Work+Allocation Finish\n");
for(j=0;j<4;j++)
{
printf("\t ");
for(i = 0 ; i < n; i++)
printf("%c ",(char)('A'+i));
}
printf("\n******************************************************************************\n");
for(k=0;k<m;k++)
{
if(flag == TRUE)
i = safe[k];
else i = k;
printf("P%d\t",i);
for(j=0;j<n;j++)
printf("%3d",work_allocation[i][j]-Allocate[i][j]);
printf("\t");
for(j=0;j<n;j++)
printf("%3d",Need[i][j]);
printf("\t");
for(j=0;j<n;j++)
printf("%3d",Allocate[i][j]);
printf("\t");
for(j=0;j<n;j++)
printf("%3d",work_allocation[i][j]);
printf("\t");
if(Finish[i] == FALSE)
printf("false\n");
else printf("true\n");
}
printf("\n\n\n");
}
void return_back()
{
int i,j;
memset(Finish,0,sizeof(Finish));
for(i=0;i<n;i++)
{
Available[i] += Request[i];
Allocate[id][i] -= Request[i];
Need[id][i] += Request[i];
}
}
/*安全性检查函数*/
int is_safe()
{
int i,j;
int count = 0;
memset(work_allocation,0,sizeof(work_allocation));
memset(safe,0,m);
printf("**********Work向量**********\n");
for(i=0;i<n;i++)
{
Work[i] = Available[i];
}
for(i=0;i<m;i++)
Finish[i] = 0;
for(i=0;i<m;i++)
{
if(Finish[i] == 0)
{
for(j=0;j<n;j++)
{
if(Need[i][j] > Work[j])
break;
}
if(j == n)
{
printf("P%d\t",i);
safe[count++] = i;
for(j=0;j<n;j++)
{
if(count==1) {
Work[j]=Available[j];
work_allocation[i][j] = Work[j]+Allocate[i][j];
printf("%d\t",Work[j]);
Work[j]=work_allocation[i][j];
}
else {
Work[j]=work_allocation[safe[count-2]][j];
work_allocation[i][j] = Work[j]+Allocate[i][j];
printf("%d\t",Work[j]);
}
}
printf("\n");
Finish[i] = 1; //进程i能顺利完成
if(1)
i = -1;//重新开始
}
}
}
printf("\n");
for(i=0;i<m;i++)
{
if(Finish[i] == 0)
{
printf("进程P%d不能顺利完成!\n",i);
return 0;
}
}
/*如果前面未返回,则存在安全序列*/
printf("存在如下安全序列:\n");
for(i=0;i<m; i++)
printf("P%d ",safe[i]);
printf("\n");
return TRUE;
}
int main()
{
int ret = FALSE;
int choice;
while(1)
{
printf("模拟避免进程死锁算法,选择你要进行的操作:\n");
printf("\t 1、默认初始化系统\n");
printf("\t 2、自定义初始化系统\n");
printf("\t 3、请求分配资源\n");
printf("\t 4、查看系统分配结果\n");
printf("\t 5、当前状态安全性检查\n");
printf("\t 0、退出系统\n");
scanf("%d",&choice);
if(choice == 1)
default_system();
else if(choice == 2)
init_system();
else if(choice == 3)
{
if(try_allocate() == 1)
{
flag = is_safe();
if(flag == 0)
{
printf("系统不安全,不能予以分配!\n");
return_back();
}else{
printf("系统安全!分配成功!\n");
print_infor();
}
}else{
printf("分配失败!\n");
return_back();
}
}
else if(choice == 4)
print_infor();
else if(choice == 0)
break;
else if(choice == 5)
{
if((flag = is_safe()) == 0)
printf("当前状态不安全!\n\n");
else
printf("当前状态安全!\n\n");
}
else
printf("输入不合法!重新输入!\n\n");
}}