多級反饋隊列調度算法


 

 

 

實 驗 報 告(拓展實驗1)

多級反饋隊列調度算法

 

 

課程名稱 操作系統實驗

學生學院 計算機學院

專業班級 17網絡工程一班

學 號 31170050**

學生姓名 陳鴻

指導教師 林穗

 

 

 

 

 

2019 12 6

 

目錄

一、    實驗目的    3

二、實驗內容    3

多級反饋隊列調度算法的概念:    3

應用范圍:    3

三、實現思路    4

四、主要的數據結構    4

void Output(); /*進程信息輸出函數*/    5

void InsertFinish(PCB *in); /*將進程插入到完成隊列尾部*/    5

void InsertPrio(ReadyQueue *in); /*創建就緒隊列,規定優先數越小,優先級越低*/    5

void PrioCreate(); /*創建就緒隊列輸入函數*/    5

void GetFirst(ReadyQueue *queue); /*取得某一個就緒隊列中的隊頭進程*/    5

void InsertLast(PCB *in,ReadyQueue *queue); /*將進程插入到就緒隊列尾部*/    5

void ProcessCreate(); /*進程創建函數*/    5

void RoundRun(ReadyQueue *timechip); /*時間片輪轉調度算法*/    5

void MultiDispatch(); /*多級調度算法,每次執行一個時間片*/    5

int main(void)    6

五、算法流程圖    12

六、運行與測試    12

用例描述:    12

運行截圖:    13

七、總結    13

 

 

 

 

 

 

 

 

 

 

Tips:建議打開word【導航視圖】與【批注】閱讀。

 

拓展實驗1:多級反饋隊列調度算法

  1. 實驗目的

分析操作系統的核心功能模塊,理解相關功能模塊實現的數據結構和算法,並加以實現,加深對操作系統原理和實現過程的理解。本次實驗: 分析並實現多級反饋隊列調度算法的模擬。

 

二、實驗內容

多級反饋隊列調度算法的概念:

是一種根據先來先服務原則給就緒隊列排序,為就緒隊列賦予不同的優先級數,不同的時間片,按照優先級搶占CPU的調度算法。算法的實施過程如下:

 

(1)按照先來先服務原則排序,設置N個就緒隊列為Q1,Q2...QN,每個隊列中都可以放很多作業;

(2)為這N個就緒隊列賦予不同的優先級,第一個隊列的優先級最高,第二個隊列次之,其余各隊列的優先權逐個降低;

(3)設置每個就緒隊列的時間片,優先權越高,算法賦予隊列的時間片越小。時間片大小的設定按照實際作業(進程)的需要調整;

(4)進程在進入待調度的隊列等待時,首先進入優先級最高的Q1等待。

(5)首先調度優先級高的隊列中的進程。若高優先級中隊列中已沒有調度的進程,則調度次優先級隊列中的進程。例如:Q1,Q2,Q3三個隊列,只有在Q1中沒有進程等待時才去調度Q2,同理,只有Q1,Q2都為空時才會去調度Q3。

(6)對於同一個隊列中的各個進程,按照時間片輪轉法調度。比如Q1隊列的時間片為N,那么Q1中的作業在經歷了時間片為N的時間后,若還沒有完成,則進入Q2隊列等待,若Q2的時間片用完后作業還不能完成,一直進入下一級隊列,直至完成。

(7)在低優先級的隊列中的進程在運行時,又有新到達的作業,那么在運行完這個時間片后,CPU馬上分配給新到達的作業即搶占式調度CPU。

 

應用范圍:

此算法應用於同一個資源的多個使用者可分優先級使用資源的情況。

三、實現思路

1、設置多個就緒隊列,並給隊列賦予不同的優先級數,第一個最高,依次遞減。

 

2、賦予各個隊列中進程執行時間片的大小,優先級越高的隊列,時間片越小。

 

3、當一個新進程進入內存后,首先將其放入一個對列末尾,如果在一個時間片

結束時尚未完成,將其轉入第二隊列末尾。

 

4、當一個進程從一個對列移至第n個隊列后,便在第n個隊列中采用時間片輪轉執行完。

 

5、僅當時間片空閑時,才調度第二個隊列中的進程。

(1~i-1)空閑時,才調度i,如果處理機正在第i隊列中運行,又有新進程進入優先權較高

隊列,則新進程搶占處理機,將正在運行的進程放入第i隊列隊尾,將處理機分給新進程。

 

四、主要的數據結構

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

typedef struct node /*進程節點信息*/

{

char name[20]; /*進程的名字*/

int prio; /*進程的優先級*/

int round; /*分配CPU的時間片*/

int cputime; /*CPU執行時間*/

int needtime; /*進程執行所需要的時間*/

char state; /*進程的狀態,W--就緒態,R--執行態,F--完成態*/

int count; /*記錄執行的次數*/

struct node *next; /*鏈表指針*/

}PCB;

typedef struct Queue /*多級就緒隊列節點信息*/

