多级反馈队列调度算法是目前公认的较好的一种进程调度算法,它能较好的满足各类进程的需要。
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;
}