C++实现--先来先服务,短作业优先,高响应比优先,时间片轮转法调度算法

目录

1.需求分析

1.1概念说明

1.2先来先服务(FCFS)

1.3短作业优先(SJF)

1.4高响应比优先调度算法(HRRN)

1.5时间片轮转法(RR)

2.代码实现

3.测试用例

4.总结分析


 


1.需求分析

1.1概念说明

1.周转时间:是指从作业被提交给系统开始,到作业完成为止的这段时间间隔(称为作业周转时间)。他包括四部分时间:作业在外存后备队列上等待(作业)调度的时间,进程在就绪队列上等待进程调度的时间,进程在CPU上执行的时间,以及进程等待I/O操作完成的这段时间。简单来说,周转时间=完成时间-提交时间。

2.带权周转时间:作业的周转时间T与系统为他提供服务的时间Ts之比,即W=T/Ts。

1.2先来先服务(FCFS)

FCFS(first-come first-served)是最简单的调度算法,该算法即可用于作业调度,也可用于进程调度。当在作业调度中采用该算法时,系统将按照作业到达的先后次序来进行调度,或者说他是优考虑在系统中等待时间最长的作业,而不去管该作业所需要执行的时间的长短,从后备队列作业中选择几个最先进入该队列的作业,将他们调入内存,为他们分配资源和创建进程,然后把他放入就绪队列中。

当在进程调度中采用FCFS算法时,每次调度是从就绪的进程队列中选择一个最先进入该队列的进程,为之分配处理机,使之投入运行。该进程一直优先到完成或者发生某事件阻塞后,进程调度程序才将处理机分配给其他进程。

1.3短作业优先(SJF)

SJF(short-job-first)算法是以作业的长短来计算优先级,作业越短,其优先级越高。作业的长短是以作业所要求的运行时间来衡量的。SJF算法可以分别用于作业调度和进程调度。在把短作业优先调度算法用于作业调度时,她将从外存的作业后备队列中选择若干个估计运行时间最短的作业,优先将他们调入内存运行。

1.4高响应比优先调度算法(HRRN)

HRRN(hignest response ratio next),该算法既考虑了作业的等待时间过长,又考虑了作业的运行时间,既照顾了短作业,又不致使长作业等待时间过长,从而改善了处理机调度的性能。

我们引入一个动态优先级,即优先级是可以改变的,令他随等待时间延长而增加,这将使长作业的优先级在等待期间不断的增加,等到足够的时间后,必然有机会获得处理机。

该优先级的变化规律可以描述为:优先权=(等待时间+要求服务时间)/要求服务时间

                                                                 =1+等待时间/要求服务时间

从上述公式我们可以得到:

  1. 如果作业的等待时间相同,则要求服务的时间越短,其优先级越高,类似于SJF算法。
  2. 当要求服务的时间相同时,作业的优先权又可以决定于其等待时间,类似于FCFS算法。
  3. 对于长作业的优先级,可以随等待时间的增加而提高,当其等待时间足够长时,也可以获得处理机

1.5时间片轮转法(RR)

在RR中,系统根据FCFS策略,将所有的就绪进程排成一个就绪队列,并可设置每个一定时间间隔(20ms)即产生一次中断,激活系统中的进程调度程序,完成一次调度,将CPU分配给队首进程,令其执行。当该进程的时间片耗尽或者运行完毕后,系统再次将CPU分配给新的队首进程(或新到达的紧迫进程)。由此,可保证就绪队列中的所有进程在一个确定的时间段内,都能够获得一次CPU执行。

在RR调度算法中,应在何时进行进程的切换,可分为两种情况:①若一个时间片尚未用完,正在运行的进程便已经完成,就立即激活调度程序,将他从就绪队列删除,再调度就绪队列中队首的其他进程运行,并启动一个新的时间片。②在一个时间片用完时,计时器阻断处理程序被激活。如果进程尚未运行完毕,调度程序把他送往就绪队列的末尾。

2.代码实现

C++代码实现:

// Self.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include<vector>
#include<algorithm>
#include <iomanip>
using namespace std;

class PCBNode
{
private:
	char name;			//进程名
	float arrivetime;	//提交时间
	float runningtime;	//运行时间
	float waittime;		//等待时间
	float finishtime;	//完成时间

