一. 實驗目的
理解進程運行的並發性
理解進程各種狀態及其之間的轉換
理解進程管理中PCB的結構
掌握優先數進程調度算法
二. 實驗內容
用 VC編寫實現進程調度算法模擬進程調度的實現過程。調度算法采用的是動態優先數與時間片相結合的算法。要求如下:
- 進程相關信息如進程標識符及進程所需時間都放入PCB中;
- 設計運行、完成和就緒三個進程隊列;
- 就緒隊列按優先數從小到大排列,每次選擇優先數最大的就緒進程運行。初始優先數定為用一個較大的數(如30)減去進程運行時間,隨着進程的運行對優先數進行調整;
- 進程每執行一次,優先數減一個固定值(如3),CPU時間加1,進程所需時間減1.如果進程所需時間變為0,說明進程運行完畢,將其狀態置為"F",將其PCB插入到完成隊列中,此時若就緒隊列不空,則將就緒隊列的第一個PCB變為運行狀態。 如果進程未完成,則將其優先數和就緒隊列中第一個PCB優先數比較,如果小,則將其變為就緒態,插入就緒隊列中適當位置,同時將就緒隊列中第一個PCB變為運行態。重復上述過程直到就緒隊列為空,所有進程成為完成狀態。
相關數據結構:
typedef struct node{
char name[10]; //進程標識符
int prio; //進程優先級
int cput; //進程占用的CPU時間
int needt; //進程離完成還需要的CPU時間
char state; //進程狀態 struct node *next;
}PCB;
三、實驗代碼
參考實驗二中的代碼自行完成該算法代碼。
要求:
編寫算法實現的流程圖
編程實現題目要求的功能
測試多組數據的實驗結果
#include <iostream> #include <cstdio> #include <ctime> #include <cstdlib> #include <cstring> #include <bits/stdc++.h> using namespace std; //定義動態申請空間的函數 #define getpch(type) (type*)malloc(sizeof(type)) typedef struct node { int ID;//進程的標識符 int prio;//進程的優先級 int cput;//進程占用的CPU時間 int ncput;//進程離完成還需要的CPU時間 char state;//進程的狀態 R運行,W等待,在run中使用F-T。 struct node *next; }PCB; PCB *ready, *run, *finish;//准備,運行,完成。 void InitProcess();//進程的初始化設置 void insertByDesc(PCB *p);//插入節點,按照從大到小排序(優先級高的先運行) void printreadyinfo();//輸出就緒隊列的信息 void processrunning();//進程開始運行 void JoinCPU();//從進程中選取一個進程進入CPU開始運行 void showrun(PCB *p);//顯示正在運行的進程(顯示過程) void showfinish(PCB *p);//顯示完成的信息 void setfinish(PCB *p);////進程完成,設置為完成 //主函數 int main() { run = getpch(PCB);//申請節點空間 finish =getpch(PCB); ready = getpch(PCB); ready->next = NULL; run->next = NULL; finish->next = NULL; InitProcess();//初始化進程 processrunning(); return 0; } void showrun(PCB *p) { printf("進程運行的信息:\n"); cout<<"ID"<<" "<<"Prio"<<" "<<"cput"<<" "<<"ncput"<<" "<<"state"<<endl; printf("%-4d %-7d %-7d %-7d %-7c\n", p->ID, p->prio, p->cput, p->ncput, p->state); } void showfinish(PCB *p) { printf("完成的進程信息:\n"); cout<<"ID"<<" "<<"Prio"<<" "<<"cput"<<" "<<"ncput"<<" "<<"state"<<endl; printf("%-4d %-7d %-7d %-7d %-7c\n", p->ID, p->prio, p->cput, p->ncput, p->state); } //進程完成,設置為完成 void setfinish(PCB *p) { PCB *r; if (p->ncput == 0) {//如果運行所需時間為0,放入finish r = finish; while (r->next != NULL) { r = r->next; } p->state = 'F';//將當前進程置為完成狀態 p->next = r->next; r->next = p; showfinish(p);//輸出完成的信息 } } //從進程中選取一個進程進入CPU開始運行 void JoinCPU() { if (ready->next != NULL) {//如果就緒隊列不為空,第一個PCB置運行 run->next = ready->next;//開始運行 ready->next = ready->next->next;//第一個從就緒隊列刪除 run->next->state = 'R';//運行的進程狀態改為R run->next->prio -= 3;//每進入CPU一次優先級-3 run->next->cput += 1;//CPU占用的時間+1 run->next->ncput -= 1;//一共還需要的時間-1 } } void processrunning() { JoinCPU(); setfinish(run->next);//時間為零置finish if (run->next->state != 'F') showrun(run->next); while (1) { if (ready->next != NULL && run->next->prio < ready->next->prio) { //小於第一個PCB優先數就將其插入就緒並調用下一個進程 if (run->next->state != 'F')//如果進程已完成就不用插入就緒 insertByDesc(run->next);//重新進行排序 JoinCPU(); setfinish(run->next); if (run->next->state != 'F') showrun(run->next); } else { run->next->prio -= 3; run->next->cput += 1; run->next->ncput -= 1; setfinish(run->next); if (run->next->state != 'F') showrun(run->next); if (ready->next == NULL) { break; } } } } //輸出就緒隊列的信息 void printreadyinfo() { PCB *p; p = ready->next; cout<<"就緒進程的信息(ready info)"<<endl; cout<<"ID"<<" "<<"Prio"<<" "<<"cput"<<" "<<"ncput"<<" "<<"state"<<endl; while (p != NULL) { printf("%-4d %-7d %-7d %-7d %-7c\n", p->ID, p->prio, p->cput, p->ncput, p->state); p = p->next; } } //插入節點,按照從大到小排序(優先級高的先運行) void insertByDesc(PCB *p){ PCB *tmp; tmp = ready; while (tmp->next != NULL && tmp->next->prio >= p->prio) {//從大到小排序 tmp = tmp->next; } //第一個節點 p->next = tmp->next; tmp->next = p; } //進程狀態的初始化: void InitProcess() { PCB *p; int n; printf("情輸入進程的個數:"); cin>>n;//輸入了進程的個數; cout<<"請輸入進程的標識符和程占用的CPU時間"<<endl; for (int i = 1; i <= n; i++) { p = getpch(PCB); int id, pri, needt;//設置變量,進程的標識,優先級,占用CPU的時間。 cin>>id>>needt; p->ID = id; p->prio = 30;//優先級初始狀態為30 p->cput = 0;//初始化時還未占用CPU p->ncput = needt;//一共需要的CPU時間 p->state = 'w';//狀態等待。 insertByDesc(p); } printreadyinfo(); }