操作系统实验——银行家算法


一、实验目的

掌握银行家算法思想,并能编程实现。

二、实验内容和要求

1、在Linux环境下编译运行程序;
2、按照教材的算法编写;
3、(*)输入数据从文本文件中读出,不从键盘录入,数据文件格式见以下说明;
4、主要数据结构的变量名和教材中的一致,包括Available、Max、Allocation、Need、Request、Work、Finish。
5、程序可支持不同个数的进程和不同个数的资源;
6、验证教材中的“银行家算法示例”中的例子(包括可成功分配、不可分配)。

三、实验原理

要解释银行家算法,必须先解释操作系统安全状态和不安全状态。

  1. 安全状态:如果存在一个由系统中所有进程构成的安全序列P1,…,Pn,则系统处于安全状态。安全状态一定是没有死锁发生。
  2. 不安全状态:不存在一个安全序列。不安全状态不一定导致死锁。

那么什么是安全序列呢?
安全序列:一个进程序列{P1,…,Pn}是安全的,如果对于每一个进程Pi(1≤i≤n),它以后尚需要的资源量不超过系统当前剩余资源量与所有进程Pj (j < i)当前占有资源量之和。
银行家算法:
按银行家制定的规则为进程分配资源,可以使系统保持在安全状态,具体方法如下:
· 进程首次申请资源的分配
如果系统现存资源可以满足该进程的最大需求量,则按当前的申请量分配资源,否则推迟分配。

· 进程在执行中继续申请资源的分配
若该进程已占用的资源与本次申请的资源之和不超过对资源的最大需求量,且现存资源能满足该进程尚需的最大资源量,则按当前申请量分配资源,否则推迟分配。

· 至少一个进程能完成
在任何时刻保证至少有一个进程能得到所需的全部资源而执行到结束。

银行家算法通过动态地检测系统中资源分配情况和进程对资源的需求情况来决定如何分配资源,并能在确保系统处于安全状态时才把资源分配给申请者,从而避免系统发生死锁。

算法实现

初始化:
由data文件中读取数据数据,分别对可利用资源向量矩阵Available、最大需求矩阵Max、分配矩阵Allocation、需求矩阵Need赋值。

银行家算法:
在避免死锁的方法中,所施加的限制条件较弱,有可能获得令人满意的系统性能。在该方法中把系统的状态分为安全状态和不安全状态,只要能使系统始终都处于安全状态,便可以避免发生死锁。

银行家算法的基本思想是分配资源之前,判断系统是否是安全的;若是,才分配。它是最具有代表性的避免死锁的算法。

设进程curProcess提出请求Request [i],则银行家算法按如下规则进行判断:

  1. 如果Request [curProcess] [i] <= NEED[curProcess][i],则转2;否则,出错。

  2. 如果Request [curProcess] [i] <= Available [i],则转3;否则,等待。

  3. 系统试探分配资源,修改相关数据:
    Available[i] -= Request[cusneed][i];
    Allocation[cusneed][i] += Request[cusneed][i];
    Need[cusneed][i] -= Request[cusneed][i];

  4. 系统执行安全性检查,如安全,则分配成立;否则试探险性分配作废,系统恢复原状,进程等待。

安全性检查算法:

  1. 设置两个工作向量Work = Available,Finish
  2. 从进程集合中找到一个满足下述条件的进程:
    Finish == false;
    Need <= Work;
    如找到,执行3;否则,执行4
  3. 设进程获得资源,可顺利执行,直至完成,从而释放资源。
    Work = Work + Allocation;
    Finish = true;
    GOTO 2
  4. 如所有的进程Finish = true,则表示安全;否则系统不安全。

四、实验程序

代码如下:

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>

typedef int bool;
#define true 1
#define false 0

int processNum;         //进程数
int resourcesNum;       //资源数
int **Allocation;       //各个进程已分配的各种资源数
int **Max;       //各个进程最大需要的各种资源数
int **Need;             //各个进程还需要的各种资源数
int *Available;         //当前可用的各种资源数
int *Request;           //当前进程请求的各资源数
bool *Finish;           //记录各进程是否完成
int *safeSequence;      //安全序列

