代码:
#include<stdio.h>#include<stdlib.h>#define Num_Dev 4 // 每个进程所需的设备的种类数量#define Max 10 //可容纳的最多的进程数量int Max_Need_Dev [Max][Num_Dev]; //所有进程所需要的设备的最大数目int Allocation_Dev [Max][Num_Dev]; //所有进程已经分配到的设备的数目int Need_Dev [Max][Num_Dev]; //所有进程还需要的设备的数目int current_Available_Dev[Max][Num_Dev]; //记录分配完之后,此时系统的可用资源数目(因为假如会产生安全队列,那么有多少个进程就会产生多少次这样的当前分配后的可用资源数目)int current_recycle_Dev[Max][Num_Dev]; //记录回收完之后,系统中各个设备的数目int system_Dev[Num_Dev]; //系统中所拥有的各类设备的数量int Available_Dev [Num_Dev]; //系统中剩余的资源数量int finish [Max]; //存放所有进程是否已经运行完毕。int quene[Max]; //假设不会出现死锁,那么用于存放安全队列。 即记录每个进程的下表。int i,j;int num; // 进程的名字 void init(){ printf("请输入系统中各类资源的数目总和:\n"); for (i = 0; i < Num_Dev; i++) { scanf("%d",&system_Dev[i]); Available_Dev[i] = system_Dev[i]; printf("%d\t",Available_Dev[i]); } printf("\n"); printf("请输入进程的数量:\n"); scanf("%d",&num); printf("\n"); printf("请输入各个进程运行所需要全部设备的数量:\n"); for(i = 0;i < num; i ++){ for (j = 0; j < Num_Dev; j++) { scanf("%d",&Max_Need_Dev[i][j]); } } printf("\n"); printf("请输入各个进程已经分配到的设备的数目:\n"); for(i = 0;i < num; i ++){ for (j = 0; j < Num_Dev; j++) { scanf("%d",&Allocation_Dev[i][j]); Available_Dev[j] = Available_Dev[j] - Allocation_Dev[i][j]; //计算系统中剩余设备的数目 } } printf("\n"); for(i = 0;i < num; i ++){ for (j = 0; j < Num_Dev; j++) { Need_Dev[i][j] = Max_Need_Dev[i][j] - Allocation_Dev[i][j]; //计算各个进程依然所需要的各个设备的数目 } } for (i = 0; i < num; i++) { finish[i] = 0; quene[i] = -1; } }void print(){ printf("进程ID\t|\tMax\t|\tAllocat\t|\tNeed\t|\tAvail\t|\tRecycle\t|\t\tfinish\t\n"); for (i = 0; i < num; i++) { printf("进程%d\t|\t",i); printf("%d,%d,%d,%d\t|\t%d,%d,%d,%d\t|\t%d,%d,%d,%d\t|\t%d,%d,%d,%d\t|\t(%d,%d,%d,%d)\t|\t%d\\",Max_Need_Dev[i][0],Max_Need_Dev[i][1],Max_Need_Dev[i][2],Max_Need_Dev[i][3],Allocation_Dev[i][0],Allocation_Dev[i][1],Allocation_Dev[i][2],Allocation_Dev[i][3],Need_Dev[i][0],Need_Dev[i][1],Need_Dev[i][2],Need_Dev[i][3],current_Available_Dev[i][0],current_Available_Dev[i][1],current_Available_Dev[i][2],current_Available_Dev[i][3],current_recycle_Dev[i][0],current_recycle_Dev[i][1],current_recycle_Dev[i][2],current_recycle_Dev[i][3],finish[i]); printf("\n"); }}int conpare(int *p){ //判断当前可用设备的数目是否可以满足所传入的进程的要求 for(j = 0;j < Num_Dev; j ++){ if(*(p+j) > Available_Dev[j] ){ return 0; } } return 1;}void recycle(int *p){ //若一个进程运行完毕,回收已经分配给它的设备 for (i = 0; i < Num_Dev; i++) { Available_Dev[i] += *(p+i); } }int allocation(){ int flag = 0; int count = 1; //判断死锁。就是遍历一遍之后没有进程可以运行。 int i = 0; //判断是哪一个进程 int index = 0; //用于记录安全队列的下表 int max_times = 0; //因为有num个变量, 所以假如有安全队列,最多就是寻找num的平方次 while (1) { max_times ++; if(conpare(Need_Dev[i])==1&&finish[i] == 0){ count = 0; finish[i] = 1; //表示该进程获得资源后运行完毕 for (j = 0; j < Num_Dev; j++) // 让进程获取剩余设备 即 { Allocation_Dev[i][j] = Max_Need_Dev[i][j] -Need_Dev[i][j]; //1.让进程已经分配的设备数目加上它仍然需要的 Available_Dev[j] -= Need_Dev[i][j]; //2.系统中目前可用的设备数目减去进程需要的 current_Available_Dev[i][j] = Available_Dev[j]; //记录分配完之后,此时系统的可用资源数目(因为假如会产生安全队列,那么有多少个进程就会产生多少次这样的当前分配后的可用资源数目) } recycle(Max_Need_Dev[i]); // 回收资源 for (j = 0; j < Num_Dev; j++) { current_recycle_Dev[i][j] += Available_Dev[j]; } quene[index] = i; index ++; if(index == num ){ flag = 1; printf("安全队列已经返回如下:\n"); break; } } if(count == num){ printf("会发生死锁。无安全队列。。。。。。\n"); break; } if(i == num - 1){ i = 0; continue; } if(max_times == num*num){ printf("全部可能已经执行完毕,无安全队列。。。。。。\n"); break; } count ++; i ++; } return flag;}int main(void ){ init(); int flag = allocation(); print(); if(flag == 1){ for (i = 0; i < num; i++) { printf("%d--->",quene[i]); } } printf("\n");}
问题:
1、为何init函数中的scanf只输入了一次,但是却生成了一个数组(28 -33)3、finish(标示是否运行完成)和quene(队列)的意义 (67 -71)4、conpare函数的意思判断当前可用设备的数目是否可以满足所传入的进程的要求5、*(p+j)的功能 (90)6、max_times的功能、max_times ==num*num的意思是什么单层遍历 遍历次数假如有安全队列,最多就是寻找num的平方次7、index的作用(108)记录安全队列的下表8、flag的作用(134) 标志9、count的作用(139) count(判断死锁 (=1死锁)) 10、printf()的作用(160)11、代码的执行顺序12、Num_Dev(进程数量)、Max_Need_Dev(最大需求)、Allocation_Dev(所有进程已经分配到的设备的数目)、Need_Dev(还需要的资源)、current_Available_Dev(分配完之后,此时系统的可用资源数目)、current_recycle_Dev(回收完之后,系统中各个设备的数目)的意义13、system_Dev(总资源)、Available_Dev(剩余可用资源)的意义14、i、j两个变量实现的功能i个进程,j个资源。15、如何判定死锁系统中的资源是有限的。不足以一下子把所有进程所需的资源都分配。我们需要做的就是在有限的资源下,是否有一个分配顺序,可以使得全部进程都可以获得资源并运行,如果可以则返回一个安全队列,如果不可以,则说明有风险,系统可能会陷入死锁。16、发生死锁和不发生死锁的输出区别发生死锁无法输出安全队列
让我逐个回答你的问题:答案参考Chatgpt解答
1. 在'init'函数中,'scanf'只输入了一次,但生成了一个数组(28-33行)。这是因为在循环中,每次循环都会读取一个数值并存储在数组中的不同位置。 2. 'finish'数组是用于存放所有进程是否已经运行完毕的标志。当一个进程完成运行时,对应的'finish'值会被设置为1。'quene'数组是一个用于存放安全队列的数组,记录每个进程的下标。安全队列是指在没有死锁的情况下,可以按照一定顺序运行的进程队列。 3. 'conpare'函数用于判断当前可用设备的数目是否可以满足传入进程的要求。它比较进程所需的设备数目和系统中剩余的设备数目,如果系统中的设备足够满足进程的要求,返回1;否则返回0。 4. '*(p+j)'是指针操作,表示取指针'p'偏移'j'个位置处的值。在这里,'p'指向一个数组,'*(p+j)'就是取数组中第'j'个元素的值。 5. 'max_times'是一个计数器,用于记录循环的次数。'max_times == num*num'表示循环次数达到了最大限制,即已经遍历了所有可能的情况。 6. 'index'是用于记录安全队列的下标,表示当前安全队列的长度。 7. 'flag'的作用是标志是否存在安全队列。如果存在安全队列,则'flag'被设置为1;否则为0。 8. 'count'是用于判断死锁的计数器。当'count'等于进程数量'num'时,表示所有进程都无法运行,可能发生死锁。 9. 'printf()'用于输出信息到标准输出。在这里,它被用于打印各种信息,如进程的资源需求、分配情况、当前可用资源等。 10. 代码的执行顺序是从'main()'函数开始,依次调用'init()'函数进行初始化,然后调用'allocation()'函数判断是否存在安全队列,最后调用'print()'函数打印相关信息。 11. 'Num_Dev'是每个进程所需的设备种类数量。'Max_Need_Dev'是所有进程所需要的设备的最大数目,'Allocation_Dev'是所有进程已经分配到的设备的数目,'Need_Dev'是所有进程还需要的设备的数目,'current_Available_Dev'记录分配完之后,此时系统的可用资源数目,'current_recycle_Dev'记录回收完之后,系统中各个设备的数目。 12. 'system_Dev'是系统中拥有的各类设备的数量。'Available_Dev'是系统中剩余的资源数量,即当前可用资源。 13. 变量'i'和'j'用于循环控制。'i'表示进程的索引,从0到'num-1','j'表示设备的索引,从0到'Num_Dev-1'。 14. 判定死锁的方法是通过遍历所有进程,检查是否有进程能够满足当前可用设备的要求。如果所有进程都无法满足要求,则可能发生死锁。 15. 发生死锁的情况下,无法输出安全队列。安全队列是指在没有死锁的情况下,可以按照一定顺序运行的进程队列。
总体来说,这段代码是一个简单的银行家算法的实现。它通过初始化系统资源和进程的资源需求,然后判断是否存在安全队列,如果存在则输出安全队列,表示可以按照一定顺序运行进程。如果不存在安全队列,则可能发生死锁。
请注意,由于代码的可读性较差,变量命名不够清晰,因此阅读和理解起来可能会有一些困难。建议对代码进行重构和注释,以提高可读性和可维护性。
参考
#include<stdio.h>
#include<stdlib.h>
#define false 0
#define true 1
int available[100]= {0};
int max[50][100]= {0};
int allocation[50][100]= {0};
int need[50][100]= {0};
int request[50][100]= {0};
int finish[100]= {0};
char Name[100]= {0};
int work[100]= {0};
int security[100]= {0};
int m,n;
int Assign_number=0;
void Data_initialization();
void Print_Data();
void Distribution_test();
void Recover();
int Safe_Judge();
void Bankers_algorithm();
int main()
{
int option=1;
Data_initialization();
Print_Data();
if(Safe_Judge()==0)
{
return 0;
}
while(option)
{
printf("\n\n 请选择 \n");
printf("1.请求资源分配\n");
printf("2.退出\n");
scanf("%d",&option);
if(option==1)
{
Bankers_algorithm();
}
else if(option==2)
{
return 0;
}
else
{
printf("重新选择 \n");
}
}
}
void Data_initialization()
{
int i,j;
int number,flag;
char name;
int temp[100]= {0};
printf("系统资源种类数为:");
scanf("%d",&n);
for(i=0; i<n; i++)
{
printf("资源%d的名称:",i);
fflush(stdin);
scanf("%c",&name);
Name[i]=name;
printf("资源%c的初始个数为:",name);
scanf("%d",&number);
available[i]=number;
}
printf("\n请输入进程的数量:");
scanf("%d",&m);
printf("请输入各进程的最大需求的值:\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==1)
printf("资源最大需求量大于系统中资源最大量,请重新输入\n");
}
while(flag!=0);
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=true;
need[i][j]=max[i][j]-allocation[i][j];
temp[j]+=allocation[i][j];
}
}
if(flag==1)
printf("分配的资源大于最大量,请重新输入\n");
}
while(flag!=0);
for(j=0; j<n; j++)
available[j]=available[j]-temp[j];
}
void Print_Data()
{
int i,j;
printf("\n系统目前可用的资源(available):\n");
for(i=0; i<n; i++)
printf("%c ",Name[i]);
printf("\n");
for(j=0; j<n; j++)
printf("%d ",available[j]);
printf("\n");
printf("系统当前的资源分配情况如下:\n");
printf(" max allocation need\n");
printf("进程名 ");
for(j=0; j<3; j++)
{
for(i=0; i<n; i++)
printf("%c ",Name[i]);
printf(" ");
}
printf("\n");
for(i=0; i<m; i++)
{
printf(" P%d ",i);
for(j=0; j<n; j++)
printf("%d ",max[i][j]);
printf(" ");
for(j=0; j<n; j++)
printf("%d ",allocation[i][j]);
printf(" ");
for(j=0; j<n; j++)
printf("%d ",need[i][j]);
printf("\n");
}
}
void Distribution_test(int i)
{
for(int j=0; j<n; j++)
{
available[j]=available[j]-request[Assign_number][j];
allocation[i][j]=allocation[i][j]+request[Assign_number][j];
need[i][j]=need[i][j]-request[Assign_number][j];
}
}
void Recover(int i)
{
for(int j=0; j<n; j++)
{
available[j] = available[j] + request[Assign_number][j];
allocation[i][j] = allocation[i][j] - request[Assign_number][j];
need[i][j] = need[i][j] + request[Assign_number][j];
}
}
int Safe_Judge()
{
int i,j,k=0,apply,p;
for(j=0; j<n; j++)
work[j] = available[j];
for(i=0; i<m; i++)
finish[i] = false;
for(i=0; i<m; i++)
{
apply=0;
for(j=0; j<n; j++)
{
if(finish[i]==false && need[i][j]<=work[j])
{
apply++;
if(apply==n)
{
for(p=0; p<n; p++)
work[p]=work[p]+allocation[i][p];
finish[i]=true;
security[k++]=i;
i=-1;
}
}
}
}
for(i=0; i<m; i++)
{
if(finish[i]==false)
{
printf("系统处于不安全状态\n");
return false;
}
}
printf("系统是处于安全状态\n");
printf("存在一个安全序列:");
for(i=0; i<m; i++)
{
printf("P%d",security[i]);
if(i<m-1)
printf(" - ");
}
printf("\n");
return true;
}
void Bankers_algorithm()
{
int flag = true;
int i,j;
printf("请输入请求分配资源的进程号(0-%d):",m-1);
scanf("%d",&i);
printf("请输入进程P%d要申请的资源个数:\n",i);
for(j=0; j<n; j++)
{
printf("%c:",Name[j]);
scanf("%d",&request[Assign_number][j]);
}
for (j=0; j<n; j++)
{
if(request[Assign_number][j]>need[i][j])
{
printf("进程P%d申请的资源大于它需要的资源\n",i);
printf("分配不合理,不分配\n");
flag = false;
break;
}
else
{
if(request[Assign_number][j]>available[j])
{
printf("进程%d申请的资源大于系统现在可利用的资源\n",i);
printf("系统无足够资源,不分配\n");
flag = false;
break;
}
}
}
if(flag)
{
Distribution_test(i);
Print_Data();
if(Safe_Judge()==0)
{
Recover(i);
Print_Data();
}
else
{
Assign_number++;
}
}
}
/*
input test
4
a
3
b
14
c
12
d
12
5
0 0 1 2
1 7 5 0
2 3 5 6
0 6 5 2
0 6 5 6
0 0 1 2
1 0 0 0
1 3 5 4
0 6 3 2
0 0 1 4
1
1
0
4
2
0
*/
计算机操作系统——银行家算法详解(C语言版)
非常详细,可以借鉴下
https://blog.csdn.net/qq_53988670/article/details/124375734
来自NewBing和LP的编写:
这是一个用于演示银行家算法的C语言程序。银行家算法是一种避免死锁的经典算法,用于动态资源分配,通过确保系统总是有足够的资源来满足进程的最大需求,以防止进入不安全状态。
列出的问题对每个问题进行解答:
在 init
函数中,scanf
函数在 for
循环中,用于读取用户输入的各类资源的总和,输入的次数取决于设备种类的数量 Num_Dev
。
finish
数组用于标记进程是否已经运行完毕,如果进程已经运行完毕,那么相应的数组元素值为1,否则为0。quene
数组用于存储安全序列,即系统可以按照这个顺序为进程分配资源,使得所有进程都能顺利完成,而不会发生死锁。
compare
函数用于判断当前系统可用设备的数目是否可以满足当前进程的需求。如果可以满足,函数返回1,否则返回0。
*(p+j)
是C语言中的指针运算,它等价于 p[j]
。这里的 p
是一个指针,指向一个整数数组。*(p+j)
表示取该数组的第 j
个元素。
max_times
用于记录程序尝试为进程分配资源的次数。max_times == num*num
的意思是,如果已经尝试了 num*num
次,但还是没有找到一个安全的分配序列,那么就认为系统会陷入死锁,结束资源分配。
index
用于记录安全队列的下标。
flag
是一个标志位,如果找到一个安全的资源分配序列,那么 flag
被设为1,否则为0。
count
用于计数,如果遍历所有进程后,没有一个进程能满足资源需求,那么 count
加1。如果 count
等于进程数量,那么认为系统会陷入死锁。
printf
是C语言中的一个函数,用于输出信息到控制台。在这个程序中,printf
用于打印各种信息,例如进程的资源需求、已分配资源、需要的资源等。
代码的执行顺序是从 main
函数开始,首先调用 init
函数初始化资源,然后调用 allocation
函数尝试为进程分配资源,最后调用 print
函数打印结果。
Num_Dev
是设备种类数量,Max_Need_Dev
存储所有进程所需要的设备的最大数目,Allocation_Dev
存储所有进程已经分配到的设备的数目,Need_Dev
存储所有进程还需要的设备的数目,current_Available_Dev
记录分配完之后,此时系统的可用资源数目,current_recycle_Dev
记录回收完之后,系统中各个设备的数目。
system_Dev
存储系统中所拥有的各类设备的数量,Available_Dev
存储系统中剩余的设备数量。在分配资源给进程后,Available_Dev
会减少,而在进程运行完毕后,Available_Dev
会增加。
在这个程序中,i
和 j
通常用作循环的索引。i
遍历进程,j
遍历设备。
死锁的判断主要在 allocation
函数中。如果在一轮遍历所有进程后,没有一个进程能满足资源需求,那么就认为系统会陷入死锁。
发生死锁和不发生死锁的主要区别在于,如果发生死锁,程序无法输出一个安全序列;如果没有发生死锁,程序会输出一个安全序列,表示系统可以按照这个顺序为进程分配资源,使得所有进程都能顺利完成。
此外,对于代码优化,您可以考虑以下几点:
compare
改为 is_request_satisfiable
,将 recycle
改为 recycle_resources
等。以下答案由GPT-3.5大模型与博主波罗歌共同编写:
scanf函数是在循环中使用的,所以会多次读取输入数据存储到数组中。
finish数组用来记录每个进程是否运行完成,初始值都是0,当一个进程运行完毕后,其对应的finish值变为1。quene数组用于记录安全队列中每个进程的下标。
conpare函数的作用是判断当前可用设备的数目是否可以满足所传入的进程的要求。函数参数p是一个指向需要判断的进程所需设备数的指针,*(p+j)表示访问p指针指向的数组中第j个元素的数值。
max_times是一个标志变量,用于统计遍历找安全队列时的循环次数。max_times ==numnum的意思是,如果num个进程都遍历过一次,那么最多执行numnum次就可以找到安全队列了。
index的作用是记录安全队列的下标,每次找到一个安全进程就把该进程的下标记录到队列中。
flag的作用是标志是否找到了安全队列。如果找到了,flag的值为1,否则为0。
count的作用是用于判断死锁。当已遍历的进程数等于总进程数时,如果没有找到安全队列,就说明进程之间存在死锁现象。
printf函数的作用是输出程序结果和提示信息。
Num_Dev表示每个进程需要的设备种类数量,Max_Need_Dev表示所有进程所需要的设备的最大数目,Allocation_Dev表示所有进程已经分配到的设备的数目,Need_Dev表示所有进程还需要的设备的数目,current_Available_Dev表示系统分配设备后当前还可用的设备数目,current_recycle_Dev表示回收设备后系统中各个设备的数目。
system_Dev表示系统中拥有的各类设备数量,Available_Dev表示系统中剩余的资源数量。
发生死锁的情况是系统中的资源数量无法满足所有进程所需,且没有一个分配顺序可以避免死锁的发生。死锁的解决方式通常是撤销某些进程的资源,或者削减它们所需的资源。
发生死锁时无法输出安全队列,因为没有安全队列可输出。在不发生死锁的情况下,安全队列的输出会显示每个进程的下标。
如果我的回答解决了您的问题,请采纳!
以下内容由CHATGPT及阿里嘎多学长共同生成、有用望采纳:
1、init函数中的scanf只输入了一次,但是却生成了一个数组(28-33)
这是因为在输入Max_Need_Dev、Allocation_Dev和Need_Dev时,是通过循环来输入的,每次循环都会为数组中的一个元素赋值,因此只需要在init函数中输入一次,就可以生成完整的数组。
2、finish(标示是否运行完成)和quene(队列)的意义(67-71)
finish数组用于记录每个进程是否已经运行完毕,0表示未运行完毕,1表示已经运行完毕。quene数组用于记录安全队列,即可以按照一定的顺序运行所有进程的进程序号。
3、conpare函数的意思判断当前可用设备的数目是否可以满足所传入的进程的要求(90)
conpare函数用于判断当前可用设备的数目是否可以满足所传入的进程的要求。如果可用设备数目大于等于进程所需设备数目,则返回1,否则返回0。
4、*(p+j)的功能(90)
*(p+j)可以理解为p[j],即获取数组p中下标为j的元素的值。
5、max_times的功能、max_times ==num*num的意思是什么单层遍历 遍历次数假如有安全队列,最多就是寻找num的平方次
max_times用于限制遍历次数,避免无限循环。max_times ==numnum表示最多循环numnum次,即寻找num个进程的所有可能排列组合。
6、index的作用(108)
index用于记录安全队列的下标,即记录已经运行完毕的进程的序号。
7、flag的作用(134)
flag用于标志是否存在安全队列,如果存在安全队列,则flag为1,否则为0。
8、count的作用(139)
count用于判断是否发生死锁。如果在一轮遍历中没有找到任何一个进程可以运行,则count加1。如果count等于num,则说明所有进程都无法运行,发生死锁。
9、printf()的作用(160)
printf()用于输出结果,其中%d表示输出整数,%f表示输出浮点数,%s表示输出字符串等。
10、代码的执行顺序
首先调用init函数初始化各个数组,然后调用allocation函数计算安全队列,最后调用print函数输出结果。
11、Num_Dev(进程数量)、Max_Need_Dev(最大需求)、Allocation_Dev(所有进程已经分配到的设备的数目)、Need_Dev(还需要的资源)、current_Available_Dev(分配完之后,此时系统的可用资源数目)、current_recycle_Dev(回收完之后,系统中各个设备的数目)的意义
这些数组记录了系统中所有进程和设备的状态。其中,Num_Dev表示进程数量,Max_Need_Dev表示每个进程需要的最大设备数目,Allocation_Dev表示已经分配给每个进程的设备数目,Need_Dev表示每个进程还需要的设备数目,current_Available_Dev表示分配完之后,此时系统的可用资源数目,current_recycle_Dev表示回收完之后,系统中各个设备的数目。
12、system_Dev(总资源)、Available_Dev(剩余可用资源)的意义
system_Dev表示系统中总共拥有的各类设备的数量,Available_Dev表示系统中剩余的各类设备的数量。
13、i、j两个变量实现的功能
i和j两个变量用于循环遍历数组,实现对每个元素的访问和操作。
14、如何判定死锁
系统中的资源是有限的。不足以一下子把所有进程所需的资源都分配。我们需要做的就是在有限的资源下,是否有一个分配顺序,可以使得全部进程都可以获得资源并运行,如果可以则返回一个安全队列,如果不可以,则说明有风险,系统可能会陷入死锁。
15、发生死锁和不发生死锁的输出区别
发生死锁时,无法输出安全队列,只能输出“会发生死锁。无安全队列”。不发生死锁时,可以输出安全队列,即按照一定的顺序运行所有进程。