多級隊列調度算法
- 多級隊列:該算法將系統中的進程就緒隊列從一個拆分為若干個,將不同類型或性質的進程固定分配在不同的就緒隊列,不同的就緒隊列采用不同的調度算法,一個就緒隊列中的進程可以設置不同的優先級,不同的就緒隊列本身也可以設置不同的優先級。
多級隊列調度算法由於設置多個就緒隊列,因此對每個就緒隊列就可以實施不同的調度算法,因此,系統針對不同用戶進程的需求,很容易提供多種調度策略。
題目描述:
- 設RQ分為RQ1和RQ2
- RQ1采用輪轉法,時間片q=7.
- RQ1>RQ2
- RQ2采用短進程優先調度算法。
- 測試數據如下:
-
其中:RQ1: P1-P5, RQ2: P6-P10
進程 | P1 | P2 | P3 | P4 | P5 | P6 | P7 | P8 | P9 | P10 |
---|---|---|---|---|---|---|---|---|---|---|
運行時間 | 16 | 11 | 14 | 13 | 15 | 21 | 18 | 10 | 7 | 14 |
已等待時間 | 6 | 5 | 4 | 3 | 2 | 1 | 2 | 3 | 4 | 5 |
程序功能
- 對於給定的數據使用多級隊列調度算法進行分析計算周轉時間。其中多級隊列分為RQ1和RQ2 ,RQ1采用的是時間片長度為7的時間片輪轉算法,RQ2采用的是短進程優先算法。並且RQ1的優先級高於RQ2(即只有在RQ1內所有程序運行結束,RQ2才能開始運行)
設計思路
- 時間片輪轉:首先對RQ1按照等待時間長短排序,然后從頭設置循環,只要隊列不空就一直進行下去,每次取隊頭RQ1的下一個元素(RQ1僅用作標志,不存儲數據)判斷need是否小於等於時間片大小,小於等於則置為0后踢出隊列進入finish隊列,大於則將need減去時間片大小,然后將其移動至隊尾。
- 短進程優先:開始前需要對RQ2按照剩余執行時間大小進行排序,與時間片輪轉法類似,不同的是這里一旦開始執行就直接執行完畢,然后下一個進程上處理機運行。

數據結構
- 本程序每個進程用一個PCB表示,每個PCB內含有name(標識符)、need(當前仍然需要多長時間才能運行結束)、turn(周轉時間(等於等待時間+運行時間))、next指針(指向等待隊列的下一個進程)。兩個隊列的頭節點分別為RQ1、RQ2還有一個結束隊列Finish(運行結束后進程從原隊列進入這里)
typedef struct tag_pcb {
char name[8];
int need = 0;//需要運行的時間
int turn = 0;//周轉時間=等待時間+運行時間
struct tag_pcb* next = NULL;
}PCB;
PCB* RQ1=new PCB, * RQ2 = new PCB, * Finish = new PCB;
代碼實現:

