银行家算法及其C++模拟实现

前言

银行家算法,是我们OS课上的一个非常重要的知识点,感觉可以说是必考题了,但是考试嘛,考过了以后不用就会忘,每次都要重新复(yu)习一遍,又非常麻烦,正好前段时间有机会实现了一遍,赶紧总结下,避免以后又忘了。

正文

银行家算法简介

银行家算法(Banker’s Algorithm)是一个避免死锁(Deadlock)的著名算法,是由艾兹格·迪杰斯特拉在1965年为T.H.E系统设计的一种避免死结产生的演算法。它以银行借贷系统的分配策略为基础,判断并保证系统的安全运行。

(来自wiki)

这里的重点是避免!!! 避免!!! 避免!!!
针对死锁这种坑爹的情况有预防和避免两种大的解决思路,之前总是傻傻分不清楚。这里我们还是通过一个生动的例子来解释吧。

女朋友:康康啊,预防感冒,冲杯板x根吧。
康康:好滴。

女朋友:康康啊,出门系上我给你织的围巾吧,避免感冒。
康康:好几。

感受到预防和避免的差异了嘛,预防就是提前做好准备,而避免则是在实际操作中小心翼翼。
回到死锁,预防死锁就是破坏死锁的四个必要条件之一,而避免死锁则是在进程运行过程中通过一些手段来避免死锁。

算法详解

其实银行家算法非常简单。
系统维护了一张所有进程的资源表。进程对每种资源的总共需求数,当前已分配的资源数,还需要的资源数。
假设系统初始状态为S0,在每次请求资源(并且这次请求合法)时,会假设为进程分配需要的资源,这时系统进入状态S1*,判断这个假设状态是否为安全的,如果是安全的,才会进行真正分配,系统进入S1状态;否则系统不会进行资源分配。
判断系统此时状态是否安全的算法也很简单。
就是假设所有进程能否按照某种顺序运行(这里的运行就是 请求资源->工作->释放资源 这个过程)。
如果存在这样一个进程运行序列,就是安全的。反之则不安全。

源码分析

数据结构

const int process_nums = 5; // 进程数
const int resource_nums = 3; //资源种类数

//进程的两种状态
enum {
    RUNNING = 0,
    SLEEP
};

//模拟的进程 只有pid和state两个成员,默认为SLEEP状态
struct Process
{
    Process(int id):pid(id), state(SLEEP){}
    int pid;
    int state;
};

vector<int> available; //一维数组,记录每种资源的现有(空闲)个数
vector<vector<int>> max_request, allocation, need,request;
//max_request 每个进程对每种资源的总共需求数 二维数组
//allocation 每个进程对每种资源的当前分配数 二维数组
//need 每个进程对每种资源的当前分配数(need[i][j] = max_request[i][j] - allocation[i][j]) 二维数组

vector<Process> process;
//进程组 每个进程的pid = index

模拟流程

    while(isSomeProcessNeedResource(need)){
        //模拟调度,让一个进程开始运行
        now_running_process = scheProcess(need);
        process[now_running_process].state = RUNNING;
        //获取进程此次运行,对于每种资源的需求数
        getRequest(now_running_process, request);
        //判断此次需求是否合法
        for(int i = 0; i < resource_nums; i++){
            //此次需求大于need,说明需求错误
            if(request[now_running_process][i] > need[now_running_process][i]){
                cout << "request error" << endl;
                return -1;
            }
            //此次需求大于available,资源数量不够,让进程阻塞 if(request[now_running_process][i] > available[i]){
                process[now_running_process].state = SLEEP;
                break;
            }
        }
        //如果需求合法,进入分配阶段
        if(process[now_running_process].state == RUNNING){
            //(1)假设分配
            for(int i = 0; i < resource_nums; i++){
                available[i] -= request[now_running_process][i];
                allocation[now_running_process][i] += request[now_running_process][i];
                need[now_running_process][i] -= request[now_running_process][i];                
            }

            print(available, max_request, need ,allocation);
            //判断经过分配后,整个系统是否处于安全状态
            if(judgeSecurity(available, need, process, allocation) == -1){
                //系统不安全,将假设分配的资源还给OS
                for(int i = 0; i < resource_nums; i++){
                    available[i] += request[now_running_process][i];
                    allocation[now_running_process][i] -= request[now_running_process][i];
                    need[now_running_process][i] += request[now_running_process][i];                     
                }

                cout << "now is not security" << endl;
            } else{
                cout << "now is security" << endl;
            }  
            process[now_running_process].state = SLEEP; 
        }
    }

核心算法:安全性检验
判断系统当前状态是否安全。

int judgeSecurity(const vector<int>& available, 
                  const vector<vector<int>>& need, 
                  const vector<Process>& process,
                  const vector<vector<int>> &allocation)
{
    vector<int> work(available);//现有的每种资源空闲数
    vector<bool> finish(process_nums, false);//标志数组,判断进程是否完成工作
    vector<int> security_list;
    int p_nums = process_nums;
    //当需要资源的进程数不为0
    while(p_nums){
        int s = p_nums;
        for(int i = 0; i < process_nums; i++){
            //如果进程还没有完成所有工作,并且它需要的资源数小于现有的空闲资源数,则可以给它分配资源
            if(finish[i] == false && judgeNeed(need[i], work)){
                //分配之后则认为进程已经完成所有工作
                finish[i] = true;
                p_nums--;
                security_list.push_back(i);
                //将进程之前占有的资源释放
                for(int j = 0; j < resource_nums; j++)
                    work[j] += allocation[i][j];
            }
        }
        //如果没有进程能被分配给资源,说明会产生死锁,系统处于不安全状态
        if(s == p_nums)
            return -1;
    }
    //输出当前状态存在的安全序列
    cout << "security_list is :"<< endl;
    for(auto i : security_list)
        cout << "p" << i << "->";
    cout << "end" << endl;
    return 0;
}

全部代码

银行家算法源码

输入数据文件

猜你喜欢

转载自blog.csdn.net/xiyoulinux_kangyijie/article/details/80393596