多級反饋佇列排程演算法(MFQ)
多級反饋佇列排程演算法是目前公認的較好的一種程式排程演算法,它能較好的滿足各類程式的需要。
MFQ演算法首先設定多個就緒佇列。佇列的優先順序遞減,且各佇列時間片大小也不同。例如我實現的演算法裡,設定了3個佇列,第一佇列優先順序>第二佇列>第三佇列,且後一個佇列的時間片大小是前一個的2倍。
每個佇列都採用FCFS策略排列。首先排程高優先順序佇列內的程式,如果此程式在時間片內不能執行完,則將它加入下一個佇列。這樣到了最後一個佇列,就成了RR演算法。
如果有高優先順序的程式到達,則放棄正在排程的程式,轉向排程最高優先順序的程式。這裡我的實現不是很完美,我的演算法裡當高優先順序程式到達時,如果有程式正在執行,則需要等到這個程式時間片結束才能轉到高優先順序程式。需要進一步修改,今晚困了,改不動了
//main.cpp
#include "MFQ.h"
int main()
{
std::vector<PCB> PCBList;
int timeslice;
//輸入時間片大小,作業資訊
InputPCB(PCBList, timeslice);
//MFQ演算法
MFQ(PCBList, timeslice);
//顯示結果
show(PCBList);
return 0;
}
//MFQ.h
#ifndef MFQ_H_
#define MFQ_H_
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <vector>
#include <queue>
//作業結構體
typedef struct PCB
{
int ID; //識別符號
int ComeTime; //到達時間
int ServerTime; //服務時間
int FinishTime; //完成時間
int TurnoverTime; //週轉時間
double WeightedTurnoverTime; //帶權週轉時間
}PCB;
/*
函式功能:輸入作業資訊
引數說明:
PCBList std::vector<PCB>& PCB鏈
timeslice int 第一佇列時間片
*/
void InputPCB(std::vector<PCB> &PCBList, int ×lice);
/*
函式功能:MFQ演算法
引數說明:
PCBList std::vector<PCB>& PCB鏈
timeslice int 第一佇列時間片
*/
void MFQ(std::vector<PCB> &PCBList, int timeslice);
/*
函式功能:顯示結果
引數說明:
PCBList std::vector<PCB>& PCB鏈
*/
void show(std::vector<PCB> &PCBList);
/*
函式功能:比較函式,用於sort(),按ComeTime升序排列
引數說明:
p1 const PCB& PCB
p2 const PCB& PCB
*/
bool CmpByComeTime(const PCB &p1, const PCB &p2);
#endif
//MFQ.cpp
#include "MFQ.h"
//輸入作業資訊
void InputPCB(std::vector<PCB> &PCBList, int ×lice)
{
std::cout << "輸入第一佇列時間片大小: ";
std::cin >> timeslice;
do {
PCB temp;
std::cout << "輸入識別符號: ";
std::cin >> temp.ID;
std::cout << "輸入到達時間: ";
std::cin >> temp.ComeTime;
std::cout << "輸入服務時間: ";
std::cin >> temp.ServerTime;
temp.FinishTime = 0; //暫時存放執行了多少時間,來判斷此作業是否執行結束
PCBList.push_back(temp);
std::cout << "繼續輸入?Y/N: ";
char ans;
std::cin >> ans;
if ('Y' == ans || 'y' == ans)
continue;
else
break;
} while (true);
}
//MFQ演算法
void MFQ(std::vector<PCB> &PCBList, int timeslice)
{
std::sort(PCBList.begin(), PCBList.end(), CmpByComeTime); //按到達時間排序
std::vector<PCB> result; //儲存結果
int BeginTime = (*PCBList.begin()).ComeTime; //第一個作業開始時間
const int QueueNum = 3;
std::queue<PCB> Ready[QueueNum]; //設定3個就緒佇列
Ready[0].push(*PCBList.begin());
PCBList.erase(PCBList.begin());
while (!PCBList.empty())
{
//這段是為了防止前面的程式執行完了,後面的程式還沒到,造成死迴圈
bool flag = false;
for (int i = 0; i < QueueNum; ++i)
{
if (!Ready[i].empty())
{
flag = true;
break;
}
}
if(!flag)
{
Ready[0].push(*PCBList.begin());
PCBList.erase(PCBList.begin());
BeginTime = Ready[0].front().ComeTime;
}
for (int i = 0; i < QueueNum; ++i)
{
int times = timeslice * (i + 1); //下一個佇列的時間片大小是上一個的2倍
if (i != QueueNum - 1) //不是最後一個佇列
{
while (!Ready[i].empty()) //佇列不空
{
if (!PCBList.empty() && BeginTime >= (*PCBList.begin()).ComeTime) //有新作業到達,加入就緒佇列,轉到第一佇列
{
Ready[0].push(*PCBList.begin());
PCBList.erase(PCBList.begin());
i = 0;
continue;
}
if (Ready[i].front().FinishTime + times < Ready[i].front().ServerTime) //時間片用完沒執行完,加入下一佇列隊尾
{
Ready[i].front().FinishTime += times;
Ready[i + 1].push(Ready[i].front());
Ready[i].pop();
BeginTime += times;
}
else //此作業執行完
{
BeginTime += Ready[i].front().ServerTime - Ready[i].front().FinishTime;
Ready[i].front().FinishTime = BeginTime;
Ready[i].front().TurnoverTime = Ready[i].front().FinishTime - Ready[i].front().ComeTime;
Ready[i].front().WeightedTurnoverTime = (double)Ready[i].front().TurnoverTime / Ready[i].front().ServerTime;
//從就緒佇列中移除作業
result.push_back(Ready[i].front());
Ready[i].pop();
}
}
}
else
{
while (!Ready[i].empty())
{
if (!PCBList.empty() && BeginTime >= (*PCBList.begin()).ComeTime) //有新作業到達,加入就緒佇列,轉到第一佇列
{
Ready[0].push(*PCBList.begin());
PCBList.erase(PCBList.begin());
i = -1;
break;
}
if (Ready[i].front().FinishTime + times < Ready[i].front().ServerTime) //時間片用完沒執行完,加入隊尾
{
Ready[i].front().FinishTime += times;
Ready[i].push(Ready[i].front());
Ready[i].pop();
BeginTime += times;
}
else //此作業執行完
{
BeginTime += Ready[i].front().ServerTime - Ready[i].front().FinishTime;
Ready[i].front().FinishTime = BeginTime;
Ready[i].front().TurnoverTime = Ready[i].front().FinishTime - Ready[i].front().ComeTime;
Ready[i].front().WeightedTurnoverTime = (double)Ready[i].front().TurnoverTime / Ready[i].front().ServerTime;
//從就緒佇列中移除作業
result.push_back(Ready[i].front());
Ready[i].pop();
}
}
}
}
}
//按ComeTime升序排序,便於顯示結果
PCBList = result;
std::sort(PCBList.begin(), PCBList.end(), CmpByComeTime);
}
//顯示結果
void show(std::vector<PCB> &PCBList)
{
int SumTurnoverTime = 0;
double SumWeightedTurnoverTime = 0;
std::cout.setf(std::ios::left);
std::cout.precision(2);
std::cout << std::setw(20) << "識別符號";
for (std::vector<PCB>::iterator it = PCBList.begin(); it < PCBList.end(); ++it)
std::cout << std::setw(5) << (*it).ID;
std::cout << std::endl;
std::cout << std::setw(20) << "到達時間";
for (std::vector<PCB>::iterator it = PCBList.begin(); it < PCBList.end(); ++it)
std::cout << std::setw(5) << (*it).ComeTime;
std::cout << std::endl;
std::cout << std::setw(20) << "服務時間";
for (std::vector<PCB>::iterator it = PCBList.begin(); it < PCBList.end(); ++it)
std::cout << std::setw(5) << (*it).ServerTime;
std::cout << std::endl;
std::cout << std::setw(20) << "完成時間";
for (std::vector<PCB>::iterator it = PCBList.begin(); it < PCBList.end(); ++it)
std::cout << std::setw(5) << (*it).FinishTime;
std::cout << std::endl;
std::cout << std::setw(20) << "週轉時間";
for (std::vector<PCB>::iterator it = PCBList.begin(); it < PCBList.end(); ++it)
{
std::cout << std::setw(5) << (*it).TurnoverTime;
SumTurnoverTime += (*it).TurnoverTime;;
}
std::cout << std::endl;
std::cout << std::setw(20) << "帶權週轉時間";
for (std::vector<PCB>::iterator it = PCBList.begin(); it < PCBList.end(); ++it)
{
std::cout << std::setw(5) << (*it).WeightedTurnoverTime;
SumWeightedTurnoverTime += (*it).WeightedTurnoverTime;;
}
std::cout << std::endl;
std::cout << "平均週轉時間: " << (double)SumTurnoverTime / PCBList.size() << std::endl;
std::cout << "平均帶權週轉時間: " << SumWeightedTurnoverTime / PCBList.size() << std::endl;
}
//比較函式,按ComeTime升序排列
bool CmpByComeTime(const PCB &p1, const PCB &p2)
{
return p1.ComeTime < p2.ComeTime;
}
相關文章
- 2.2.5排程演算法:時間片輪轉、優先順序排程、多級反饋排程演算法
- ModStart排程和佇列佇列
- 程式排程演算法Linux程式排程演算法演算法Linux
- golang實現併發爬蟲三(用佇列排程器實現)Golang爬蟲佇列
- [BUG反饋]升級後獨立模型出錯模型
- 反饋工具BIC
- 三、資料結構演算法-棧、佇列、優先佇列、雙端佇列資料結構演算法佇列
- 陣列模擬佇列進階版本——環形佇列(真正意義上的排隊)陣列佇列
- 資料結構與演算法——佇列(環形佇列)資料結構演算法佇列
- [BUG反饋]admin的二級選單排序BUG排序
- cpu的排程演算法演算法
- 《演算法》- 佇列和棧演算法佇列
- 演算法-棧佇列堆演算法佇列
- 佇列:佇列線上程池等有限資源池中的應用佇列
- PHP 程式池與輪詢排程演算法實現多工PHP演算法
- 原始碼解讀·RT-Thread多工排程演算法原始碼thread演算法
- LVS排程演算法演算法
- 模擬銀行排隊時間—4佇列佇列
- [資料結構與演算法]佇列Queue 的多種實現資料結構演算法佇列
- 佇列、阻塞佇列佇列
- [BUG反饋]Markdown不解析
- [BUG反饋]文件模型bug模型
- [BUG反饋]安裝bug?
- Material-UI 使用反饋UI
- web app 觸控反饋WebAPP
- 開環和閉環;正反饋和負反饋
- Flink排程之排程器、排程策略、排程模式模式
- [BUG反饋]onethink\ThinkPHP\Library\OT\Database.class.php 問題反饋PHPDatabase
- [BUG反饋]OneThink1.0開發手冊書寫錯誤反饋
- 磁軌排程演算法介紹演算法
- 電梯排程演算法簡述演算法
- 演算法系列:電梯排程演算法
- 作業系統排程演算法作業系統演算法
- 演算法面試(三) 優先佇列演算法面試佇列
- 演算法之美:棧和佇列演算法佇列
- 【小白學演算法】3. 佇列演算法佇列
- 佇列-單端佇列佇列
- python資料結構與演算法——棧、佇列與雙端佇列Python資料結構演算法佇列