//初始化
void init(char* argv[], int *flag1, FILE *fp) {
	if(fp == NULL) {
		printf("ERROR!\n");
		*flag1 = 0;
		return ;
	}
	//从文件中读取进程数和资源数
	fscanf(fp, "%d", &processNum);
	fscanf(fp, "%d", &resourcesNum);
    //分配二维数组(Allocation、Max、Need)的大小
    Allocation = (int**)malloc(processNum * sizeof(int*));
    Max = (int**)malloc(processNum * sizeof(int*));
    Need = (int**)malloc(processNum * sizeof(int*));
    for(int i = 0;i < processNum; i++) {
        Allocation[i] = (int*)malloc(resourcesNum * sizeof(int));
        Max[i] = (int*)malloc(resourcesNum * sizeof(int));
        Need[i] = (int*)malloc(resourcesNum * sizeof(int));
    }
    //分配一维数组大小(Available)
    Available = (int*)malloc(resourcesNum * sizeof(int));
    Finish = (int*)malloc(resourcesNum * sizeof(int));
    safeSequence = (int*)malloc(processNum * sizeof(int));

	//初始化系统剩余资源数(刚开始为最大资源数)
	for(int i = 0; i < resourcesNum; i++){
		fscanf(fp, "%d", &Available[i]);
	}

	//初始化已分配的资源矩阵和最大需求矩阵	
	int count = 0;
	while(count < processNum) {
		int curProcess;	//当前进程号
		fscanf(fp, "%d", &curProcess);
		//从data文件中读取进程curProcessd的Allocation和Max
		for(int i = 0; i < resourcesNum; i++) {
			fscanf(fp, "%d", &Allocation[curProcess][i]);
		}
		for(int i = 0; i < resourcesNum; i++) {
			fscanf(fp, "%d", &Max[curProcess][i]);
		}
		count++;
	}

	//初始化进程还需要的各种资源数(Need数组)
    for(int i = 0;i < processNum; i++) {
        for(int j = 0; j < resourcesNum; j++) {
            Need[i][j] = Max[i][j] - Allocation[i][j];
        }
    }

	//分配给各进程一定资源数后,更新系统剩余的资源数
	for(int i = 0; i < resourcesNum; i++) {
		for(int j = 0; j < processNum; j++) {
			Available[i] = Available[i] - Allocation[j][i];
		}
	}
}


//打印当前时刻的安全序列表
void safeShow(int *Work, int curProcess) {
    printf("P%d\t\t ", curProcess);

    for(int j = 0; j < resourcesNum; j++) {
        printf("%d ", Work[j]);
    }

    printf("\t\t ");
    for(int j = 0; j < resourcesNum; j++) {
        printf("%d ", Need[curProcess][j]);
    }

    printf("\t\t ");
    for(int j = 0; j < resourcesNum; j++) {
        printf("%d ", Allocation[curProcess][j]);
    }

    printf("\t\t\t ");
    for(int j = 0; j < resourcesNum; j++) {
        printf("%d ", Work[j] + Allocation[curProcess][j]);
    }

    printf("\n");
}