	float roundtime;	//周转时间
	float weighttime;	//带权周转时间
	float prior;//优先级
	float rrtime;//时间片轮转法的完成标记
	int flag;	//只是标记默认排序的方式
public:
	//这里设置flag是因为FCFS和SJF排序的方式不对
	operator float() const 
	{ 
		if (1 == flag)
		{
			return arrivetime;
		}
		else if (2 == flag)
		{
			return runningtime;
		}
		else if(3==flag)
		{
			return prior;
		}
		else if (4 == flag)
		{
			return waittime;
		}
	}
	//构造函数,初始化进程
	PCBNode(char nameP, float arrivetimeP, float runningtimeP)
		:name(nameP), arrivetime(arrivetimeP), runningtime(runningtimeP), rrtime(runningtime)
	{
		
		waittime = 0;
	}
	char& Name() {
		return name;
	}
	const char& Name() const {
		return name;
	}
	float& Arrivetime()
	{
		return arrivetime;
	}
	const float& Arrivetime()const
	{
		return arrivetime;
	}
	float& Runntime() {
		return runningtime;
	}
	const float& Runningtime() const{
		return runningtime;
	}
	float & Waittime()
	{
		return waittime;
	}
	const float& Waittime()const
	{
		return waittime;
	}
	float& Finishtime()
	{
		return finishtime;
	}
	const float& Finishtime()const
	{
		return finishtime;
	}
	float& Roundtime()
	{
		return roundtime;
	}
	const float& Roundtime() const {//周转时间
		return roundtime; 
	}	
	float& Weighttime() {
		return  weighttime; 
	}	//带权周转时间
	const float& Weighttime() const
	{ return  weighttime;
	}
	float& Rrtime()
	{
		return rrtime;
	}
	const float& Rrtime()const
	{
		return rrtime;
	}
	float& Prior()
	{
		return prior;
	}
	const float& Prior()const 
	{
		return prior;
	}
	int& Flag()
	{
		return flag;
	}
	const int& Flag()const
	{
		return flag;
	}
};
class Manage
{
private:
	vector<PCBNode> ProcessList;
	vector<PCBNode> RRProcess;//作为中间桥梁
	vector<PCBNode> RunProcess;//用来存放运行的程序运行
	vector<PCBNode> FinallProcess;//存放最终结果

	float allroundtime = 0.0;
	float allweightroundtime = 0.0;

	float averroundtime = 0.0;
	float averweighttime = 0.0;

public:
	
	void add(PCBNode &val)
	{
		ProcessList.push_back(val);
	}
	//取得平均带权时间和平均带权周转时间
	void AverageTime(vector<PCBNode> ProcessList)
	{
		allroundtime = 0, allweightroundtime = 0;
		for (size_t i = 0; i < ProcessList.size(); i++)
		{
			
			allroundtime = allroundtime + ProcessList[i].Roundtime();
			allweightroundtime = allweightroundtime + ProcessList[i].Weighttime();
		}
		averroundtime = allroundtime / ProcessList.size();
		averweighttime = allweightroundtime / ProcessList.size();
		cout << "平均带权时间:" << averroundtime << endl;
		cout << "平均带权周转时间:" << averweighttime << endl;
	}
	void BaseOf_FCFSSJF()
	{
		//完成时间=提交时间+运行时间
		//周转时间=完成时间-运行时间
		//ProcessList0是第一个到达的,所以它的等待时间是0
		for (int i = 0; i < ProcessList.size(); i++)
		{
			if (0 == i)
			{
				ProcessList[i].Waittime() = 0.0;
			}
			else if (ProcessList[i].Arrivetime() < ProcessList[i - 1].Finishtime())
			{
				ProcessList[i].Waittime() = ProcessList[i - 1].Finishtime() - ProcessList[i].Arrivetime();
			}
			else
			{
				ProcessList[i].Waittime() = ProcessList[i].Arrivetime();
			}
			ProcessList[i].Finishtime() = ProcessList[i].Runningtime() + ProcessList[i].Waittime() + ProcessList[i].Arrivetime();
			ProcessList[i].Roundtime() = ProcessList[i].Finishtime() - ProcessList[i].Arrivetime();
			ProcessList[i].Weighttime() = ProcessList[i].Roundtime() / ProcessList[i].Runningtime();
		}
	
	}
	void FCFS()
	{
		for (int i = 0; i < ProcessList.size(); i++)
		{
			ProcessList[i].Flag() = 1;
		}
		sort(ProcessList.begin() + 1, ProcessList.end());
		BaseOf_FCFSSJF();
		Print(ProcessList);
		AverageTime(ProcessList);
		FinallProcess.clear();
		ProcessList.clear();
		RunProcess.clear();
	}
	void SJF()
	{
		for (int i = 0; i < ProcessList.size(); i++)
		{
			ProcessList[i].Flag() = 2;
		}
		//排序从第二个进程开始的原因:第一位进程先到达,直接运行,不用等待
		sort(ProcessList.begin() + 1, ProcessList.end());	
		BaseOf_FCFSSJF();
		Print(ProcessList);
		AverageTime(ProcessList);
		FinallProcess.clear();
		ProcessList.clear();
		RunProcess.clear();
	}
	
