銀行家算法及其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;
}

全部代碼

銀行家算法源碼

輸入數據文件

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章