OS_死鎖_銀行家算法和安全性測試算法:C++實現

1、實驗目的:
經過對銀行家算法的模擬加深對避免死鎖的理解,掌握銀行家算法和安全性測試算法;
2、實驗內容:
系統中有m個同類資源,被n個進程共享,每一個進程對資源的最大需求數分別爲S一、S二、…、Sn,且Max(Si)<=m(i=1,2,…,n)。進程能夠動態地申請資源和釋放資源。編寫一個程序,實現銀行家算法模擬分配資源以及進行安全性檢測。當系統將資源分配給某一進程而不會死鎖時,就分配之。不然,推遲分配,並顯示適當信息。
3、實驗要求:ios

  1. 將本實驗分紅兩個階段,第一階段實現系統安全性檢測算法(在系統安全的狀況下要求輸出安全序列), 第二階段實現銀行家算法。
  2. 要求用戶能自主地輸入不一樣的向量矩陣。
  3. 程序能正確輸出不一樣的運算結果。
  4. 程序應具有良好的容錯能力。

首先是頭文件和預處理算法

#include<iostream>
#include<fstream>

#define pnum 5
#define rnum 3

pnum是processnum也就是進程數量,rnum是resourcenum也就是資源數量,這是一個關於如何合理的分配資源給進程的算法,在操做系統書上有講解,但願讀者區看看。數組

//定義安全性算法的數據結構
int sign[pnum],//安全序列
    work[pnum][rnum],//記錄要顯示的work,由算法種的work賦值獲得,方便打印輸出
	workAll[pnum][rnum];//work+allocation

//定義銀行家算法的數據結構
int Available[pnum],//可用資源向量available
	Max[pnum][rnum],//最大需求向量,每一個進程的最大需求
	Allocation[pnum][rnum],//分配矩陣,至關於當前已經分配了
	Need[pnum][rnum];//max-allocation,當前還需資源數目向量

根據書上的內容能夠做出以下的定義,銀行家算法的可用資源,最大等(有批註),安全性算法的work是爲了顯示,後面的算法中會有體現,work+allocation是根書上保持一致因此這樣的一個定義,具體的能夠根據書上的表格進行比較,話很少說,老規矩,main函數分析。安全

首先在main函數中咱們是須要申請多少的資源,是哪一個進程申請,因此咱們須要定義個request二維數組,進行一個資源的申請,行爲進程pnum列爲資源rnum
這時候,看了我前面的應該知道,咱們須要進行一個建立,咱們最大資源是多少,有多少個進程什麼什麼的,這些能夠根據書上的已知條件,從而知道咱們有多少數據須要用戶進行一個輸入。數據結構

creat函數進行一個封裝,初始化

基本思想:將max,allocation,need,available數組裝載數值,有些是一維,有些是二維,根據書上的已知條件能夠獲得如何建立,這裏可能有些讀者沒書,在此給出代碼函數

//初始化
void creat(){
	for(int i = 0;i<pnum;i++){
		cout<<"請輸入第 "<<i<<" 個進程的數據:"<<endl;
		cout<<"MAX:第"<<i<<"個進程一共須要申請多少個資源(A B C):";
			for(int j=0;j<rnum;j++)
				cin>>Max[i][j];
			cout<<"Allocation:已得到的資源數量(A B C):  ";
			for(int j=0;j<rnum;j++)
				cin>>Allocation[i][j];
			cout<<"Need:還須要的資源數量(A B C):  ";
			for(int j=0;j<rnum;j++)
				cin>>Need[i][j];

			if(i==0){
				cout<<"Available:現有資源的數量(A B C):  ";
                for(int j = 0;j < rnum;j++)
                        cin>>Available[j];
			}
	}
}

這時候咱們回到咱們的main,建立好了以後咱們須要輸入request數組中是哪一個進程申請資源數量爲多少,爲了讓讀者閱讀方便,在此也給出代碼測試

while(true){
		cout<<endl<<"請輸入Request[進程標號i][資源類型j]:"<<endl;
        cout<<"進程i=:";
        cin>>i;
        cout<<"各種資源數量(A B C):  ";
            for(int j = 0;j < rnum;j++)
                cin>>Request[i][j];
            cout<<endl;
        //執行銀行家算法
            int res = Banker(i,Request);
        //輸出每次判斷產生的執行序列
            cout<<endl<<"當前的資源分配表:"<<endl;
            show(res);
	}

你會發現有banker裏面的參數是進程幾申請資源,最終返回的結果用來輸出,那麼咱們的show應該如何的進行定義呢?
咱們得顯示咱們的資源分配表,若是說安全性算法後還有一個安全隊列,咱們得輸出安全性隊列下的work等一系列,若是沒有,咱們就輸出咱們各個進程初始信息,all+need+available。讓用戶明白本身的申請的問題出錯在哪。操作系統

show:資源分配表的定義

首先show函數得接收一個值,res,表示有無安全序列,若是有,就是個人進程數,若是沒有,就是不能構成安全序列咱們須要輸出它的初始信息
這裏直接給源碼,但願讀者讀懂後能夠評論區留言說說你的理解code

