實驗三時間片輪轉算法和優先級調度算法模擬實現
一、 實驗任務
1. 設計進程控制塊PCB的結構,通常應包括如下信息:
進程名、進程優先數(或輪轉時間片數)、進程已占用的CPU時間、進程到完成還需要的時間、進程的狀態、當前隊列指針等。
2.編寫兩種調度算法程序:
優先級調度算法
時間片輪轉調度算法
3. 按要求輸出結果。
二、實驗目的
1. 加深理解有關進程控制塊、進程隊列等概念。
2. 體會和了解優先級調度算法和時間片輪轉算法的具體實施辦法。
三、實驗環境
1. 一台運行Windows 7操作系統的計算機。
2. 選用以C、C++、visual c++、Java等任何一種語言。
四、實驗要求
1. 在程序編制中,應有數據顯示,最好采用圖形界面顯示。
2. 用戶可以選擇哪種方式進行調度,有優先級調度算法和時間片輪轉法兩種,但在開始調度前要創建好進程,在創建的過程中,如選擇的是優先算法,則按優先級插到隊列后面,若是一般的輪轉法則直接插到就緒隊列后面即可;完成對進程的創建后就調用相應的調度算法進行調度。
3. 實驗課時:4課時。
五、實驗准備知識
分別用兩種調度算法對多個進程進行調度。每個進程可有三種狀態;執行狀態(run)、就緒狀態(ready,包括等待狀態)和完成狀態(finish),並假定初始狀態為就緒狀態。
(一)進程控制塊結構如下:
name——進程標示符
prio/round——進程優先數/進程每次輪轉的時間片數(設為常數2)
cputime——進程累計占用CPU的時間片數
needtime——進程到完成還需要的時間片數
state——進程狀態
next——鏈指針
注:
1.為了便於處理,程序中進程的運行時間以時間片為單位進行計算;
2.各進程的優先數或輪轉時間片數,以及進程運行時間片數的初值,均由用戶在程序運行時給定。
(二)進程的就緒態和等待態均為鏈表結構,共有四個指針如下:
run——當前運行進程指針
ready——就緒隊列頭指針
tail——就緒隊列尾指針
finish——完成隊列頭指針
(三)程序說明
1. 在優先級調度算法中,進程優先數的初值設為: 50-needtime
每執行一次,優先數減1,CPU時間片數加1,進程還需要的時間片數減1。
在時間片輪轉法中,采用固定時間片單位(兩個時間片為一個單位),進程每輪轉一次,CPU時間片數加2,進程還需要的時間片數減2,並退出CPU,排到就緒隊列尾,等待下一次調度。
2. 程序的模塊結構提示如下:
整個程序可由主程序和如下7個過程組成:
(1)insert1——在優先級調度算法中,將尚未完成的PCB按優先數順序插入到就緒隊列中;
(2)insert2——在時間片輪轉法中,將執行了一個時間片單位(為2),但尚未完成的進程的PCB,插到就緒隊列的隊尾;
(3)firstin——調度就緒隊列的第一個進程投入運行;
(4)prt/prt1/prt2——顯示每執行一次后所有進程的狀態及有關信息。
(5)create1/create2——創建新進程,並將它的PCB插入就緒隊列;
(6)priority——按優先級調度算法調度進程;
(7)roundrun——按時間片輪轉法調度進程。
主程序定義PCB結構和其他有關變量。
(四)運行和顯示
程序開始運行后,首先提示:請用戶選擇算法,輸入進程名和相應的needtime值。
每次顯示結果均為如下5個字段:
name cputime needtime priority state
注:
1.在state字段中,"R"代表執行態,"W"代表就緒(等待)態,"F"代表完成態。
2.應先顯示"R"態的,再顯示"W"態的,再顯示"F"態的。
3.在"W"態中,以優先數高低或輪轉順序排隊;在"F"態中,以完成先后順序排隊。
六、程序源代碼及注釋
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct node { char name[10]; /*進程標識符*/
int prio; /*進程優先數*/
int round; /*進程時間輪轉時間片*/
int cputime; /*進程占用CPU時間*/
int needtime; /*進程到完成還要的時間*/
int count; /*計數器*/
char state; /*進程的狀態*/
struct node *next; /*鏈指針*/ }PCB; PCB *finish,*ready,*tail,*run; /*隊列指針*/
int N; /*進程數*/
/*將就緒隊列中的第一個進程投入運行*/ firstin() { run=ready; /*就緒隊列頭指針賦值給運行頭指針*/ run->state='R'; /*進程狀態變為運行態*/ ready=ready->next; /*就緒對列頭指針后移到下一進程*/ } void prt1(char a) { if(toupper(a)=='P') /*優先級調度算法*/ printf(" name cputime needtime priority state\n"); else printf(" name cputime needtime count round state\n"); } /*進程PCB輸出*/
void prt2(char a,PCB *q) { if(toupper(a)=='P') /*優先級調度算法的輸出*/ printf(" %-10s%-10d%-10d%-10d %c\n",q->name, q->cputime,q->needtime,q->prio,q->state); else/*時間片輪轉算法的輸出*/ printf(" %-10s%-10d%-10d%-10d%-10d %-c\n",q->name, q->cputime,q->needtime,q->count,q->round,q->state); } /*輸出函數*/
void prt(char algo) { PCB *p; prt1(algo); /*輸出標題*/
if(run!=NULL) /*如果運行指針不空*/ prt2(algo,run); /*輸出當前正在運行的PCB*/ p=ready; /*輸出就緒隊列PCB*/
while(p!=NULL) { prt2(algo,p); p=p->next; } p=finish; /*輸出完成隊列的PCB*/
while(p!=NULL) { prt2(algo,p); p=p->next; } getchar(); /*壓任意鍵繼續*/ } /*優先數的插入算法*/ insert1(PCB *q) { PCB *p1,*s,*r; int b; s=q; /*待插入的PCB指針*/ p1=ready; /*就緒隊列頭指針*/ r=p1; /*r做p1的前驅指針*/ b=1; while((p1!=NULL)&&b) /*根據優先數確定插入位置*/
if(p1->prio>=s->prio) { r=p1; p1=p1->next; } else b=0; if(r!=p1) /*如果條件成立說明插入在r與p1之間*/ { r->next=s; s->next=p1; } else { s->next=p1; /*否則插入在就緒隊列的頭*/ ready=s; } } /*輪轉法插入函數*/ insert2(PCB *p2) { tail->next=p2; /*將新的PCB插入在當前就緒隊列的尾*/ tail=p2; p2->next=NULL; } /*優先數創建初始PCB信息*/
void create1(char alg) { PCB *p; int i,time; char na[10]; ready=NULL; /*就緒隊列頭指針*/ finish=NULL; /*完成隊列頭指針*/ run=NULL; /*運行隊列指針*/ printf("輸入進程名稱和運行時間\n"); /*輸入進程標識和所需時間創建PCB*/
for(i=1;i<=N;i++ ) { p=malloc(sizeof(PCB)); scanf("%s",na); scanf("%d",&time); strcpy(p->name,na); p->cputime=0; p->needtime=time; p->state='w'; p->prio=50-time; if(ready!=NULL) /*就緒隊列不空調用插入函數插入*/ insert1(p); else { p->next=ready; /*創建就緒隊列的第一個PCB*/ ready=p; } } //clrscr();
printf(" 優先算法的輸出:\n"); printf("************************************************\n"); prt(alg); /*輸出進程PCB信息*/ run=ready; /*將就緒隊列的第一個進程投入運行*/ ready=ready->next; run->state='R'; } /*輪轉法創建進程PCB*/
void create2(char alg) { PCB *p; int i,time; char na[10]; ready=NULL; finish=NULL; run=NULL; printf("輸入進程的名稱和運行時間:\n"); for(i=1;i<=N;i++) { p=malloc(sizeof(PCB)); scanf("%s",na); scanf("%d",&time); strcpy(p->name,na); p->cputime=0; p->needtime=time; p->count=0; /*計數器*/ p->state='w'; p->round=2; /*時間片*/
if(ready!=NULL) insert2(p); else { p->next=ready; ready=p; tail=p; } } //clrscr();
printf(" 簡單時間片輪轉輸出 \n"); printf("************************************************\n"); prt(alg); /*輸出進程PCB信息*/ run=ready; /*將就緒隊列的第一個進程投入運行*/ ready=ready->next; run->state='R'; } /*優先級調度算法*/ priority(char alg) { while(run!=NULL) /*當運行隊列不空時,有進程正在運行*/ { run->cputime=run->cputime+1; run->needtime=run->needtime-1; run->prio=run->prio-2; /*每運行一次優先數降低2個單位*/
if(run->needtime==0) /*如所需時間為0將其插入完成隊列*/ { run->next=finish; finish=run; run->state='F'; /*置狀態為完成態*/ run=NULL; /*運行隊列頭指針為空*/
if(ready!=NULL) /*如就緒隊列不空*/ firstin(); /*將就緒隊列的第一個進程投入運行*/ } else /*沒有運行完同時優先數不是最大,則將其變為就緒態插入到就緒隊列*/
if((ready!=NULL)&&(run->prio<ready->prio)) { run->state='W'; insert1(run); firstin(); /*將就緒隊列的第一個進程投入運行*/ } prt(alg); /*輸出進程PCB信息*/ } } /*時間片輪轉法*/ roundrun(char alg) { while(run!=NULL) { run->cputime=run->cputime+1; run->needtime=run->needtime-1; run->count=run->count+1; if(run->needtime==0)/*運行完將其變為完成態,插入完成隊列*/ { run->next=finish; finish=run; run->state='F'; run=NULL; if(ready!=NULL) firstin(); /*就緒隊列不空,將第一個進程投入運行*/ } else
if(run->count==run->round) /*如果時間片到*/ { run->count=0; /*計數器置0*/
if(ready!=NULL) /*如就緒隊列不空*/ { run->state='W'; /*將進程插入到就緒隊列中等待輪轉*/ insert2(run); firstin(); /*將就緒隊列的第一個進程投入運行*/ } } prt(alg); /*輸出進程信息*/ } } /*主函數*/ main() { char flag; /*算法標記*/ printf("選擇算法類型:P/R(優先算法/輪轉法)\n"); scanf("%c",&flag); /*輸入字符確定算法*/ printf("輸入進程個數:\n"); scanf("%d",&N); /*輸入進程數*/
if(flag=='P'||flag=='p') { create1(flag); /*優先級調度算法*/ priority(flag); } else
if(flag=='R'||flag=='r') { create2(flag); /*時間片輪轉法*/ roundrun(flag); } }