//判断当前系统是否处于安全状态
bool isSafe() {
    int trueFinished = 0;   //记录进程分配成功的个数
    int *Work = (int*)malloc(resourcesNum * sizeof(int));
    //初始化Work数组
    for(int i = 0; i < resourcesNum; i++) {
        Work[i] = Available[i];
    }

    //初始化Finish数组,开始时所有进程的资源都未分配成功
    for(int i = 0; i < processNum; i++) {
        Finish[i] = false;
    }

    int curProcess = 0;   //当前进程号
    //下面两个temp的作用是:对进程组的每一轮遍历后,即curProcess到头之后,检查一下trueFinished有没有增加。
    int temp = 0;   //记录这一次遍历的trueFinished
    int temp0 = 0;  //记录上一次遍历的trueFinished
    int flag = 0;   //记录是否是第一次遍历各个进程

    while(trueFinished != processNum) {
        int count = 0;      //进程需要的资源数小于系统剩余的资源数的个数
        //当前进程curProcess未完成分配
        if(Finish[curProcess] == false) {
            //检查是否进程需要的资源数是否都小于系统剩余的资源数
            for(int i = 0; i < resourcesNum; i++) {
                if(Need[curProcess][i] <= Work[i])
                    count++;
                else break;
            }
            if(count == resourcesNum) {
                Finish[curProcess] = true; //进程curProcess分配完成
                safeShow(Work, curProcess);
                //将分配给curProcess的资源回收
                for(int i = 0; i < resourcesNum; i++) {
                    Work[i] += Allocation[curProcess][i];
                }
                //将curProcess例如安全序列
                safeSequence[trueFinished] = curProcess;
                trueFinished++;
            }
        }
        curProcess++;
        if(curProcess >= processNum) {
            curProcess = curProcess % processNum;
            //第一次遍历各个进程
            if(flag == 0) {
                temp = trueFinished;
                temp0 = trueFinished;
            }
            //非第一次遍历各个进程
            if(flag == 1) {
                temp = trueFinished;
                //遍历完后的trueFinish和这次遍历前的trueFinish相等
                //即这次遍历完分配完成的进程数没有增加,说明系统剩余
                //的资源已经不能满足任意未分配的进程了,即系统进入不安全状态
                if(temp == temp0) {
                    break;  //退出while循环
                }else {
                    temp0 = temp;
                }
            }
            flag = 1;
        }
        temp = trueFinished;
    }
    free(Work);
    //完成分配的进程数等于内存进程数,即系统出于安全状态
    if(trueFinished == processNum)
        return true;
    else    //系统处于不安全状态
        return false;
}

//打印当前资源分配表
void show() {
    printf("----------------------------当前资源分配表----------------------------\n");
    printf("各资源剩余:");
    for(int i = 0; i < resourcesNum; i++) {
        printf("%d ", Available[i]);
    }
    printf("\n");
    printf("PID\t\t Max\t\t\t Allocation\t\t Need\n");
    for(int i = 0; i < processNum; i++) {
            printf("P%d\t\t ", i);
            for(int j = 0; j < resourcesNum; j++) {
                printf("%d ", Max[i][j]);
            }

            printf("\t\t\t ");
            for(int j = 0; j < resourcesNum; j++) {
                printf("%d ", Allocation[i][j]);
            }

            printf("\t\t\t ");
            for(int j = 0; j < resourcesNum; j++) {
                printf("%d ", Need[i][j]);
            }

        printf("\n");
    }
    printf("----------------------------------------------------------------------\n");
    printf("\n");
}