#include<iostream>
#include <fstream>
using namespace std;
typedef struct tag_pcb {
char name[8];
int need = 0;//需要運行的時間
int turn = 0;//周轉時間=等待時間+運行時間
struct tag_pcb* next = NULL;
}PCB;
PCB* RQ1=new PCB, * RQ2 = new PCB, * Finish = new PCB;
const int TimePiece = 7;//時間片長度
void ReadFile(){
ifstream In("RQ1.txt");
PCB* Current = RQ1;
while (!In.eof()) {
PCB* Cur = new PCB;
In >> Cur->name >> Cur->need>> Cur->turn;
Current->next = Cur;
Current = Current->next;
}
In.close();
ifstream In1("RQ2.txt");
PCB* Current1 = RQ2;
while (!In1.eof()) {
PCB* Cur1 = new PCB;
In1 >> Cur1->name >> Cur1->need >> Cur1->turn;
Current1->next = Cur1;
Current1 = Current1->next;
}
In1.close();
}
void Q1_Insert(PCB a) { //時間片輪轉算法隊列的插入(插入尾部)
PCB* Current = RQ1;
while (Current->next != NULL)
Current = Current->next;
Current->next = new PCB;
*Current->next = a;
//Current->next = &a;
Current->next->next = NULL;
}
void Q2_Insert(PCB b) { //短進程優先調度算法隊列的插入
PCB* Current = RQ2;
while (Current->next != NULL)
Current = Current->next;
Current->next = new PCB;
*Current->next = b;
Current->next->next = NULL;
}
void Fin_Insert(PCB c) { //短進程優先調度算法隊列的插入
PCB* cc = new PCB;
*cc = c;
cc->next = Finish->next;
Finish->next = cc;
}
void Q2_sort(PCB *T) {
PCB* X = new PCB;//用來保存排序后的鏈表
PCB* p = new PCB;//用來保存當此最小值的前一位
PCB* Current = T->next;
PCB * PreCurrent = T;
PCB* TailX = X;
while (T->next != NULL) {
int tem = 999999;
Current = T->next;
PreCurrent = T;
while (Current != NULL) {
if (Current->need < tem) {
tem = Current->need;
p = PreCurrent;
//cout << "處理" << p->name << p->need << "\n";
}
Current = Current->next;
PreCurrent = PreCurrent->next;
}
TailX->next = p->next;
TailX = TailX->next;
if (p->next->next != NULL)
p->next = p->next->next;
else
p->next = NULL;
}
*T = *X;
}
int main()
{
ReadFile();
int clock = 0; //時鍾
while (RQ1->next != NULL) {//表示RQ1還有元素
int t = TimePiece;
PCB* Current = RQ1->next;
int fin = 0;
if (Current->need <= t)
t = Current->need, fin = 1;
clock += t;//表示pi運行t
//輸出計算過程
//cout << "\n" << Current->name << "_____" << Current->turn << "__+ ___" << clock << "__= ___" << Current->turn +clock << "\n";
Current->need -= t;
if (fin)
Current->turn += clock, Fin_Insert(*Current);//運行結束
else
Q1_Insert(*Current);//進入隊尾等待運行
if (Current->next == NULL)
break;
RQ1->next = Current->next;
}
clock = 0;//時鍾要清空一次
Q2_sort(RQ2);//先排序
cout << "RQ2:__";
for (PCB* Current2 = RQ2->next; Current2 != NULL; Current2 = Current2->next)
cout << Current2->name << "--";
while (RQ2->next != NULL) {//表示RQ2還有元素(到這一步默認RQ1已經為空)
PCB* Current3 = RQ2->next;
int t = Current3->need;
clock += t;//表示pi運行t
Current3->need -= t;//實質為清空
Current3->turn += clock;
Fin_Insert(*Current3);
if (Current3->next == NULL)
break;
RQ2->next = Current3->next;
}
int SUM = 0;
for (PCB* Current2 = Finish->next; Current2 != NULL; Current2 = Current2->next) {
cout << "\n" << Current2->name <<"\t"<< Current2->turn ;
SUM += Current2->turn;
}
cout << "\n總周轉時間為:" << SUM << "\n";
}
- 多級隊列調度測試結果:
附:
多級反饋隊列調度算法如下原理:
- 1、設有N個隊列(Q1,Q2…QN),其中各個隊列對於處理機的優先級是不一樣的,也就是說位於各個隊列中的作業(進程)的優先級也是不一樣的。一般來說,優先級Priority(Q1) > Priority(Q2) > … > Priority(QN)。怎么講,位於Q1中的任何一個作業(進程)都要比Q2中的任何一個作業(進程)相對於CPU的優先級要高(也就是說,Q1中的作業一定要比Q2中的作業先被處理機調度),依次類推其它的隊列。
- 2、對於優先級最低的隊列來說,里面是遵循時間片輪轉法。也就是說,位於隊列QN中有M個作業,它們的運行時間是通過QN這個隊列所設定的時間片來確定的;對於其他隊列,遵循的是先來先服務算法,每一進程分配一定的時間片,若時間片運行完時進程未結束,則進入下一優先級隊列的末尾。
- 3、各個隊列的時間片是一樣的嗎?
不一樣,這就是該算法設計的精妙之處。各個隊列的時間片是隨着優先級的增加而減少的,也就是說,優先級越高的隊列中它的時間片就越短。同時,為了便於那些超大作業的完成,最后一個隊列QN(優先級最低的隊列)的時間片一般很大(不需要考慮這個問題)。
上述程序在某一進程在一級隊列運行一輪后沒有運行完畢,若加入二級隊列而不是加入原隊列的尾部,則可以實現簡單的多級反饋隊列調度算法
兩種算法的不同之處就在於:當一個RQ1中的進程在時間片結束之后是回到當前的隊尾還是到RQ2隊列之中。
在上述程序中也很容易實現:
if (fin)
Current->turn += clock, Fin_Insert(*Current);//運行結束
else
Q1_Insert(*Current);//進入隊尾等待運行
修改為:
if (fin)
Fin_Insert(*Current);//運行結束
else
Q2_Insert(*Current);//進入二級隊列等待運行
Current->turn += clock,
上述兩種代碼分別實現了上述兩種功能,執行時只需選一種在相應位置即可。
- 多級反饋隊列調度測試結果:
由分析上述數據容易發現:在該測試數據的情況下多級反饋隊列調度算法是要優於多級隊列調度的