	void Prior_HRRN(int i, const int tag)
	{
		for (; i < ProcessList.size(); i++)
		{
			if (ProcessList[i].Arrivetime() < ProcessList[tag].Finishtime())
			{
				ProcessList[i].Waittime() = ProcessList[tag].Finishtime() - ProcessList[i].Arrivetime();
			}
			else
			{
				//ProcessList[i].Waittime() = 0;
			}
			ProcessList[i].Finishtime() = ProcessList[i].Runningtime() + ProcessList[i].Waittime() + ProcessList[i].Arrivetime();
			ProcessList[i].Roundtime() = ProcessList[i].Finishtime() - ProcessList[i].Arrivetime();
			ProcessList[i].Weighttime() = ProcessList[i].Roundtime() / ProcessList[i].Runningtime();
			ProcessList[i].Prior() = ProcessList[i].Waittime() / ProcessList[i].Runningtime() + 1;
		}

	}
	void Base_HRRN(int i, const int tag)
	{
		for (int k = 0; k < ProcessList.size(); k++)
		{
			ProcessList[k].Flag() = 3;
		}
		for (; i < ProcessList.size(); i++)
		{
			//计算优先级
			Prior_HRRN(i, tag);

			//按优先级高低排序	
			sort(ProcessList.begin() + 1, ProcessList.end(), greater<PCBNode>());
			//优先级高的进程首先执行
			ProcessList[i].Finishtime() = ProcessList[i].Runningtime() + ProcessList[i].Waittime() + ProcessList[i].Arrivetime();
			ProcessList[i].Roundtime() = ProcessList[i].Finishtime() - ProcessList[i].Arrivetime();
			ProcessList[i].Weighttime() = ProcessList[i].Roundtime() / ProcessList[i].Runningtime();
			for (int j = i + 1; j < ProcessList.size(); j++)
			{
				ProcessList[j].Finishtime() = ProcessList[j].Roundtime() = 0;
				//ProcessList[i].Waittime() = ProcessList[i-1].Waittime() = 0;
			}

			break;
		}


	}
	void HRRN()
	{
		//对于第一个进程来说优先运行
		ProcessList[0].Waittime() = 0.0;
		ProcessList[0].Finishtime() = ProcessList[0].Runningtime() + ProcessList[0].Waittime() + ProcessList[0].Arrivetime();

		ProcessList[0].Roundtime() = ProcessList[0].Finishtime() - ProcessList[0].Arrivetime();
		ProcessList[0].Weighttime() = ProcessList[0].Roundtime() / ProcessList[0].Runningtime();
		int length = ProcessList.size();
		int tag = 0;
		//当有一个进程运行完时,都要计算其余的每个进程的优先级
		for (int i = 1; i < length; i++)
		{
			Base_HRRN(i, i - 1);
		}

		Print(ProcessList);
		AverageTime(ProcessList);
		FinallProcess.clear();
		ProcessList.clear();
		RunProcess.clear();
	}

