這個學期的作業系統有兩道題目,辛辛苦苦趕著時間點完成了,寫篇博文記錄一下吧!
項目程式:http://download.csdn.net/detail/crayon_dys/5521261
首先是實驗題目。
1、 採用多級反饋隊列調度演算法進行進程調度。
2、 每個進程對應一個PCB 。在 PCB 中包括進程標識符pid、進程的狀態標識status 、進程優先順序 priority、進程的隊列指標 next 和表示進程生命週期的資料項目life (在實際系統中不包括該項)。
3、 建立進程時即建立一個PCB ,各個進程的pid 都是唯一的,pid 是在1到100 範圍內的一個整數。可以建立一個下標為1 到100 的布爾數組,“真”表示下標對應的進程標識號是閒置,“假”表示下標對應的進程標識號已指派給某個進程。
4、 進程狀態status 的取值為“就緒ready”或“運行run ”,剛建立時,狀態為“ready”。被進程發送器選中後變為“run ”。
5、 進程優先順序priority 是0 到49範圍內的一個隨機整數。
6、 進程生命週期life 是1 到5 範圍內的一個隨機整數。
7、 初始化時,建立一個鄰接表,包含50個就緒隊列,各就緒隊列的進程優先順序priority 分別是0 到49。
8、 為了類比使用者動態提交任務的過程,要求動態建立進程。進入進程調度迴圈後,每次按 ctrl+f 即動態建立一個進程,然後將該 PCB 插入就緒隊列中。按ctrl+q 退出進程調度迴圈。
9、 在進程調度迴圈中,每次選擇優先順序最大的就緒進程來執行。將其狀態從就緒變為運行,通過延時一段時間來類比該進程執行一個時間片的過程,然後優先順序減半,生命週期減一。設計圖形化使用者介面GUI ,在視窗中顯示該進程和其他所有進程的PCB 內容。如果將該運行進程的生命週期不為0 ,則重新把它變為就緒狀態,插入就緒隊列中;否則該進程執行完成,撤消其PCB 。以上為一次進程調度迴圈。
這裡的第八點要求我在GUI中是通過按鍵的方式建立進程和退出進程調度。
下面是我實現過程的一點記錄:首先要理解多級反饋調度演算法是怎麼回事(這個看看書就知道了)。然後明確要實現的過程有什麼要處理。第一是隨機動態建立進程,建立進程的規則上面有說明;其次是進程調度,程式中準備了50個就緒隊列,那麼就要將產生的進程依進程優先順序放到就緒隊列中,之後就根據這個50個就緒隊列來進行調度,調度規則當然也是優先順序,從大到小,調度每一個進程的處理規則,上面的說明也有,生命減一,優先順序減半;第三,就是在進程調度過程還有實現可添加進程的功能。
由於要實現GUI,所以我用java實現,環境是eclipse。程式的主介面如:
下面稍稍解說一下:
整體思路:
1、介面GUI的實現。主視窗中包含兩個Panel,第一個panel是實現一些button;第二個panel是輸出相關的進程調度資訊。
2、進程PCB類:其中包含的變數有:
private int pid; //進程標識符
private int status; //進程的狀態標識,取值為“就緒 ready--0 ”,“運行 run--1 ”,“結束--2”
private int priority; //進程優先順序
private int life; //進程生命週期
並且實現了對應的getter和setter。
3、ButtonPanel類(即第一個panel對應的類)
這個類中實現了每一個button的事件處理
4、ProcessPanel類(即第二個panel對應的類)
這個類主要的功能是輸出進程的調度資訊
首先介紹一下資料的處理方式
程式中有50個就緒隊列,我這裡的處理是:採用java中的linkedlist代替,其實功能都是一樣的,都可以實現先進先出的功能,那麼就需要50個linkedlist,我把它們按序都放到Vector中,這樣就是“隊列數組”了。
// 50個就緒隊列
public static Vector<LinkedList<PCB>> myQueueVector;
下面具體介紹兩個panel類中的內容,這也是這個程式的重點內容。
(一)ButtonPanel類
裡麵包含了一個文本輸入框和六個button。
1、文本輸入框:
輸入初始時要建立的進程個數,根據實驗內容中的建立進程要求建立進程pcb。每調用一次就建立一個進程添加到相對應的就緒隊列中。動態建立進程的方法中含有一個參數index是為了區分是初始時建立,還是在程式運行過程中建立。
建立進程的代碼如下所示:
// 動態建立進程 index == 1 表示是調度過程中的建立void creatProcessToQueue(int index) {PCB newPCB;int aPid;do {Random aRandom = new Random();aPid = aRandom.nextInt(100) % 100;} while (pidArray[aPid] != 0);pidArray[aPid] = 1; // 表示myPCDPid進程以及分配給某個進程// 進程優先順序priority 是0 到49範圍內的一個隨機整數。Random bRandom = new Random();int aPriority = bRandom.nextInt(50) % 50;// 進程生命週期life 是1 到5 範圍內的一個隨機整數。Random cRandom = new Random();int aLife = cRandom.nextInt(5) % 5 + 1;newPCB = new PCB();newPCB.setPid(aPid);newPCB.setPriority(aPriority);newPCB.setStatus(0);newPCB.setLife(aLife);myQueueVector.get(aPriority).add(newPCB);if (index == 1) {ProcessPanel.addProcessShow(newPCB);}}
3、進行進程調度Button
在這個按鍵的事件處理中進行進程調度。進程調度的思想是這樣的:我們從優先順序高的就緒隊列開始往下掃描每一個就緒隊列,如果該就緒隊列中含有進程,那麼根據先進先出的原則彈出進行進程處理,即生命減1,優先順序減半。如果生命值不等於0,那麼就進入相應優先順序的就緒隊列。
每進行一次調度,在第二個panel的第二個文字框中進行顯示。
由於要處理接下來的調度過程中動態添加進程,我把這個進程調度的過程放到一個線程中,並且為了方便顯示,每進行一次調度,延時一秒即sleep。
調度方法的代碼如下:
// 進程調度void doProcessManager(final ProcessPanel processPanel) {processThread = new Thread(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubfor (int i = 49; i >= 0; i--) {LinkedList<PCB> temLinkedList = myQueueVector.get(i);while (temLinkedList.size() != 0) {for (int j = 0; j < temLinkedList.size(); j++) {PCB temPcb = temLinkedList.get(j);temPcb.setStatus(1);// RuntemPcb.setLife((temPcb.getLife() - 1)); // life-1temPcb.setPriority(temPcb.getPriority() / 2); // Priority/2String currentString = "pid:" + temPcb.getPid()+ " priority:" + temPcb.getPriority() + " life:"+ temPcb.getLife() + " status:" + "Run";processPanel.CurrentProcess(currentString);myQueueVector.get(i).remove(j); // removeif (temPcb.getLife() > 0) {myQueueVector.get(temPcb.getPriority()).add(temPcb);}//life=0;Endelse if(temPcb.getLife() == 0){temPcb.setStatus(2);//End}String statuString = "";if (temPcb.getStatus() == 0) {statuString = "Ready";} else if (temPcb.getStatus() == 1) {statuString = "Run";}else if (temPcb.getStatus() == 2) {statuString = "End";}processsStringBuffer.append("Processing-->" + "pid:"+ temPcb.getPid() + " priority:" + temPcb.getPriority()+ " life:" + temPcb.getLife() + " status:"+ statuString + "\n");processPanel.showFinishInfo(processsStringBuffer);//delaytry {Thread.sleep(1000);} catch (InterruptedException ex) {ex.printStackTrace();}}}}processPanel.CurrentProcess("Finish process scheduling !");}});processThread.start();}
4、暫停進程調度Button
在這個button的事件處理中只需要中斷調度進程的運行就可以了。
實現的代碼:
processThread.suspend();
5、建立一個進程Button
前面已經看過了動態建立進程的方法了,其中的參數index如果為1的時候的是符合調度過程中建立進程的。所以還算調用這個方法。
實現的代碼:
creatProcessToQueue(1);
6、恢複進程調度Button
在這個button的事件處理中只需要回複中斷的調度進程就可以了,由於在中斷調度進程的過程中,可能建立了新的進程添加到就緒隊列中,那麼就需要重新掃描就緒隊列,所以這裡的回複進程調度是採用重新調用進程調度方法。
實現的代碼:
doProcessManager(processPanel);
7、退出進程調度Button
在這個button的事件處理中就是退出程式。
實現代碼如下:
System.exit(0);
(一)ProcessPanel類
在第二panel中包含一個顯示當前調度進程資訊的label和兩個文字框,左邊的文字框顯示建立的所有的進程資訊,右邊的文字框顯示的是進程調度的過程。
下面分別介紹一下這三個部分顯示的處理代碼。
①顯示當前調度進程
在調度之前顯示:
在調度過程中顯示:
在調度結束後顯示:
處理的代碼如下:
public void CurrentProcess(String string) {currentLabel.setText(string);if (string.equals("Finish process scheduling !")) {//在rightTextArea輸出結束資訊rightTextArea.append(">>>>>>----Finish process scheduling----<<<<<<"+'\n');}
②左邊文字框顯示建立的所有的進程資訊
這裡的處理是:掃描就緒隊列,逐個隊列進行顯示,調用showProcessInfo() 方法。如果在調度過程中動態添加了進程的話,就調用addProcessShow()。
實現代碼如下:
public void showProcessInfo() {StringBuffer stringBuffer = new StringBuffer();int j = 0;for (int index = 0; index < 50; index++) {LinkedList<PCB> myList = new LinkedList<PCB>();myList = ButtonPanel.getLinkedList(index);if (myList != null) {for (int i = 0; i < myList.size(); i++) {PCB aPcb = myList.get(i);String statuString;if (aPcb.getStatus() == 0) {statuString = "Ready";} else {statuString = "Run";}stringBuffer.append("Process" + j++ + ":" + "pid:"+ aPcb.getPid() + " priority:" + aPcb.getPriority()+ " life:" + aPcb.getLife() + " status:"+ statuString + "\n");}}}leftTextArea.setText(stringBuffer.toString());}
public static void addProcessShow(PCB aPcb) {String string = "Process" + ":" + "pid:"+ aPcb.getPid() + " priority:" + aPcb.getPriority()+ " life:" + aPcb.getLife() + " status:"+ "Ready" + "\n";leftTextArea.append(string);}
③右邊的文字框顯示的是進程調度的過程資訊
這裡的處理是:在進程調度方法中,調用下面這個方法就可以添加相應的調度資訊到文字框中進行顯示。
實現代碼如下:
public void showFinishInfo(StringBuffer stringBuffer) {rightTextArea.setText("");rightTextArea.append(stringBuffer.toString());}