int main(int argc, char* argv[])
{
    printf("-------------进行系统资源初始化过程-------------\n\n");
	FILE *fp = NULL;
	//printf("%s\n", argv[1]);
	fp = fopen(argv[1],"r");
	printf("---->正在从文件data中读取数据···\n");
	int flag1 = 1;   //记录文件读取成功与否
	init(argv, &flag1, fp);
	if(flag1 == 0) {
		printf("---->读取数据失败!\n\n");	
		return 0;	
	}
	printf("---->读取数据完成!\n");
    printf("\n-----------------系统初始化完成-----------------\n\n");

    printf("\n系统安全情况分析\n");
    printf("-----------------------------------当前时刻的安全序列表-----------------------------------\n");
    printf("PID\t\t Work\t\t Need\t\t Allocation\t\t Work + Allocation\n");

    if(isSafe()) {
        printf("------------------------------------------------------------------------------------------\n");
        printf("当前系统处于安全状态,其中一个安全序列为:");
        for(int i = 0; i < processNum; i++) {
            printf("P%d",safeSequence[i]);
            if(i != processNum - 1)
                printf(" -> ");
        }
        printf("\n");
    }else {
        printf("------------------------------------------------------------------------------------------\n");
        printf("当前系统已处于不安全状态!\n");
        //释放用malloc动态分配的内存,防止内存泄露
        free(Allocation);
        free(Max);
        free(Need);
        free(Available);
        free(Finish);
        free(safeSequence);
        return 0;
    }
    printf("\n");

    show(); //打印当前资源分配表


    while(true) {
        //printf("\n\n是否继续为进程分配资源?(1:是    0:否):");
        //int flag;
        //scanf("%d", &flag);
        int flag;
		fpos_t home;   //记录当前行首位置
		fgetpos(fp, &home); //将文件fp的当前读写位置保存到home中
		int temp;
		if(fscanf(fp, "%d", &temp) != EOF) {   //判断当前文件指针是否指向末尾,注意这里文件指针会前进
			flag = 1;
		} else {
			flag = 0;
		}
		//回退文件指针,回到行首
		fsetpos(fp,&home);
		

        if(flag) { //继续分配资源
			printf("\n\n单击回车键继续为进程分配资源");
			getchar();
            int curProcess; //分配的进程号
            Request = (int*)malloc(resourcesNum * sizeof(int));  //分配请求资源数组大小

            fscanf(fp, "%d", &curProcess);
            printf("从data文件中读取分配资源的进程号:%d\n", curProcess);
            printf("从data文件中读取分配给 P%d 的各资源数:", curProcess);
            for(int i = 0; i < resourcesNum; i++) {
                fscanf(fp, "%d", &Request[i]);
				printf("%d ", Request[i]);
            }
			printf("\n");

            int count = 0;  //记录curProcess请求的各资源小于其需要(Need)资源的个数
            int count2 = 0; //记录curProcess请求的各资源小于系统剩余(Available)资源的个数
            for(int i = 0; i < resourcesNum; i++) {
                if(Request[i] <= Need[curProcess][i]) {
                    count++;
                } else {
                    printf("\nERROR!请求的资源数大于需要的资源数!\n\n");
                    break;
                }
            }
            if(count == resourcesNum) {
                for(int i = 0; i < resourcesNum; i++) {
                    if(Request[i] <= Available[i]) {
                        count2++;
                    }
                    else {
                        printf("\n资源不足,等待其它进程释放资源中!\n\n");
                        break;
                    }
                }
            }
            if(count2 == resourcesNum) {
                //尝试为该进程分配其请求的资源
                for(int i = 0; i < resourcesNum; i++) {
                    Available[i] -= Request[i];
                    Allocation[curProcess][i] += Request[i];
                    Need[curProcess][i] -= Request[i];
                }
                printf("\n系统安全情况分析\n");
                printf("-----------------------------------当前时刻的安全序列表-----------------------------------\n");
                printf("PID\t\t Work\t\t Need\t\t Allocation\t\t Work + Allocation\n");
                if(isSafe()) {
                    printf("------------------------------------------------------------------------------------------\n");
                    printf("资源分配成功!安全序列为:");
                    for(int i = 0; i < processNum; i++) {
                        printf("P%d",safeSequence[i]);
                        if(i != processNum - 1)
                            printf(" -> ");
                    }
                    printf("\n\n");
                    show();
                }else {
                    printf("------------------------------------------------------------------------------------------\n");
                    printf("资源分配失败!若分配会导致系统进入不安全状态!\n\n");
                    //回收尝试分配的资源
                    for(int i = 0; i < resourcesNum; i++) {
                        Available[i] += Request[i];
                        Allocation[curProcess][i] -= Request[i];
                        Need[curProcess][i] += Request[i];
                    }
                }
            }
        }else {
            //释放用malloc动态分配的内存,防止内存泄露
            free(Allocation);
            free(Max);
            free(Need);
            free(Available);
            free(Finish);
            free(safeSequence);
            return 0;
        }
    }
    //释放用malloc动态分配的内存,防止内存泄露
    free(Allocation);
    free(Max);
    free(Need);
    free(Available);
    free(Finish);
    free(safeSequence);
    return 0;
}

五、验证数据和运行结果

运行结果截图

注:实验中所有的数据均从data文件中获取,data文件与banker.c文件放在同一个文件夹中。

测试用例一(实验要求的数据)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
测试用例二 (自己另外加的一组数据)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
测试用例三(自己另外加的一组数据):测试系统刚开始就已经处于不安全状态的情况
在这里插入图片描述
在这里插入图片描述