	void CalTimeRR(const int piece)
	{
		///各进程等待时间排序(我在计算等待时间时多加了少于一个时间片的时间长度,具体可以自己看)
		for (int i = 0; i < FinallProcess.size(); i++)
		{
			FinallProcess[i].Flag() = 4;
		}
		sort(FinallProcess.begin(), FinallProcess.end());

		int length = FinallProcess.size();
		int flag = 0;
		int sub = 0;//多计算的时间差
		//标记出是从那个进程开始多计算时间的
		for (int i = 0; i < length; i++)
		{
			if (FinallProcess[i].Rrtime() != 0)
			{
				flag = i;
				sub = abs(FinallProcess[i].Rrtime());
				break;
			}

		}
		for (int i = 0; i < length; i++)
		{
			if (i > flag)
			{
				FinallProcess[i].Waittime() = FinallProcess[i].Waittime() - sub;
			}
			FinallProcess[i].Finishtime() = FinallProcess[i].Runningtime() + FinallProcess[i].Waittime() + FinallProcess[i].Arrivetime();
			FinallProcess[i].Roundtime() = FinallProcess[i].Finishtime() - FinallProcess[i].Arrivetime();
			FinallProcess[i].Weighttime() = FinallProcess[i].Roundtime() / FinallProcess[i].Runningtime();
		}
	}

	//判断所有的进程是否都执行完,成功执行完返回true
	bool Success(int length)
	{

		int count = 0;
		for (int g = 0; g < length; g++)
		{
			if (FinallProcess[g].Rrtime() > 0)
			{
				return false;
			}
			count++;
		}
		if (count == length)
		{
			return true;;
		}
	}
	void All_Process(const int length, const int piece)
	{
		int i = 0;
		bool end = false;
		while (!end)
		{
			if (FinallProcess[i].Rrtime() > 0)//表示该进程还没有执行完
			{
				FinallProcess[i].Rrtime() = FinallProcess[i].Rrtime() - piece;

				for (int g = 0; g < length; g++)
				{
					if (FinallProcess[g].Rrtime() > 0 && g != i)
					{
						FinallProcess[g].Waittime() += piece;
					}
				}
			}
			i = (i + 1) % length;
			end = Success(length);
		}
	}
	void FillList(int k, const int piece,const  int length, int count)
	{
		//先更新进程列表信息
		//更新RRp队列中的进程
		RRProcess.erase(RRProcess.begin());
		RRProcess.push_back(RunProcess[0]);
		RunProcess.pop_back();
		RunProcess.push_back(FinallProcess[0]);
		FinallProcess.erase(FinallProcess.begin());

		int length_RRP = RRProcess.size();

		for (int g = 0; g < length_RRP; g++)
		{
			FinallProcess[g].Waittime() += piece;
		}
		for (; k < length; k++)
		{
			if (ProcessList[k].Arrivetime() <= piece * count)
			{
				RRProcess.push_back(ProcessList[k]);
				FinallProcess.push_back(ProcessList[k]);
				FinallProcess[k - 1].Waittime() = piece * 2 - FinallProcess[k - 1].Arrivetime();
			}
			else//后面的进程还没有到达就绪队列
			{
				break;
			}
		}
		//然后运行Runn中的进程
		if (RunProcess[0].Runningtime() <= piece)//第一个进程能够在一个时间片内完成
		{
			RunProcess[0].Rrtime() = 0;
		}
		else
		{
			RunProcess[0].Rrtime() = RunProcess[0].Runningtime() - piece;
		}
		FinallProcess.push_back(RunProcess[0]);
	}
	void Base_RR(const int piece)
	{
		int length = ProcessList.size();

		
		int k = 1;
		//运行队列中为第一个到达的队列
		RunProcess.push_back(ProcessList[0]);
		//看有哪些进程已经到达就绪队列
		for (; k < length; k++)
		{
			if (ProcessList[k].Arrivetime() <= piece * 1)
			{
				RRProcess.push_back(ProcessList[k]);

				FinallProcess.push_back(ProcessList[k]);
				FinallProcess[k - 1].Waittime() = piece * 1 - FinallProcess[k - 1].Arrivetime();
			}
			else//后面的进程还没有到达就绪队列
			{
				break;
			}
		}
		//运行Runn中的进程,并计算RRP队列中的各种时间
		if (RunProcess[0].Runningtime() <= piece)//第一个进程能够在一个时间片内完成
		{
			RunProcess[0].Waittime() = 0;
			RunProcess[0].Rrtime() = 0;
		}
		else
		{
			RunProcess[0].Rrtime() = RunProcess[0].Runningtime() - piece;
		}
		FinallProcess.push_back(RunProcess[0]);
		//------------第一次进程完成--------------

			//判断是否所有进程都以到达就绪队列
		int count = 2;
		while (length != FinallProcess.size())
		{

			//在进程1结束后,还有进程没有到达就绪队列

			FillList(k, piece, length, count);
			count++;

		}

		All_Process(length, piece);
		CalTimeRR(piece);//计算各个进程的完成时间,周转时间,带权周转时间,
		//AverageTime_RR(FinallProcess);//计算平均周转时间,带权平均周转时间
	}

