文章目錄
一、實驗目的
用高級語言編寫和調試一個或多個作業調度的模擬程序,以加深對作業調度算法的理解。因爲源碼中我對一些關鍵步驟的註釋已經比較清晰了,所以在本文中不會再對每一個細節都進行分析,只分析整體的代碼結構和所使用到的設計模式。
博客內所有文章均爲 原創,所有示意圖均爲 原創,若轉載請附原文鏈接。
二、實驗內容
2.1 數據結構
-
1.可利用資源向量 Available ,它是一個含有 m 個元素的數組,其中的每一個元素代表一類可利用的資源的數目,其初始值是系統中所配置的該類全部可用資源數目。其數值隨該類資源的分配和回收而動態地改變。如果Available(j) = k,表是系統中現有Rj類資源k個。
-
2.最大需求矩陣 Max,這是一個n×m的矩陣,它定義了系統中 n 個進程中的每一個進程對 m 類資源的最大需求。如果Max(i,j) = k,表示進程 i 需要 Rj 類資源的最大數目爲 k 。
-
3.分配矩陣 Allocation,這是一個 n×m 的矩陣,它定義了系統中的每類資源當前一分配到每一個進程的資源數。如果 Allocation(i,j) = k,表示進程 i 當前已經分到 Rj 類資源的數目爲 k 。Allocationi 表示進程i的分配向量,有矩陣 Allocation 的第 i 行構成。
-
4.需求矩陣 Need,這是一個 n×m 的矩陣,用以表示每個進程還需要的各類資源的數目。如果Need(i,j) = k,表示進程i還需要 Rj 類資源 k 個,才能完成其任務。Needi 表示進程i的需求向量,由矩陣 Need 的第 i 行構成。
-
上述三個矩陣間存在關係:Need(i,j) = Max(i,j) - Allocation(i,j);
2.2 銀行家算法
設 Requesti 是進程 Pi 的請求向量,如果 Requesti[j] = K,表示進程 Pi 需要 K 個 Pj 類型的資源。當 Pi 發出自願請求後,系統按下述步驟進行檢查:
- (1)如果 Requesti[j] <= Need[i,j],便轉向步驟(2);否則認爲出錯,因爲它所需要的資源數已超過它所宣佈的最大值。
- (2)如果Requesti[j] <= Available[j],便轉向步驟(3);否則,表示尚無足夠資源,Pi 需等待。
- (3)系統試探着把資源分配給進程 Pi,並修改下面數據結構中的數值:
Available[j] = Available[j] - Requesti[j];
Allocation[i,j] = Allocation + Requesti[j];
Need[i,j] = Need[i,j] - Requesti[j]; - (4)系統執行安全性算法,檢查此次資源分配後系統是否處於安全狀態。若安全,才正式將資源分配給進程 Pi,以完成本次分配;否則,將本次的試探性分配作廢,恢復原來的資源分配狀態,讓進程 Pi 等待。
2.3 安全性算法
-
1.設置兩個向量。
Work:它表示系統可提供給進程繼續運行的各類資源數目,它包含m個元素,開始執行安全性算法時,Work = Available。
Finish:它表示系統是否有足夠的資源分配給進程,使之運行完成,開始Finish(i)=false;當有足夠資源分配給進程Pi時,令Finish(i)=true; -
2.從進程集合中找到一個能滿足下述條件的進程。
Finish(i) == false;
Need i ≤ work;
如找到則執行步驟3;否則,執行步驟4; -
3.當進程 Pi 獲得資源後,可順利執行直到完成,並釋放出分配給它的資源,故應執行
Work = work + Allocation i
Finish(i) = true;轉向步驟2; -
4.若所有進程的 Finish(i) 都爲true,則表示系統處於安全狀態;否則,系統處於不安全狀態。
三、流程圖
3.1 單道批處理系統的作業調度
四、代碼實現
#include <iostream>
#include <vector>
typedef std::vector<int> Resource;
typedef std::vector<int> * ResourcePtr;
typedef std::vector<std::vector<int>> Resources;
typedef std::vector<std::vector<int>> * ResourcesPtr;
class BankerAlgorithm
{
public:
BankerAlgorithm()
{
/*
process_num_ = process_num;
resource_num_ = resource_num;
*/
// should input by user
//available_ = new std::vector<int>(resource_num, 0);
/*
(*available_)[0] = 3;
(*available_)[1] = 3;
(*available_)[2] = 2;
*/
//allocation_ = createResourceArray(process_num, resource_num);
//need_ = createResourceArray(process_num, resource_num);
/*
(*need_)[0][0] = 7; (*need_)[0][1] = 4; (*need_)[0][2] = 3;
(*need_)[1][0] = 1; (*need_)[1][1] = 2; (*need_)[1][2] = 2;
(*need_)[2][0] = 6; (*need_)[2][1] = 0; (*need_)[2][2] = 0;
(*need_)[3][0] = 0; (*need_)[3][1] = 1; (*need_)[3][2] = 1;
(*need_)[4][0] = 4; (*need_)[4][1] = 3; (*need_)[4][2] = 1;
(*allocation_)[0][0] = 0; (*allocation_)[0][1] = 1; (*allocation_)[0][2] = 0;
(*allocation_)[1][0] = 2; (*allocation_)[1][1] = 0; (*allocation_)[1][2] = 0;
(*allocation_)[2][0] = 3; (*allocation_)[2][1] = 0; (*allocation_)[2][2] = 2;
(*allocation_)[3][0] = 2; (*allocation_)[3][1] = 1; (*allocation_)[3][2] = 1;
(*allocation_)[4][0] = 0; (*allocation_)[4][1] = 0; (*allocation_)[4][2] = 2;
*/
}
inline ResourcesPtr createResourceArray(int row_num, int col_num)
{
return new std::vector<std::vector<int>>(row_num, std::vector<int>(col_num, 0));
}
inline ResourcesPtr copyResourceArray(ResourcesPtr ori)
{
int col_num = (*ori)[0].size();
int row_num = (*ori).size();
ResourcesPtr res = createResourceArray(row_num, col_num);
for (int i = 0; i < row_num; ++i)
for (int j = 0; j < col_num; ++j)
(*res)[i][j] = (*ori)[i][j];
return res;
}
bool inputInitData()
{
std::cout << "please input process num and resource num: " << std::endl;
std::cin >> process_num_ >> resource_num_;
// allocate memory for struct
available_ = new std::vector<int>(resource_num_, 0);
allocation_ = createResourceArray(process_num_, resource_num_);
need_ = createResourceArray(process_num_, resource_num_);
std::cout << "please input init resource: " << std::endl;
for (int i = 0; i < resource_num_; ++i)
std::cin >> (*available_)[i];
std::cout << "please input max matrix: " << std::endl;
ResourcesPtr max = createResourceArray(process_num_, resource_num_);
bool inputSuccess = true;
do {
inputSuccess = true;
for (int i = 0; i < process_num_; ++i)
{
for (int j = 0; j < resource_num_; ++j)
{
std::cin >> (*max)[i][j];
if ((*max)[i][j] > (*available_)[j])
{
inputSuccess = false;
max->clear();
std::cout << "max matrix is illegal, please reinput max matrix: " << std::endl;
break;
}
}
}
} while (!inputSuccess);
std::cout << "please input allocation matrix: " << std::endl;
for (int i = 0; i < process_num_; ++i)
{
for (int j = 0; j < resource_num_; ++j)
{
std::cin >> (*allocation_)[i][j];
(*need_)[i][j] = (*max)[i][j] - (*allocation_)[i][j];
(*available_)[j] -= (*allocation_)[i][j];
}
}
std::cout << "current available resource: [";
for (int num : *available_)
std::cout << num << " ";
std::cout << "]" << std::endl;
std::vector<int> * req = new std::vector<int>(resource_num_, 0);
if (!bankerAlgorithm(-1, req))
{
std::cout << "init fail, data is illegal!" << std::endl;
}
bool quit = false;
while (!quit)
{
std::cout << "please input request process: " << std::endl;
int pid = -1;
std::cin >> pid;
std::cout << "please input request resource: " << std::endl;
for (int i = 0; i < resource_num_; ++i)
std::cin >> (*req)[i];
// do allocate.
bankerAlgorithm(pid, req);
}
}
inline bool allocateResourcesForProcess(int pid, ResourcePtr request)
{
return bankerAlgorithm(pid, request);
}
bool bankerAlgorithm(int pid, ResourcePtr request)
{
for (int i = 0; pid != -1 && i < (*request).size(); ++i)
{
if ((*request)[i] > (*need_)[pid][i])
{
std::cout << "[ERROR] request Resource more than need ResourcePtr." << std::endl;
return false;
}
else if ((*request)[i] > (*available_)[i])
{
std::cout << "[ERROR] request Resource more than available ResourcePtr." << std::endl;
return false;
}
}
// Here the copied value is passed
if (securityAlgorithm(pid, *available_, *request, *need_, *allocation_))
{
std::cout << "[INFO] securityAlgorithm true" << std::endl;
// Really allocate resources to process
for (int i = 0; pid != -1 && i < (*request).size(); ++i)
{
(*available_)[i] -= (*request)[i];
(*allocation_)[pid][i] += (*request)[i];
(*need_)[pid][i] -= (*request)[i];
}
// Debug
printResources();
return true;
}
else
{
std::cout << "[INFO] securityAlgorithm false" << std::endl;
// Don't allocate resources to process
// Debug
printResources();
return false;
}
}
bool securityAlgorithm(int pid, Resource available, Resource request, Resources need, Resources allocation)
{
if (pid != -1)
{
for (int i = 0; i < request.size(); ++i)
{
available[i] -= request[i];
allocation[pid][i] += request[i];
need[pid][i] -= request[i];
}
}
Resource work(available);
std::vector<bool> finish(allocation.size(), false);
while ((pid = getUsableProcessForSecurityAlgorithm(finish, work, need)) != -1)
{
for (int i = 0; i < work.size(); ++i)
work[i] += allocation[pid][i];
finish[pid] = true;
std::cout << "[INFO] process " << pid << " finish true, work: [";
for (int num : work)
std::cout << num << " ";
std::cout << "]" << std::endl;
}
for (bool b : finish)
if (!b) return false;
return true;
}
// return pid
int getUsableProcessForSecurityAlgorithm(std::vector<bool> finish, Resource work, Resources need)
{
for (int pid = 0; pid < finish.size(); ++pid)
{
if (!finish[pid])
{
bool canUse = true;
for (int i = 0; i < work.size(); ++i)
{
if (need[pid][i] > work[i])
{
canUse = false;
break;
}
}
if (canUse) return pid;
}
}
return -1;
}
bool printResources()
{
std::cout << "available: " << std::endl;
for (int num : *available_)
std::cout << num << " ";
std::cout << std::endl << std::endl;
std::cout << "allocation: " << std::endl;
printResource(allocation_);
std::cout << std::endl;
std::cout << "need: " << std::endl;
printResource(need_);
std::cout << std::endl;
}
bool printResource(ResourcesPtr ResourcesPtr)
{
for (std::vector<int> vec : *ResourcesPtr)
{
for (int num : vec)
std::cout << num << " ";
std::cout << std::endl;
}
return true;
}
private:
int process_num_;
int resource_num_;
ResourcePtr available_;
ResourcesPtr allocation_;
ResourcesPtr need_;
};
五、運行結果
5.1 初始化
5.2 驗證初始化狀態的安全性
5.3 進程1請求資源 1 0 2 並通過安全性檢查,分配給它資源
5.4 進程4請求資源 3 3 0 並因爲其請求資源大於Available資源,因此讓進程4等待
5.5 進程0請求資源 0 2 0 並因爲進行安全性檢查時不存在安全序列,因此不分配資源
5.6 進程0請求資源 0 1 0 並因爲符合安全性檢查,存在安全隊列,因此分配資源
六、結尾
如果本文描述的內容或使用的代碼存在任何問題,請及時聯繫我或在本篇文章的下面進行評論,我會本着對每一位學技術同學的負責態度立即修改。在後續還會有三篇計算機操作系統的算法 C++ 復現博文,如果感興趣可以關注我。