多级反馈队列调度算法(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;
}


  • 10
    点赞
  • 78
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值