六、思考与分析

本次实验要求输入数据从文本文件中读出,不从键盘录入,且要求通过命令行参数指定文件,如: ./banker ./data运行。因此需要在程序目录下建立data文件,然后在main函数中添加参数:int main(int argc, char* argv[]) ,其中argc记录参数的个数,argv数组记录在命令行中输入的参数,这里我们运行程序时在命令行中输入的是两个参数:./banker和./data,因此数组argv中存放的就是这两个字符串,argv[1]就是data文件的路径,通过文件指针指向data文件:FILE *fp = fopen(argv[1],“r”); 然后根据data文件中给的数据的顺序依次读取赋给给进程数、系统资源种数、资源最大数向量、已分配资源向量、最大资源需求量向量和资源请求向量赋值,进行系统的初始化。

实验还要求程序可支持不同个数的进程和不同个数的资源;因此程序中的各种数据结构采用数组形式,用malloc实现动态分配大小,根据进程数(processNum)和资源数(resourcesNum)动态分配各数组空间大小,具体可见代码中的初始化函数:void init()。

程序实现:首先从data文件中读取数据对各数据结构进行初始化,若读取失败(命令行参数指定的文件在程序目录下不存在),提示读取失败,结束程序;读取成功,则对刚初始化的系统进行安全性检测,打印安全序列表,若系统处于不安全状态,安全序列表打印出来的进程数就会小于总进程数,并提示系统处于不安全状态,然后结束程序;处于安全状态则列出一个安全序列,并列出当前的资源分配表(包括系统各资源剩余、各进程的Max、Allocation和Need),然后根据当前文件是否读到文件尾(即data文件中有无资源请求),若无则结束程序,有则利用getchar()并提示按下回车进行资源分配,若进程请求的资源大于其需要的最大资源,则提示错误信息;若进程请求的资源大于系统剩余的资源,则提示“资源不足,等待其他进程释放资源“;否则系统尝试分配给该进程申请的资源,然后调用安全性检测isSafe()函数,若系统处于不安全状态,则提示“分配失败,若分配系统将处于不安全状态”,并将尝试分配的资源进行回收;若系统处于安全状态,则将分配后的安全序列表(包括一个安全序列)和当前资源分配表打印出来,然后继续判断文件是否读到文件尾,通过getchar()实现每次按下回车进行一个进程的资源分配。

思考:为什么说找到了安全序列,就能够保证这个此次分配是安全的?safe的本质是什么?
这种安全之说,实际上是建立在一种假设之上的。其实,在实际的执行过程中,我们根本无法确定各进程是否会尽力去申请其声明的最大数额的资源,这是其一;其二,这种序列,也只是一种假设,是我们自己找出来的一种可能的不会造成死锁的方案,进程实际的执行顺序是不可能与我们预测的完全一致的。进程何时停止?到底会申请多少资源?我们无从而知。所以,系统假定所有进程将最终试图获取其声明的最大资源并在之后马上终止,并释放资源。这是一个合理的假设,因为系统不会特意关注每个进程运行了多久。此外,如果一个进程终止前没有获取它能获取的最大数额的资源,也无伤大雅,这种情况对系统而言反而更容易处理。 基于这一假设,该算法通过尝试寻找一个理想的进程请求序列集合来决定是否安全,根据这个集合中的序列方案,每个进程能够获得的最大资源,之后结束,并把资源返还给系统。

附:银行家算法的验证数据文件data格式说明

验证数据:建立在程序目录下建立data文件,文件内容是:
5 3
10 5 7
0 0 1 0 7 5 3
1 2 0 0 3 2 2
2 3 0 2 9 0 2
3 2 1 1 2 2 2
4 0 0 2 4 3 3
1 1 0 2
4 3 3 0
0 0 2 0
第一行:5个进程,3种资源。
第二行:每种资源系统拥有的最大数量。
3-7行:第一列是进程号(按顺序排),2-4列是Allocation(资源请求)向量,5-7列是Max(最大资源需求量)向量。
8-10行:第一列是进程号,2-4列是Request(资源请求)向量。