{

PCB *LinkPCB; /*就緒隊列中的進程隊列指針*/

int prio; /*本就緒隊列的優先級*/

int round; /*本就緒隊列所分配的時間片*/

struct Queue *next; /*指向下一個就緒隊列的鏈表指針*/

}ReadyQueue;

PCB *run=NULL,*finish=NULL; /*定義三個隊列,就緒隊列,執行隊列和完成隊列*/

ReadyQueue *Head = NULL; /*定義第一個就緒隊列*/

int num; /*進程個數*/

int ReadyNum; /*就緒隊列個數*/

 

void Output(); /*進程信息輸出函數*/

void InsertFinish(PCB *in); /*將進程插入到完成隊列尾部*/

void InsertPrio(ReadyQueue *in); /*創建就緒隊列,規定優先數越小,優先級越低*/

void PrioCreate(); /*創建就緒隊列輸入函數*/

void GetFirst(ReadyQueue *queue); /*取得某一個就緒隊列中的隊頭進程*/

void InsertLast(PCB *in,ReadyQueue *queue); /*將進程插入到就緒隊列尾部*/

void ProcessCreate(); /*進程創建函數*/

void RoundRun(ReadyQueue *timechip); /*時間片輪轉調度算法*/

void MultiDispatch(); /*多級調度算法,每次執行一個時間片*/

 

 

int main(void)

{

PrioCreate(); /*創建就緒隊列*/

ProcessCreate();/*創建就緒進程隊列*/

MultiDispatch();/*算法開始*/

Output(); /*輸出最終的調度序列*/

return 0;

}

void Output() /*進程信息輸出函數*/

{

ReadyQueue *print = Head;

PCB *p;

printf("進程名\t優先級\t輪數\tcpu時間\t需要時間\t進程狀態\t計數器\n");

while(print)

{

if(print ->LinkPCB != NULL)

{

p=print ->LinkPCB;

while(p)

{

printf("%s\t%d\t%d\t%d\t%d\t\t%c\t\t%d\n",p->name,p->prio,p->round,p->cputime,p->needtime,p->state,p->count);

p = p->next;

                 }

         }

print = print->next;

     }

p = finish;

while(p!=NULL)

{

printf("%s\t%d\t%d\t%d\t%d\t\t%c\t\t%d\n",p->name,p->prio,p->round,p->cputime,p->needtime,p->state,p->count);

p = p->next;

}

p = run;

while(p!=NULL)

{

printf("%s\t%d\t%d\t%d\t%d\t\t%c\t\t%d\n",p->name,p->prio,p->round,p->cputime,p->needtime,p->state,p->count);

p = p->next;

}

}

void InsertFinish(PCB *in) /*將進程插入到完成隊列尾部*/ {

PCB *fst;

fst = finish;

if(finish == NULL)

{

in->next = finish;

finish = in;

}

else

{

while(fst->next != NULL)

{

fst = fst->next;

         }

in ->next = fst ->next;

fst ->next = in;

}

}

void InsertPrio(ReadyQueue *in) /*創建就緒隊列,規定優先數越小,優先級越低*/

{

ReadyQueue *fst,*nxt;

fst = nxt = Head;

if(Head == NULL) /*如果沒有隊列,則為第一個元素*/

{

in->next = Head;

Head = in;

}

else /*查到合適的位置進行插入*/

{

if(in ->prio >= fst ->prio) /*比第一個還要大,則插入到隊頭*/

{

in->next = Head;

Head = in;

}

else

{

while(fst->next != NULL) /*移動指針查找第一個別它小的元素的位置進行插入*/

{

nxt = fst;

fst = fst->next;

                 }

if(fst ->next == NULL) /*已經搜索到隊尾,則其優先級數最小,將其插入到隊尾即可*/

{

in ->next = fst ->next;

fst ->next = in;

}

else /*插入到隊列中*/

{

nxt = in;

in ->next = fst;

}

}

}

}

void PrioCreate() /*創建就緒隊列輸入函數*/

{

ReadyQueue *tmp;

int i;

printf("輸入就緒隊列的個數:\n");

scanf("%d",&ReadyNum);

 

printf("輸入每個就緒隊列的CPU時間片:\n");

for(i = 0;i < ReadyNum; i++)

{

if((tmp = (ReadyQueue *)malloc(sizeof(ReadyQueue)))==NULL)

{

perror("malloc");

exit(1);

}

scanf("%d",&(tmp->round)); /*輸入此就緒隊列中給每個進程所分配的CPU時間片*/

tmp ->prio = 50 - tmp->round; /*設置其優先級,時間片越高,其優先級越低*/

tmp ->LinkPCB = NULL; /*初始化其連接的進程隊列為空*/

tmp ->next = NULL;

InsertPrio(tmp); /*按照優先級從高到低,建立多個就緒隊列*/

}

}

void GetFirst(ReadyQueue *queue) /*取得某一個就緒隊列中的隊頭進程*/

