一、實驗內容
按優先數調度算法實現處理器調度。
二、實驗目的
在採用多道程序設計的系統中,往往有若干個進程同時處於就緒狀態。當就緒進程個數大於處理器數時,就必須依照某種策略來決定哪些進程優先佔用處理器。本實驗模擬在單處理器情況下的處理器調度,幫助學生加深瞭解處理器調度的工作。
三、實驗原理
設計一個按優先數調度算法實現處理器調度的程序。
(1) 假定系統有五個進程,每一個進程用一個進程控制塊PCB來代表,進程控制塊的格式爲:
class PCB {
public String pcbName;
public PCB next;
public int time;
public int priority;
public char state = 'R';
public PCB(String pcbName, int time, int priority) {
this.pcbName = pcbName;
this.time = time;
this.priority = priority;
}
@Override
public String toString() {
return "進程名:" + pcbName + " 要求運行時間:" + time + " 優先級數:" + priority
+ " 狀態:" + state;
}
}
其中,進程名——作爲進程的標識,假設五個進程的進程名分別爲P1,P2,P3,P4,P5。
指針——按優先數的大小把五個進程連成隊列,用指針指出下一個進程的進程控制塊的首地址,最後一個進程中的指針爲“0”。
要求運行時間——假設進程需要運行的單位時間數。
優先數——賦予進程的優先數,調度時總是選取優先數大的進程先執行。
狀態——可假設有兩種狀態,“就緒”狀態和“結束”狀態。五個進程的初始狀態都爲“就緒”,用“R”表示,當一個進程運行結束後,它的狀態爲“結束”,用“E”表示。
(2) 在每次運行你所設計的處理器調度程序之前,爲每個進程任意確定它的“優先數”和“要求運行時間”。
(3) 爲了調度方便,把五個進程按給定的優先數從大到小連成隊列。用一單元指出隊首進程,用指針指出隊列的連接情況。例:
(4) 處理器調度總是選隊首進程運行。採用動態改變優先數的辦法,進程每運行一次優先數就減“1”。由於本實驗是模擬處理器調度,所以,對被選中的進程並不實際的啓動運行,而是執行:
優先數-1
要求運行時間-1
來模擬進程的一次運行。
System.out.println("開始執行" + cur.pcbName + "進程");
System.out.println(cur);
//cur的運行優先級-1 運行時間-1
cur.priority -= 1;
cur.time -= 1;
System.out.println(cur.pcbName + "進程執行完畢");
提醒注意的是:在實際的系統中,當一個進程被選中運行時,必須恢復進程的現場,讓它佔有處理器運行,直到出現等待事件或運行結束。在這裏省去了這些工作。
(5) 進程運行一次後,若要求運行時間不爲0,則再將它加入隊列(按優先數大小插入,且置隊首標誌);若要求運行時間=0,則把它的狀態修改成“結束”(E),且退出隊列。
public void addPCB(PCB node) {
//如果所需運行時間爲0,狀態改爲E 退出進程隊列
if (node.time == 0) {
node.state = 'E';
System.out.println(node.pcbName + "退出進程隊列");
System.out.println(node);
System.out.println();
return;
}
//若頭結點爲空
if (this.head == null) {
this.head = node;
return;
}
//進行邊插邊按優先級進行排序
//如果優先級比頭結點大
if (node.priority > this.head.priority) {
node.next = this.head;
this.head = node;
return;
}
//如果和頭結點優先級相同,按先來先服務原則
if (node.priority == this.head.priority) {
node.next = this.head.next;
this.head.next = node;
return;
}
//在node的優先級在中間插入
PCB cur = this.head.next;
PCB parent = this.head;
while (cur != null) {
if (node.priority > cur.priority) {
//進行插入
node.next = parent.next;
parent.next = node;
return;
} else if (node.priority == cur.priority) {
//優先級相同,按先來先服務原則
parent = cur;
node.next = parent.next;
parent.next = node;
return;
}
parent = cur;
cur = cur.next;
}
//此時還未結束說明優先級最下就直接插到尾
parent.next = node;
node.next = null;
}
(6) 若“就緒”狀態的進程隊列不爲空,則重複上面(4)和(5)的步驟,直到所有進程都成爲“結束”狀態。
//進程運行方法
public void runPCB() {
while (this.head != null) {
//運行優先級最高的第一個進程
PCB cur = this.head;
this.head = this.head.next;
System.out.println();
System.out.println("開始執行" + cur.pcbName + "進程");
System.out.println(cur);
//cur的運行優先級-1 運行時間-1
cur.priority -= 1;
cur.time -= 1;
System.out.println(cur.pcbName + "進程執行完畢");
System.out.println();
//將cur再插入進程隊列
addPCB(cur);
//運行一次結束後遍歷顯示此時進程隊列所有信息
if (this.head == null) {
System.out.println("所有進程執行完畢");
return;
}
System.out.println("此時進程隊列的所有進程信息:");
System.out.println("=================");
display();
System.out.println("=================");
}
}
(7) 在所設計的程序中應有顯示或打印語句,能顯示或打印每次被選中進程的進程名以及運行一次後進程隊列的變化。
(8) 爲五個進程任意確定一組“優先數”和“要求運行時間”,啓動所設計的處理器調度程序,顯示或打印逐次被選中進程的進程名以及進程控制塊的動態變化過程。
四、實現代碼
class PCB {
public String pcbName;
public PCB next;
public int time;
public int priority;
public char state = 'R';
public PCB(String pcbName, int time, int priority) {
this.pcbName = pcbName;
this.time = time;
this.priority = priority;
}
@Override
public String toString() {
return "進程名:" + pcbName + " 要求運行時間:" + time + " 優先級數:" + priority
+ " 狀態:" + state;
}
}
public class ProcessScheduling {
private PCB head;
//pcb對象插入操作
public void addPCB(PCB node) {
//如果所需運行時間爲0,狀態改爲E 退出進程隊列
if (node.time == 0) {
node.state = 'E';
System.out.println(node.pcbName + "退出進程隊列");
System.out.println(node);
System.out.println();
return;
}
//若頭結點爲空
if (this.head == null) {
this.head = node;
return;
}
//進行邊插邊按優先級進行排序
//如果優先級比頭結點大
if (node.priority > this.head.priority) {
node.next = this.head;
this.head = node;
return;
}
//如果和頭結點優先級相同,按先來先服務原則
if (node.priority == this.head.priority) {
node.next = this.head.next;
this.head.next = node;
return;
}
//在node的優先級在中間插入
PCB cur = this.head.next;
PCB parent = this.head;
while (cur != null) {
if (node.priority > cur.priority) {
//進行插入
node.next = parent.next;
parent.next = node;
return;
} else if (node.priority == cur.priority) {
//優先級相同,按先來先服務原則
parent = cur;
node.next = parent.next;
parent.next = node;
return;
}
parent = cur;
cur = cur.next;
}
//此時還未結束說明優先級最下就直接插到尾
parent.next = node;
node.next = null;
}
//進程運行方法
public void runPCB() {
while (this.head != null) {
//運行優先級最高的第一個進程
PCB cur = this.head;
this.head = this.head.next;
System.out.println();
System.out.println("開始執行" + cur.pcbName + "進程");
System.out.println(cur);
//cur的運行優先級-1 運行時間-1
cur.priority -= 1;
cur.time -= 1;
System.out.println(cur.pcbName + "進程執行完畢");
System.out.println();
//將cur再插入進程隊列
addPCB(cur);
//運行一次結束後遍歷顯示此時進程隊列所有信息
if (this.head == null) {
System.out.println("所有進程執行完畢");
return;
}
System.out.println("此時進程隊列的所有進程信息:");
System.out.println("=================");
display();
System.out.println("=================");
}
}
public void display() {
for (PCB pcb = this.head; pcb != null; pcb = pcb.next) {
System.out.println(pcb);
}
}
}
五、測試
public class TestProcess {
public static void main(String[] args) {
PCB[] pcbs = new PCB[5];
pcbs[0] = new PCB("P1", 2, 1);
pcbs[1] = new PCB("P2", 3, 5);
pcbs[2] = new PCB("P3", 1, 3);
pcbs[3] = new PCB("P4", 2, 4);
pcbs[4] = new PCB("P5", 4, 2);
ProcessScheduling processScheduling = new ProcessScheduling();
for (PCB p : pcbs
) {
processScheduling.addPCB(p);
}
processScheduling.runPCB();
}
}
測試結果
開始執行P2進程
進程名:P2 要求運行時間:3 優先級數:5 狀態:R
P2進程執行完畢
此時進程隊列的所有進程信息:
=================
進程名:P4 要求運行時間:2 優先級數:4 狀態:R
進程名:P2 要求運行時間:2 優先級數:4 狀態:R
進程名:P3 要求運行時間:1 優先級數:3 狀態:R
進程名:P5 要求運行時間:4 優先級數:2 狀態:R
進程名:P1 要求運行時間:2 優先級數:1 狀態:R
=================
開始執行P4進程
進程名:P4 要求運行時間:2 優先級數:4 狀態:R
P4進程執行完畢
此時進程隊列的所有進程信息:
=================
進程名:P2 要求運行時間:2 優先級數:4 狀態:R
進程名:P3 要求運行時間:1 優先級數:3 狀態:R
進程名:P4 要求運行時間:1 優先級數:3 狀態:R
進程名:P5 要求運行時間:4 優先級數:2 狀態:R
進程名:P1 要求運行時間:2 優先級數:1 狀態:R
=================
開始執行P2進程
進程名:P2 要求運行時間:2 優先級數:4 狀態:R
P2進程執行完畢
此時進程隊列的所有進程信息:
=================
進程名:P3 要求運行時間:1 優先級數:3 狀態:R
進程名:P2 要求運行時間:1 優先級數:3 狀態:R
進程名:P4 要求運行時間:1 優先級數:3 狀態:R
進程名:P5 要求運行時間:4 優先級數:2 狀態:R
進程名:P1 要求運行時間:2 優先級數:1 狀態:R
=================
開始執行P3進程
進程名:P3 要求運行時間:1 優先級數:3 狀態:R
P3進程執行完畢
P3退出進程隊列
進程名:P3 要求運行時間:0 優先級數:2 狀態:E
此時進程隊列的所有進程信息:
=================
進程名:P2 要求運行時間:1 優先級數:3 狀態:R
進程名:P4 要求運行時間:1 優先級數:3 狀態:R
進程名:P5 要求運行時間:4 優先級數:2 狀態:R
進程名:P1 要求運行時間:2 優先級數:1 狀態:R
=================
開始執行P2進程
進程名:P2 要求運行時間:1 優先級數:3 狀態:R
P2進程執行完畢
P2退出進程隊列
進程名:P2 要求運行時間:0 優先級數:2 狀態:E
此時進程隊列的所有進程信息:
=================
進程名:P4 要求運行時間:1 優先級數:3 狀態:R
進程名:P5 要求運行時間:4 優先級數:2 狀態:R
進程名:P1 要求運行時間:2 優先級數:1 狀態:R
=================
開始執行P4進程
進程名:P4 要求運行時間:1 優先級數:3 狀態:R
P4進程執行完畢
P4退出進程隊列
進程名:P4 要求運行時間:0 優先級數:2 狀態:E
此時進程隊列的所有進程信息:
=================
進程名:P5 要求運行時間:4 優先級數:2 狀態:R
進程名:P1 要求運行時間:2 優先級數:1 狀態:R
=================
開始執行P5進程
進程名:P5 要求運行時間:4 優先級數:2 狀態:R
P5進程執行完畢
此時進程隊列的所有進程信息:
=================
進程名:P1 要求運行時間:2 優先級數:1 狀態:R
進程名:P5 要求運行時間:3 優先級數:1 狀態:R
=================
開始執行P1進程
進程名:P1 要求運行時間:2 優先級數:1 狀態:R
P1進程執行完畢
此時進程隊列的所有進程信息:
=================
進程名:P5 要求運行時間:3 優先級數:1 狀態:R
進程名:P1 要求運行時間:1 優先級數:0 狀態:R
=================
開始執行P5進程
進程名:P5 要求運行時間:3 優先級數:1 狀態:R
P5進程執行完畢
此時進程隊列的所有進程信息:
=================
進程名:P1 要求運行時間:1 優先級數:0 狀態:R
進程名:P5 要求運行時間:2 優先級數:0 狀態:R
=================
開始執行P1進程
進程名:P1 要求運行時間:1 優先級數:0 狀態:R
P1進程執行完畢
P1退出進程隊列
進程名:P1 要求運行時間:0 優先級數:-1 狀態:E
此時進程隊列的所有進程信息:
=================
進程名:P5 要求運行時間:2 優先級數:0 狀態:R
=================
開始執行P5進程
進程名:P5 要求運行時間:2 優先級數:0 狀態:R
P5進程執行完畢
此時進程隊列的所有進程信息:
=================
進程名:P5 要求運行時間:1 優先級數:-1 狀態:R
=================
開始執行P5進程
進程名:P5 要求運行時間:1 優先級數:-1 狀態:R
P5進程執行完畢
P5退出進程隊列
進程名:P5 要求運行時間:0 優先級數:-2 狀態:E
所有進程執行完畢
Process finished with exit code 0