	void RR(int piece)
	{
		//各进程按照到达时间排序
		for (int i = 0; i < ProcessList.size(); i++)
		{
			ProcessList[i].Flag() = 1;
		}
		sort(ProcessList.begin() + 1, ProcessList.end());

		Base_RR(piece);
		
		
		Print(FinallProcess);
		AverageTime(FinallProcess);
		FinallProcess.clear();
		ProcessList.clear();
		RunProcess.clear();


	}
	void Print(vector<PCBNode> ProcessList)
	{
		for (int i = 0; i < ProcessList.size(); i++)
		{
			ProcessList[i].Flag() = 1;
		}
		sort(ProcessList.begin() + 1, ProcessList.end());
		cout << "-进程" << "--提交时间" << "--运行时间"
			<< "--完成时间"<<"--等待时间"<< "--周转时间" << "--带权周转时间" << endl;
		for (int i = 0; i < ProcessList.size(); i++)
		{
			cout << setw(3) <<ProcessList[i].Name() << setw(8) << ProcessList[i].Arrivetime()
				<<setw(10) << ProcessList[i].Runntime() << setw(9)	<< ProcessList[i].Finishtime()
				<< setw(12) <<ProcessList[i].Waittime()<< setw(10) << ProcessList[i].Roundtime() << 
				setw(10) << ProcessList[i].Weighttime()<< endl;
		}
		
	}
	void Menu()
	{
		cout << "1------先来先服务算法FCFS------" << endl;
		cout << "2------短作业优先算法SJF-------" << endl;
		cout << "3------高响应比算法HRRN--------" << endl;
		cout << "4------时间片轮转算法RR--------" << endl;
	}
};
int main()
{
	int num_process;
	char name;
	float arrivetime, runntime;
	Manage process;
	int choose = 0;
	char end = 'y';
	int piece = 0;
	int count = 1;
	while ('y'==end ||'Y'==end)
	{
		fflush(stdin);
		process.Menu();
		cout << "请输入你的选择:";
		cin >> choose;
		if (choose < 1 || choose>4)
		{
			cout << "请重新输入!!!" << endl;
		}
		else
		{
			cout << "请输入进程的个数:";
			cin >> num_process;	
			for (int i = 0; i < num_process; ++i)
			{
				cout << "请输入第" << i + 1 << "个进程的名称,提交时间,运行时间:";
				cin >> name;
				cin >> arrivetime;
				cin >> runntime;
				PCBNode obj(name, arrivetime, runntime);
				process.add(obj);
				}
			switch (choose)
			{
			case 1:
				process.FCFS();
				break;
			case 2:
				process.SJF();
				break;
			case 3:
				process.HRRN();
				break;
			case 4:
				cout << "请输入时间片的大小:";
				cin >> piece;
				process.RR(piece);
				break;
			default:
				cout << "请输入正确选项!!!" << endl;
				break;
			}
		
			cout << "是否继续选择算法(Y/y):";
			fflush(stdin);
			cin >> end;
		
		}
		
		
	}
	
}

3.测试用例

 

4.总结分析

  1. FCFS算法经常与其他调度算法相结合使用,形成一种更为高效的调度算法。

  2. SJF算法,对长作业非常不利,长作业的周转时间会明显地增加,甚至会出现饥饿现象;而且完全没有考虑作业的紧迫程度。

  3. HRRN算法,在每次进行调度时,都需要先做响应比的计算,显然会增加系统开销。

  4. RR算法,时间片的选择大小对系统性能有很大的影响。若选择较小的时间片,将有利于短作业,因为他能在该时间内完成。但时间片小,意味着频繁地执行进程调度和进程上下文的切换,会增加系统的开销。若时间片选择得太长,且为使每个进程都能在一个时间片完成,RR算法便会退化为FCFS算法,无法满足短作业和交互式用户的需求。一个较为可取的时间片是略大于一次典型的交互所需要的时间,使大多数交互式进程能够在一个时间片内完成,从而获得很小的响应时间。 

 

  • 23
    点赞
  • 168
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值