{

run = queue ->LinkPCB;

if(queue ->LinkPCB != NULL)

{

run ->state = 'R';

queue ->LinkPCB = queue ->LinkPCB ->next;

run ->next = NULL;

}

}

void InsertLast(PCB *in,ReadyQueue *queue) /*將進程插入到就緒隊列尾部*/

{

PCB *fst;

fst = queue->LinkPCB;

if( queue->LinkPCB == NULL)

{

in->next = queue->LinkPCB;

queue->LinkPCB = in;

}

else

{

while(fst->next != NULL)

{

fst = fst->next;

}

in ->next = fst ->next;

fst ->next = in;

}

}

void ProcessCreate() /*進程創建函數*/

{

PCB *tmp;

int i;

 

printf("輸入進程的個數:\n");

scanf("%d",&num);

printf("輸入進程名字和進程所需時間:\n");

for(i = 0;i < num; i++)

{

if((tmp = (PCB *)malloc(sizeof(PCB)))==NULL)

{

perror("malloc");

exit(1);

}

scanf("%s",tmp->name);

getchar(); /*吸收回車符號*/

scanf("%d",&(tmp->needtime));

tmp ->cputime = 0;

tmp ->state ='W';

tmp ->prio = 50 - tmp->needtime; /*設置其優先級,需要的時間越多,優先級越低*/

tmp ->round = Head ->round;

tmp ->count = 0;

InsertLast(tmp,Head); /*按照優先級從高到低,插入到就緒隊列*/

}

}

void RoundRun(ReadyQueue *timechip) /*時間片輪轉調度算法*/

{

int flag = 1;

GetFirst(timechip);

while(run != NULL)

{

while(flag)

{

run->count++;

run->cputime++;

run->needtime--;

if(run->needtime == 0) /*進程執行完畢*/

{

run ->state = 'F';

InsertFinish(run);

flag = 0;

}

else if(run->count == timechip ->round)/*時間片用完*/

{

run->state = 'W';

run->count = 0; /*計數器清零,為下次做准備*/

InsertLast(run,timechip);

flag = 0;

}

}

flag = 1;

GetFirst(timechip);

}

}

void MultiDispatch() /*多級調度算法,每次執行一個時間片*/

{

int flag = 1;

int k = 0;

ReadyQueue *point;

point = Head;

GetFirst(point);

while(run != NULL)

{

Output();

if(Head ->LinkPCB!=NULL)

point = Head;

while(flag) {

run->count++;

run->cputime++;

run->needtime--;

if(run->needtime == 0) /*進程執行完畢*/

{

run ->state = 'F';

InsertFinish(run);

flag = 0;

}

else if(run->count == run->round)/*時間片用完*/

{

run->state = 'W';

run->count = 0; /*計數器清零,為下次做准備*/

if(point ->next!=NULL)

{

run ->round = point->next ->round;/*設置其時間片是下一個就緒隊列的時間片*/

InsertLast(run,point->next); /*將進程插入到下一個就緒隊列中*/

flag = 0;

}

else {

RoundRun(point); /*如果為最后一個就緒隊列就調用時間片輪轉算法*/

break;

}

}

++k;

if(k == 3) {

ProcessCreate();

}

}

flag = 1;

if(point ->LinkPCB == NULL)/*就緒隊列指針下移*/

point =point->next;

if(point ->next ==NULL)

{

RoundRun(point);

break;

}

GetFirst(point);

}

}

五、算法流程圖

六、運行與測試

用例描述:

 

假設系統中有3個就緒隊列Q1,Q2,Q3,時間片分別為2,4,8

現在有3個作業J1,J2,J3它們所需要的CPU時間分別是3,2,1個時間片

 

1、時刻0: J1到達。於是進入到隊列1 , 運行1個時間片 , 時間片還未到,此時J2到達。

2、時刻1: J2到達。 由於時間片仍然由J1掌控,於是等待。 J1在運行了1個時間片后,已經完成了在Q1中的2個時間片的限制,於是J1置於Q2等待被調度。現在處理機分配給J2。

3、時刻2: J1進入Q2等待調度,J2獲得CPU開始運行。

4、時刻3:J3到達,由於J2的時間片未到,故J3在Q1等待調度,J1也在Q2等待調度。

5、時刻4:J2處理完成,由於J3,J1都在等待調度,但是J3所在的隊列比J1所在的隊列的優先級要高,於是J3被調度,J1繼續在Q2等待。

6、時刻5:J3經過1個時間片,完成。

7、時刻6:由於Q1已經空閑,於是開始調度Q2中的作業,則J1得到處理器開始運行。

8、時刻7:J1再經過一個時間片,完成了任務。於是整個調度過程結束。

 

 

 

 

運行截圖:

七、總結

 

多級反饋隊列調度算法體現了計算思維的調度特點,應用了先來先服務原則、應用時間片等做法使得每個申請者都能及時使用資源,是一種很好的協調整體的解決方案。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM