目录
1.需求分析
1.1概念说明
1.2先来先服务(FCFS)
1.3短作业优先(SJF)
1.4高响应比优先调度算法(HRRN)
1.5时间片轮转法(RR)
2.代码实现
3.测试用例
4.总结分析
1.周转时间:是指从作业被提交给系统开始,到作业完成为止的这段时间间隔(称为作业周转时间)。他包括四部分时间:作业在外存后备队列上等待(作业)调度的时间,进程在就绪队列上等待进程调度的时间,进程在CPU上执行的时间,以及进程等待I/O操作完成的这段时间。简单来说,周转时间=完成时间-提交时间。
2.带权周转时间:作业的周转时间T与系统为他提供服务的时间Ts之比,即W=T/Ts。
FCFS(first-come first-served)是最简单的调度算法,该算法即可用于作业调度,也可用于进程调度。当在作业调度中采用该算法时,系统将按照作业到达的先后次序来进行调度,或者说他是优考虑在系统中等待时间最长的作业,而不去管该作业所需要执行的时间的长短,从后备队列作业中选择几个最先进入该队列的作业,将他们调入内存,为他们分配资源和创建进程,然后把他放入就绪队列中。
当在进程调度中采用FCFS算法时,每次调度是从就绪的进程队列中选择一个最先进入该队列的进程,为之分配处理机,使之投入运行。该进程一直优先到完成或者发生某事件阻塞后,进程调度程序才将处理机分配给其他进程。
SJF(short-job-first)算法是以作业的长短来计算优先级,作业越短,其优先级越高。作业的长短是以作业所要求的运行时间来衡量的。SJF算法可以分别用于作业调度和进程调度。在把短作业优先调度算法用于作业调度时,她将从外存的作业后备队列中选择若干个估计运行时间最短的作业,优先将他们调入内存运行。
HRRN(hignest response ratio next),该算法既考虑了作业的等待时间过长,又考虑了作业的运行时间,既照顾了短作业,又不致使长作业等待时间过长,从而改善了处理机调度的性能。
我们引入一个动态优先级,即优先级是可以改变的,令他随等待时间延长而增加,这将使长作业的优先级在等待期间不断的增加,等到足够的时间后,必然有机会获得处理机。
该优先级的变化规律可以描述为:优先权=(等待时间+要求服务时间)/要求服务时间
=1+等待时间/要求服务时间
从上述公式我们可以得到:
在RR中,系统根据FCFS策略,将所有的就绪进程排成一个就绪队列,并可设置每个一定时间间隔(20ms)即产生一次中断,激活系统中的进程调度程序,完成一次调度,将CPU分配给队首进程,令其执行。当该进程的时间片耗尽或者运行完毕后,系统再次将CPU分配给新的队首进程(或新到达的紧迫进程)。由此,可保证就绪队列中的所有进程在一个确定的时间段内,都能够获得一次CPU执行。
在RR调度算法中,应在何时进行进程的切换,可分为两种情况:①若一个时间片尚未用完,正在运行的进程便已经完成,就立即激活调度程序,将他从就绪队列删除,再调度就绪队列中队首的其他进程运行,并启动一个新的时间片。②在一个时间片用完时,计时器阻断处理程序被激活。如果进程尚未运行完毕,调度程序把他送往就绪队列的末尾。
C++代码实现:
// Self.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include
#include
#include
#include
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 ProcessList;
vector RRProcess;//作为中间桥梁
vector RunProcess;//用来存放运行的程序运行
vector 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 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());
//优先级高的进程首先执行
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 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) <> 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;
}
}
}
FCFS算法经常与其他调度算法相结合使用,形成一种更为高效的调度算法。
SJF算法,对长作业非常不利,长作业的周转时间会明显地增加,甚至会出现饥饿现象;而且完全没有考虑作业的紧迫程度。
HRRN算法,在每次进行调度时,都需要先做响应比的计算,显然会增加系统开销。
RR算法,时间片的选择大小对系统性能有很大的影响。若选择较小的时间片,将有利于短作业,因为他能在该时间内完成。但时间片小,意味着频繁地执行进程调度和进程上下文的切换,会增加系统的开销。若时间片选择得太长,且为使每个进程都能在一个时间片完成,RR算法便会退化为FCFS算法,无法满足短作业和交互式用户的需求。一个较为可取的时间片是略大于一次典型的交互所需要的时间,使大多数交互式进程能够在一个时间片内完成,从而获得很小的响应时间。