《操作系統》課程實驗(三)
系統資源的分配方式決定了系統的進程和資源狀態是否安全。本設計要求用高級語言編寫和調試一個簡單的用銀行家算法判斷此次資源分配是否安全的方法。通過本實驗可以加深理解有關銀行家算髮的使用方法和概念,並體會和了解系統的安全性的資源分配準則。
在避免死鎖的方法中,允許進程動態地申請資源,但系統在進行資源分配之前,應先計算此次資源分配的安全性。若此次分配不會導致系統進入不安全狀態,則將資源分配給進程; 否則,令進程等待。(所謂安全狀態,是指系統能按某種進程順序(P1, P2, …,Pn)(稱〈P1, P2, …, Pn〉序列爲安全序列),來爲每個進程Pi分配其所需資源,直至滿足每個進程對資源的最大需求,使每個進程都可順利地完成。如果系統無法找到這樣一個安全序列,則稱系統處於不安全狀態。)
T0時刻的資源分配表如下:
T0時刻的安全性:利用安全性算法對T0時刻的資源分配情況進行分析,在T0時刻是否存在着一個安全序列
P1請求資源 (1, 0, 2),則是否存在着一個安全序列?
P4請求資源 (3,3,0),則是否存在着一個安全序列?
編程語言:Java
開發工具:IntelliJ IDEA
- 實驗要求
爲了實現銀行家算法,在系統中必須設置這樣四個數據結構,分別用來描述系統中可利用的資源、所有進程對資源的最大需求、系統中的資源分配,以及所有進程還需要多少資源的情況。
(1) 可利用資源向量Available。
(2) 最大需求矩陣Max。
(3) 分配矩陣Allocation。
(4) 需求矩陣Need。
設Requesti是進程Pi的請求向量,如果Request i[j]=K,表示進程Pi需要K個Rj類型的資源。Pi發出資源請求後,系統按下述步驟進行檢查:
(1) 如果Request i[j]≤Need[i, j],便轉向步驟(2); 否則認爲出錯,因爲它所需要的資源數已超過它所宣佈的最大值。
(2) 如果Request i[j]≤Available[j],便轉向步驟(3); 否則,表示尚無足夠資源,Pi須等待。
(3) 系統試探着把資源分配給進程Pi,並修改下面數據結構中的數值:
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];
(4) 系統執行安全性算法,檢查此次資源分配後系統是否處於安全狀態。若安全,才正式將資源分配給進程Pi,以完成本次分配;否則,將本次的試探分配作廢,恢復原來的資源分配狀態,讓進程Pi等待。
系統所執行的安全性算法可描述如下:
(1) 設置兩個向量:
① 工作向量Work,它表示系統可提供給進程繼續運行所需的各類資源數目,它含有m個元素,在執行安全算法開始時,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;
go to step 2;
(4) 如果所有進程的Finish[i]=true都滿足,則表示系統處於安全狀態;否則,系統處於不安全狀態。
- 實驗代碼
- 類名:BankerClass //銀行家算法
public class BankerClass {
int x = 5;
int y = 3;
int[] Available = {10, 5, 7};
int[][] Max = new int[x][3];
int[][] Alloction = new int[x][3];
int[][] Need = new int[x][3];
int[][] Request = new int[x][3];
int[] Work = new int[3];
int num = 0;//進程編號
Scanner in = new Scanner(System.in);
public BankerClass() {
// Max={{6,3,2},{5,6,1},{2,3,2}};
}
public void setSystemVariable(){//設置各初始系統變量,並判斷是否處於安全狀態。
setMax();
setAlloction();
printSystemVariable();
SecurityAlgorithm();
}
public void setMax() {//設置Max矩陣
System.out.println("請設置各進程的最大需求矩陣Max:");
Max = new int[][]{{7, 5, 3},{3,3,2},{9,0,2},{2,2,2},{4,3,3}};
// for (int i = 0; i < x; i++) {
// System.out.println("請輸入進程P" + i + "的最大資源需求量:");
// for (int j = 0; j < 3; j++) {
// Max[i][j] = in.nextInt();
// }
// }
}
public void setAlloction() {//設置已分配矩陣Alloction
System.out.println("請設置請各進程分配矩陣Alloction:");
// for (int i = 0; i < x; i++) {
// System.out.println("晴輸入進程P" + i + "的分配資源量:");
// for (int j = 0; j < 3; j++) {
// Alloction[i][j] = in.nextInt();
// }
// }
Alloction = new int[][]{{0,1,0},{2,0,0},{3,0,2},{2,1,1},{0,0,2}};
System.out.println("Available=Available-Alloction.");
System.out.println("Need=Max-Alloction.");
for (int i = 0; i < 3; i++) {//設置Alloction矩陣
for (int j = 0; j < x; j++) {
Available[i] = Available[i] - Alloction[j][i];
}
}
for (int i = 0; i < x; i++) {//設置Need矩陣
for (int j = 0; j < 3; j++) {
Need[i][j] = Max[i][j] - Alloction[i][j];
}
}
}
public void printSystemVariable(){
System.out.println("此時資源分配量如下:");
System.out.println("進程 "+" Max "+" Alloction "+" Need "+" Available ");
for(int i=0;i<x;i++){
System.out.print("P"+i+" ");
for(int j=0;j<3;j++){
System.out.print(Max[i][j]+" ");
}
System.out.print("| ");
for(int j=0;j<3;j++){
System.out.print(Alloction[i][j]+" ");
}
System.out.print("| ");
for(int j=0;j<3;j++){
System.out.print(Need[i][j]+" ");
}
System.out.print("| ");
if(i==0){
for(int j=0;j<3;j++){
System.out.print(Available[j]+" ");
}
}
System.out.println();
}
}
public void setRequest() {//設置請求資源量Request
System.out.println("請輸入請求資源的進程編號:");
num= in.nextInt();//設置全局變量進程編號num
System.out.println("請輸入請求各資源的數量:");
for (int j = 0; j < 3; j++) {
Request[num][j] = in.nextInt();
}
System.out.println("即進程P" + num + "對各資源請求Request:(" + Request[num][0] + "," + Request[num][1] + "," + Request[num][2] + ").");
BankerAlgorithm();
}
public void BankerAlgorithm() {//銀行家算法
boolean T=true;
if (Request[num][0] <= Need[num][0] && Request[num][1] <= Need[num][1] && Request[num][2] <= Need[num][2]) {//判斷Request是否小於Need
if (Request[num][0] <= Available[0] && Request[num][1] <= Available[1] && Request[num][2] <= Available[2]) {//判斷Request是否小於Alloction
for (int i = 0; i < 3; i++) {
Available[i] -= Request[num][i];
Alloction[num][i] += Request[num][i];
Need[num][i] -= Request[num][i];
}
} else {
System.out.println("當前沒有足夠的資源可分配,進程P" + num + "需等待。");
T=false;
}
} else {
System.out.println("進程P" + num + "請求已經超出最大需求量Need.");
T=false;
}
if(T==true){
printSystemVariable();
System.out.println("現在進入安全算法:");
SecurityAlgorithm();
}
}
public void SecurityAlgorithm() {//安全算法
boolean[] Finish = {false, false, false, false, false};//初始化Finish
int count = 0;//完成進程數
int circle=0;//循環圈數
int[] S=new int[x];//安全序列
for (int i = 0; i < 3; i++) {//設置工作向量
Work[i] = Available[i];
}
boolean flag = true;
while (count < x) {
if(flag){
System.out.println("進程 "+" Work "+" Alloction "+" Need "+" Work+Alloction ");
flag = false;
}
for (int i = 0; i < x; i++) {
if (Finish[i]==false&&Need[i][0]<=Work[0]&&Need[i][1]<=Work[1]&&Need[i][2]<=Work[2]) {//判斷條件
System.out.print("P"+i+" ");
for (int k = 0; k < 3; k++){
System.out.print(Work[k]+" ");
}
System.out.print("| ");
for (int j = 0; j<3;j++){
Work[j]+=Alloction[i][j];
}
Finish[i]=true;//噹噹前進程能滿足時
S[count]=i;//設置當前序列排號
count++;//滿足進程數加1
for(int j=0;j<3;j++){
System.out.print(Alloction[i][j]+" ");
}
System.out.print("| ");
for(int j=0;j<3;j++){
System.out.print(Need[i][j]+" ");
}
System.out.print("| ");
for(int j=0;j<3;j++){
System.out.print(Work[j]+" ");
}
System.out.println();
}
}
circle++;//循環圈數加1
if(count==x){//判斷是否滿足所有進程需要
System.out.print("此時存在一個安全序列:");
for (int i = 0; i<x;i++){//輸出安全序列
System.out.print("P"+S[i]+" ");
}
System.out.println("故當前可分配!");
break;//跳出循環
}
if(count<circle){//判斷完成進程數是否小於循環圈數
count=5;
System.out.println("當前系統處於不安全狀態,故不存在安全序列。");
break;//跳出循環
}
}
}
}
- 類名:TestBank //主類
class TestBankerClass {
public static void main(String[] args) {
// TODO code application logic here
boolean Choose = true;
String C;
Scanner in = new Scanner(System.in);
BankerClass T = new BankerClass();
System.out.println("這是一個三個進程,初始系統可用三類資源爲{10,8,7}的銀行家算法:");
T.setSystemVariable();
while (Choose == true) {
T.setRequest();
System.out.println("您是否還要進行請求:y/n?");
C = in.nextLine();
if (C.endsWith("n")) {
Choose = false;
}
}
}
}
- 實驗截圖