运行程序,通过命令行参数指定文件,如: ./banker ./data运行。

5 银行家算法实现 5.1 实验类型 设计型(4学时)。 5.2 实验目的 1) 理解死锁避免相关内容; 2) 掌握银行家算法主要流程; 3) 掌握安全性检查流程。 5.3 实验描述 本实验主要对操作系统中的死锁预防部分的理论进行实验。要求实验者设计一个程序,该程序可对每一次资源申请采用银行家算法进行分配。 5.4 实验内容 1) 设计多个资源(≥3); 2) 设计多个进程(≥3); 3) 设计银行家算法相关的数据结构; 4) 动态进行资源申请、分配、安全性检测并给出分配结果。 5.5 实验要求 1) 编写程序完成实验内容; 2) 画出安全性检测函数流程图; 3) 撰写实验报告。 5.6 测试要求 1) 进行Request请求,输入参数为进程号、资源号和资源数; 2) 进行3次以上的Request请求; 3) 至少进行1次资源数目少于可用资源数,但不安全的请求。 5.7 相关知识 5.7.1 银行家算法的数据结构 1) 可利用资源向量Available。其中每个元素代表每类资源的数目。 2) 最大需求矩阵Max。其中每个元素代表每个进程对于每类资源的最大需求量。Max[i,j]=K表示i进程对于j类资源的最大需求量为K。 3) 分配矩阵Allocation。其中每个元素代表每个进程已得到的每类资源的数目。 4) 需求矩阵Need。其中每个元素代表每个进程还需要的每类资源的数目。 5.7.2 银行家算法 Request i [j]=K表示进程Pi需要K个j类资源。 1) 如果Request i [j]≤Need[i , j],便转向步骤2,否则认为出错。 2) 如果Request i [j]≤Available[j],便转向步骤3,否则表示无足够资源,Pi需等待; 3) 系统尝试分配资源给Pi; 4) 系统进行安全性检查,检查此次资源分配后,系统是否安全。如果安全,则正式分配资源,否则撤销此次分配。 5.7.3 安全性算法 1) 设置两个向量:工作向量Work和Finish。算法开始时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; 到第2)步。 4) 直到所有Finish[i]=True,表示系统处于安全状态;否则系统处于不安全状态。 5.8 实验设备 PC机1台,要求安装DOS7.1、Turbo C3.0、Windows2000。 5.9 实验成绩评定 实验成绩评定方式包含实验报告成绩、实验过程成绩两个部分,其中实验过程成绩占60%、实验报告成绩占40%,如果其中任何一个部分成绩不及格,则总成绩按不及格处理。 5.10 实验报告 按照实验目的、实验内容、实验要求、实验设备、测试等部分进行组织。 5.11 实验思考 1) 针对死锁有哪些可行方案? 2) 死锁解除的难点是什么?
实验目的】 1. 理解死锁的概念; 2. 用高级语言编写和调试一个银行家算法程序,以加深对死锁的理解。 【实验准备】 1. 产生死锁的原因  竞争资源引起的死锁  进程推进顺序不当引起死锁 2.产生死锁的必要条件  互斥条件  请求和保持条件  不剥夺条件  环路等待条件 3.处理死锁的基本方法  预防死锁  避免死锁  检测死锁  解除死锁 【实验内容】 1. 实验原理 银行家算法是从当前状态出发,逐个按安全序列检查各客户中谁能完成其工作,然后假定其完成工作且归还全部贷款,再进而检查下一个能完成工作的客户。如果所有客户都能完成工作,则找到一个安全序列,银行家才是安全的。与预防死锁的几种方法相比较,限制条件少,资源利用程度提高了。缺点:该算法要求客户数保持固定不变,这在多道程序系统中是难以做到的;该算法保证所有客户在有限的时间内得到满足,但实时客户要求快速响应,所以要考虑这个因素;由于要寻找一个安全序列,实际上增加了系统的开销.Banker algorithm 最重要的一点是:保证操作系统的安全状态!这也是操作系统判断是否分配给一个进程资源的标准!那什么是安全状态?举个小例子,进程P 需要申请8个资源(假设都是一样的),已经申请了5个资源,还差3个资源。若这个时候操作系统还剩下2个资源。很显然,这个时候操作系统无论如何都不能再分配资源给进程P了,因为即使全部给了他也不够,还很可能会造成死锁。若这个时候操作系统还有3个资源,无论P这一次申请几个资源,操作系统都可以满足他,因为操作系统可以保证P不死锁,只要他不把剩余的资源分配给别人,进程P就一定能顺利完成任务。 2.实验题目 设计五个进程{P0,P1,P2,P3,P4}共享三类资源{A,B,C}的系统,{A,B,C}的资源数量分别为10,5,7。进程可动态地申请资源和释放资源,系统按各进程的申请动态地分配资源。要求程序具有显示和打印各进程的某一时刻的资源分配表和安全序列;显示和打印各进程依次要求申请的资源号以及为某进程分配资源后的有关资源数据。 3.算法描述 我们引入了两个向量:Resourse(资源总量)、Available(剩余资源量) 以及两个矩阵:Claim(每个进程的最大需求量)、Allocation(已为每个进程分配的数量)。它们共同构成了任一时刻系统对资源的分配状态。 向量模型: R1 R2 R3 矩阵模型: R1 R2 P1 P2 P3 这里,我们设置另外一个矩阵:各个进程尚需资源量(Need),可以看出 Need = Claim – Allocation(每个进程的最大需求量-剩余资源量) 因此,我们可以这样描述银行家算法: 设Request[i]是进程Pi的请求向量。如果Request[i , j]=k,表示Pi需k个Rj类资源。当Pi发出资源请求后,系统按下述步骤进行检查: (1) if (Request[i]<=Need[i]) goto (2); else error(“over request”); (2) if (Request[i]<=Available[i]) goto (3); else wait(); (3) 系统试探性把要求资源分给Pi(类似回溯算法)。并根据分配修改下面数据结构中的值。 剩余资源量:Available[i] = Available[i] – Request[i] ; 已为每个进程分配的数量: Allocation[i] = Allocation[i] + Request[i]; 各个进程尚需资源量:Need[i] = Need[i]-Request[i]; (4) 系统执行安全性检查,检查此次资源分配后,系统是否处于安全状态。若安全,才正式将资源分配给进程以完成此次分配;若不安全,试探方案作废,恢复原资源分配表,让进程Pi等待。 系统所执行的安全性检查算法可描述如下: 设置两个向量:Free、Finish 工作向量Free是一个横向量,表示系统可提供给进程继续运行所需要的各类资源数目,它含有的元素个数等于资源数。执行安全算法开始时,Free = Available .标记向量Finish是一个纵向量,表示进程在此次检查中中是否被满足,使之运行完成,开始时对当前未满足的进程做Finish[i] = false;当有足够资源分配给进程(Need[i]<=Free)时,Finish[i]=true,Pi完成,并释放资源。 (1)从进程集中找一个能满足下述条件的进程Pi ① Finish[i] == false(未定) ② Need[i] D->B->A A 1 6 B 1 5 C 2 4 D 4 7 Available = (2) ; Resourse = (10) ; 测试结果如下 process number:5 resource number:4 resource series:6 3 4 2 assined matrix:p0:3 0 1 1 p1:0 1 0 0 p2:1 1 1 0 p3:1 1 0 1 p4:0 0 0 0 needed matrix: p0:1 1 0 0 p1:0 1 1 2 p2:3 1 0 0 p3:0 0 1 0 p4:2 1 1 0 p3-->p4-->p0-->p2-->p1 p3-->p4-->p0-->p1-->p2 p3-->p0-->p4-->p2-->p1 p3-->p0-->p4-->p1-->p2 p3-->p0-->p2-->p4-->p1 p3-->p0-->p2-->p1-->p4 p3-->p0-->p1-->p4-->p2 p3-->p0-->p1-->p2-->p4 it is safe,and it has 8 solutions
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值