void show(int res){
	if(res == pnum){
		cout<<" 進程號--"<<" Work[A,B,C]"
		<<" Need[A,B,C]"<<" Allocation[A,B,C]"<<" Work+Allocation[A,B,C]"<<" Finish"<<endl;
        for(int i = 0;i < pnum;i++) {
            for(int j = 0;j < rnum;j++)
                cout<<work[sign[i]][j]<<" ";
            cout<<'\t'<<'\t';
            for(int j = 0;j < rnum;j++)
                cout<<Need[sign[i]][j]<<" ";
            cout<<'\t'<<'\t';
            for(int j = 0;j < rnum;j++)
                cout<<Allocation[sign[i]][j]<<" ";
            cout<<'\t'<<'\t';
            for(int j = 0;j < rnum;j++)
                cout<<workAll[sign[i]][j]<<" ";
            cout<<'\t'<<'\t';
            cout<<"true"<<endl;
        }
	cout<<endl<<"安全序列爲:{p["<<sign[0]<<"]";
	for(int m = 1;m<pnum;m++){
		cout<<",p["<<sign[m]<<"]";
	}
	cout<<"}"<<endl;
}
	else{//沒經過輸出信息
		cout<<" 進程號--"<<" Allocation[A,B,C]"
			<<" Need[A,B,C]"<<" Available[A,B,C]"<<endl;
		for(int k = 0;k < 5;k++){
			cout<<'\t'<<"P["<<k<<"]"<<'\t'<<'\t';
			for(int j = 0;j < 3;j++)cout<<Allocation[k][j]<<" ";
			cout<<'\t'<<'\t';
			for(int j = 0;j < 3;j++)cout<<Need[k][j]<<" ";
			cout<<'\t'<<'\t';
			if(k == 0) {
				for(int j = 0;j < 3;j++)
				cout<<Available[j]<<" ";
			}
			cout<<endl;
		}
	}
}

如今進入正題隊列

銀行家算法banker(i,request[][rnum])

基本思想:第一步,//判斷request內的資源是否比可用總數和進程i總共所需的大小,這是基本的條件
如何的實現呢?

for(int j = 0;j < rnum;j++) {
        if(Request[i][j] > Need[i][j]){
            cout<<"分配失敗------>"<<endl<<"所需資源數超出其宣佈的最大值!"<<endl;
            return 0;
        } else if(Request[i][j] > Available[j]) {
                    cout<<"分配失敗------>"<<endl<<"無足夠資源,p["<<i<<"]須要進行wait"<<endl;
                    return 0;
                }
        }

若是經過了,咱們試着分配資源,進行安全性算法,若是沒經過就直接返回了error,也會輸出提示信息。

嘗試分配資源咱們應該怎麼作呢?

首先讓資源總數available減去request,讓進程的allocation加上申請的,need也須要減去request。
大體理解:由於你申請了資源如今在假定分配,因此分配給你了系統的可用資源就要減小,當前進程的已用資源就要增長,目前還需資源就也要減小,由於系統已經知足你的需求了。

for(int j = 0;j < rnum;j++) {
                Available[j] = Available[j] - Request[i][j];
                Allocation[i][j] = Allocation[i][j] + Request[i][j];
                Need[i][j] = Need[i][j] - Request[i][j];
        }

執行安全性算法,根據安全性算法的返回值,肯定是否有隊列,最終輸出顯示的狀況
後續代碼我只給出執行安全性算法,如何讓系統交互作的更好留給讀者。

int n = Safe(Available,Need,Allocation);
        cout<<endl;

        if(n == pnum) {//有5個'true'返回1,表示此時刻安全

接下來來到安全性算法safe,它帶了參數available和need和allocation

咱們爲了方便運算,原來的work爲了存放available總數加上釋放,因此咱們這裏新建一個work數組,它是一維的,由於它只須要將一組的數據進行一個傳遞,finish數組的定義爲了判斷是否有一個隊列,因此它的大小爲pnum。這裏給出定義,ijmn是根據個人需求進行一個添加

int Safe(int Available[],int Need[][rnum],int Allocation[][rnum]) {
	int i=0,j=0,m=0,n=0;
	int Work[rnum],Finish[pnum] = {0,0,0,0,0};

接下來咱們將咱們的可用資源數目給咱們的work臨時一維數組。

進入一個大while,只要咱們的i<進程總數pnum咱們就繼續在循環中找。這裏你應該明白i是爲了計數,看看有無這麼多的進程完成,若是實在沒有咱們的掃描也會結束,到時候finish和i的值都不是理想值

只要對應的finish[i]是等於0 的說明尚未被加入就緒隊列,首先判斷現有的資源總量可否知足它的需求,能夠知足咱們就進行一個分配。這裏分配後直接釋放了,因此咱們能夠直接讓work加上allocation中當前i進程的已用資源allocation,在這以前用咱們的work二維數組記錄下咱們當前的work再去加進行一個變化,這樣在循環中,work中就是顯示未釋放的狀態中的可用資源,讓咱們的workall等於咱們的一維數組work,有些許繞,我附上小部分的代碼,但願讀者鑽研一下。

if(j == rnum){//若是need的三個資源均可以被知足,就分配而且釋放和記錄
				 for(int k = 0;k < rnum;k++){
                    work[i][k] = Work[k];//記錄分配前的可用的資源總數
                    Work[k] = Work[k]+Allocation[i][k];
					workAll[i][k] = Work[k];
				}

若是咱們這一步成功了,說明是能夠分配的,讓咱們的安全序列數組sign中的第一個m變成i。finish[i]=1,i=-1,m++.
i 等於-1是由於在咱們的if(Finish[i]==0){後還有一段代碼,咱們慢慢分析

咱們是從頭開始掃描,因此若是沒加入,或者已經加入過了咱們必須讓咱們的i++,讓咱們的j(用於檢查可用資源是否知足的一個變量)歸零。因此在if中咱們的i=-1,在外++就變成了0,就是繼續從首部查找。

最終根據finish中是否有0,咱們能夠獲得咱們是該返回pnum仍是其餘數字了。

到此已經講述完了,但願讀者可以仔細思考一下問題,後續結果有人提問我再在評論區更新!!!

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息