时间片轮转强占式短进程优先算法Word文档格式.docx
《时间片轮转强占式短进程优先算法Word文档格式.docx》由会员分享,可在线阅读,更多相关《时间片轮转强占式短进程优先算法Word文档格式.docx(16页珍藏版)》请在冰豆网上搜索。
⑴需求分析;
⑵功能设计(数据结构及模块说明);
⑶开发平台及源程序的主要部分;
⑷测试用例,运行结果与运行情况分析;
⑸自我评价与总结:
)你认为你完成的设计哪些地方做得比较好或比较出色;
)什么地方做得不太好,以后如何改正;
)从本设计得到的收获(在编写,调试,执行过程中的经验和教训);
)完成本题是否有其他方法(如果有,简要说明该方法);
时间安排:
设计安排一周:
周1、周2:
完成程序分析及设计。
周2、周3:
完成程序调试及测试。
周4、周5:
验收、撰写课程设计报告。
(注意事项:
严禁抄袭,一旦发现,一律按0分记)
指导教师签名:
年月日
系主任(或责任教师)签名:
进程调度模拟设计
时间片轮转、强占式短进程优先算法
一、需求分析
本次课程设计需要通过设计一个模拟进程调度的系统,来实现进程调度过程的模拟,对进程调度的功能以及进程调度的算法有更加深层次的理解。
时间片轮转法的基本思路是每个进程被分配一个时间段,称作它的时间片,即该进程允许运行的时间。
如果在时间片结束时进程还在运行,则CPU将被剥夺并分配给另一个进程。
如果进程在时间片结束前阻塞或结束,则CPU当即进行切换。
调度程序所要做的就是维护一张就绪进程列表,当进程用完它的时间片后,它被移到队列的末尾。
这样让每个进程在就绪队列中的等待时间与享受服务的时间成正比例。
在批处理为主的系统中,如果采用FCFS方式进程作业调度,虽然系统开销小,算法简单,但是,如果估计执行时间很短的作业时在那些长作业的后面到达系统的话,则必须等待长作业执行完成之后才有机会获得执行。
这将造成不必要的等待和不公平,最短作业优先法就是选择那些估计需要执行时间最短的作业投入执行,为它们创建进程和分配资源。
直观上说,采用最短作业优先的调度算法,可使得系统在同一时间内处理的作业个数最多,从而吞吐量也就大于其它调度方式。
按照需求有以下条件:
进程PCB(包含进程名、到达时间、预计运行时间等)
调度算法(时间片轮转、强占式短进程优先)
为完成这两种算法的调度模拟,需要用高级语言编程完成模拟操作,能够处理以下的情形:
(1)能够选择不同的调度算法(要求中给出的调度算法)
(2)能够输入进程的基本信息,如进程名、到达时间和运行时间等
(3)根据选择的调度算法显示进程调度队列
(4)根据选择的调度算法计算平均周转时间和平均带权周转时间
该设计中的进程调度模拟系统在使用时,用户可以输入各进程信息(包含进程名、到达时间、估计运行时间);
输入完毕确认后,可选择两种调度算法中的一种执行,查看结果可得到相应算法的调度序列,每个进程的到达时间、预计运行时间、开始时间、结束时间和周转时间、带权周转时间,以及平均周转时间和平均带权周转时间。
二、功能设计
2.1进程信息的描述和实现
此次课程设计中,进程作为基本数据处理单元,需要对进程的基本信息进行相关的描述。
进程的基本信息包括进程进程名、到达的时间、预计的进程运行时间、进程开始运行时间、进程仍需运行的时间、进程完成的时间、进程运行的次数等。
在此,定义一个类来抽象进程。
并在此基础上进行其他操作。
数据结构方案声明如下:
classProcePcb{
public:
ProcePcb(stringname,intsub,intexe,intid):
pro_name(name),time_submit(sub),time_exe(exe),pro_id(id),
time_start(0),time_end(0),time_wait(0),pro_state(READY),time_left(exe),
time_turn(0),time_aver(0.0){}
//默认构造函数
ProcePcb():
pro_name(string("
"
)),time_submit(0),time_exe(0),pro_id(-1),
time_end(0),time_start(0),time_wait(0),pro_state(READY),time_left(0),
time_turn(0),time_aver(0.0){}
//GettersandSetters
stringgetPro_name(){returnpro_name;
}
intgetTime_submit(){returntime_submit;
intgetTime_exe(){returntime_exe;
intgetPro_id(){returnpro_id;
intgetTime_start(){returntime_start;
}
intgetTime_wait(){returntime_start;
intgetPro_state(){returnpro_state;
intgetTime_left(){returntime_left;
intgetTime_turn(){returntime_turn;
intgetTime_aver(){returntime_aver;
voidsetTime_start(intstart){time_start=start;
}//设置开始时间
voidsetTime_left(intleft){time_left=left;
voidsetTime_end(intend){time_end=end;
}//设置结束时间
voidsetPro_state(intstate){pro_state=state;
}//设置进程的状态
//..打印进程的信息
voidPrintPcbInfo();
//
//..进程执行模拟
boolProceExe(int);
//参数为时间单位,返回CPU是否执行完毕
//内部逻辑计算包括周转时间以及带权周转时间的计算
voidCalTimeLogic();
protected:
//进程的名字
stringpro_name;
//提交时间--用十进制封装
inttime_submit;
//从时间的1开始计时
//进程所需的运行时间
inttime_exe;
//进程ID--系统生成
intpro_id;
//开始执行的时间
inttime_start;
//结束的时间
inttime_end;
//等待的时间
inttime_wait;
//进程的状态(就绪,执行,完成)
intpro_state;
//...上下文封装
inttime_left;
//还需多少时间单位,初始化为所需的执行时间
//周转时间
inttime_turn;
//带权周转时间
floattime_aver;
};
2.2调度算法的描述和实现
进程基本信息所构成的模块作为基本单元,并且相关调度算法的侧重进程基本信息点不同,所以要根据其调度算法的特点来结合基本信息进行对应的设计。
此次课程设计要求的调度算法描述如下:
2.2.1时间片轮转调度算法
时间片轮转法的中心思想在于将CPU的运行划分为一个个时间片,然后将这些时间片平均分配给已经准备就绪的进程,在一个时间片内只允许一个进程占用处理器。
如果当前进程运行结束则时间片终止。
这样可以较公平的分配处理器运行时间,使每个进程都可以得到处理。
2.2.2强占式短进程优先调度算法
对强占式短进程优先调度算法而言,其本质特征便是按进程的预计运行时间长短进行排序,先执行短进程。
若内存中运行的进程优先级比就绪队列中的某进程优先级低(即运行的进程预计运行时间比就绪队列中的某进程长),此运行的进程让出内存并进入就绪队列,优先级更高的短进程强占内存资源并运行直到结束或者遇到优先级更高的进程强占为止。
2.2.3模块说明:
classCPUModel//CPU功能模块的封装
{
CPUModel():
pcbnum(0),idCount(0),allturn(0),allaver(0.0){}
//从用户界面获取进程
voidGetPcb(pcbList&
);
//..CPU开始执行程序
voidExeProce(pcbList&
//时间片轮转法模拟程序
voidRRModel(pcbList&
//不能改变原队列
//抢占式短进程优先
voidSJF_Grab(sjfList);
//..获取当前时刻之前的最短进程在队列中的标号
intGetTheSP(sjfList,int);
//队列为排序之后的队列
//..获取下一个进程ID
intGetNextId();
//打印就绪队列中的进程的信息
voidPrintList(pcbList);
intgetPcbnum(){returnpcbnum;
//...
boolIsProComing(int);
//..当前时刻时是否有新的进程到达
//...将就绪队列按提交时间排序
voidSortTheList(sjfList);
boolIsOver(sjfList);
//是否所有的进程都执行完毕
private:
//进程数量
intpcbnum;
intidCount;
//进程ID计数
intallturn;
//总周转时间
floatallaver;
//总带权周转时间
下面为较为重要的几个函数:
voidProcePcb:
:
PrintPcbInfo()//打印信息
CalTimeLogic()//内部逻辑计算
boolProcePcb:
ProceExe(inttime)//进程执行模拟
voidCPUModel:
GetPcb(pcbList&
list)//获取用户需要建立的进程,入就绪队列
PrintList(pcbListlist)//打印就绪队列中的进程的信息
ExeProce(pcbList&
list)进程调度主过程
RRModel(pcbList&
list)//时间片轮转法模拟
SJF_Grab(sjfListlist)//强占式短进程优先模拟
程序的主程序流程如下:
intmain()
CPUModelcpu;
cpu.GetPcb(pcblist);
cpu.PrintList(pcblist);
cpu.ExeProce(pcblist);
return0;
三、开发平台
MicrosoftWindows7操作系统;
MicrosoftVisual2010。
四、源程序的主要部分
4.1.时间片轮转法模拟部分:
list){
staticintrtime=1;
//表示时钟
if(list.size()==0)
return;
//..不断的从就绪队列中取进程执行
/*
时间片轮转的模型是:
时间片为1秒进程各个时间都以十进制来简化
进程正在执行时打印其信息并让主CPU停顿1秒以表示执行进程一个时间单位
*/
ProcePcbpcb;
//每次执行的进程
//设置一个轮转队列
pcbListrrlist;
while
(1){
//查找当前时间下已经提交的进程入轮转队列
if(IsProComing(rtime)){
while(readylist.size()!
=0&
&
IsProComing(rtime+1)){//先对队列判空是必须的
ProcePcbpcb=readylist.front();
rrlist.push(pcb);
readylist.pop();
}
}
//下面的程序操作轮转队列
if(rrlist.size()==0){//查看最早提交的进程
cout<
<
"
\n->
TIME:
第"
rtime<
秒:
endl;
->
没有进程提交!
++rtime;
Sleep(1000);
//消耗CPU时间1秒
continue;
//..每次从队列中取第一个进程
pcb=rrlist.front();
rrlist.pop();
//先进行进程逻辑维护
pcb.setPro_state(EXECUTE);
//设置执行状态
if(pcb.getTime_start()==0)
pcb.setTime_start(rtime);
//设置开始时间
boolresult=false;
result=pcb.ProceExe
(1);
//进程执行一个时间单位
cout<
正在调度执行的进程:
endl;
pcb.PrintPcbInfo();
//打印正在执行的进程的信息
if(result){
//进程执行完毕
pcb.setPro_state(END);
pcb.setTime_end(rtime);
//CPU调度统计计算
pcb.CalTimeLogic();
allturn+=pcb.getTime_turn();
allaver+=pcb.getTime_aver();
//......
进程:
pcb.PrintPcbInfo();
执行完毕"
}else{
//执行完一个时间片后进程仍然没有完毕
//则要查看下一个进程是否已经提交..现在设置了轮转队列不要进行这个判断
pcb.setPro_state(READY);
//设置进程的状态为就绪
rrlist.push(pcb);
//入轮转队列
if(rrlist.size()==0&
readylist.size()==0){
//所有进程调度执行完毕
所有的进程执行完毕,退出时间片轮转法模拟模块程序!
轮转法调度结果统计:
总进程数 :
pcbnum<
个"
平均周转时间:
(float)allturn/pcbnum<
平均带权周转时间:
allaver/pcbnum<
break;
++rtime;
Sleep(2000);
//消耗CPU时间1秒}
4.2强占式短进程优先法部分:
SJF_Grab(sjfListlist){
if(list==NULL)
staticinttime=1;
//控制CPU的时钟从1开始计时
intpid=-1;
//选取占有CPU的进程在队列中的位置
while
(1){
pid=GetTheSP(list,time);
//获取已经提交的进程中最短进程
//进程尚未结束但是返回-1则说明当前时间还没有提交任何进程
if(!
IsOver(list)&
pid==-1){
time<
++time;
Sleep(1000);
//消耗CPU时间1秒
}elseif(!
pid!
=-1){
//执行进程
//先进行进程逻辑维护
list[pid].setPro_state(EXECUTE);
if(list[pid].getTime_start()==0)
list[pid].setTime_start(time);
boolresult=false;
result=list[pid].ProceExe
(1);
list[pid].PrintPcbInfo();
if(result){
//进程执行完毕
list[pid].setPro_state(END);
list[pid].setTime_end(time);
//CPU调度统计计算
list[pid].CalTimeLogic();
allturn+=list[pid].getTime_turn();
allaver+=list[pid].getTime_aver();
//......
cout<
list[pid].PrintPcbInfo();
}elseif(IsOver(list)){
//所有的进程执行完毕
所有的进程执行完毕,退出强占式短进程优先法模拟程序!
强占式短进程优先法调度结果统计:
五、测试用例
进程名:
a到达时间:
1预测运行时间:
3
b到达时间:
3预测运行时间:
5
c到达时间:
5预测运行时间:
2
依次输入进程信息。
输入完毕后可显示出所有进程信息,并可开始选择使用哪种算法进行模拟调度,下面选择1,时间片轮转法,模拟开始。
3秒末进程a执行完毕,显示其周转时间和带权周转时间。
10秒末进程c执行完毕,显示其周转时间和带权周转时间。
11秒末进程b执行完毕,显示其周转时间和带权周转时间。
所有调度完毕,显示平均周转时间和平均带权周转时间。
继续选择2,模拟强占式短进程优先
7秒末进程c执行完毕,显示其周转时间和带权周转时间。
六、自我评价与总结
1.优势:
该程序封装性好,用了几个类进行封装,程序的结构非常清晰,每一个功能都用一个模块来实现,方便以后的移植。
在进程调度开始之前显示打印出每个进程的信息供输入者检查可以避免不必要的错误和误操作,在调度模拟过程中,每一秒的进程调度情况都打印出来供程序操作者参考,调度过程显得十分直观,充分反应了编程模拟的优越性。
2.不足:
我在定义数据结构时考虑还不太周全,我把时间都定义成了int型,就意味着我不能处理毫秒级别的问题,而且程序到达时间的输入不能和实际的世界时刻进行同步,只能做比较简单的调度模拟。
处理时间片轮转法时我将时间片固定了,并不能根据具体的情况来变化时间片的长度。
意味着如果需要处理的进程的运行时间都很长的话,会浪费比较多的系统资源来轮转处理器的执行。
3.总结:
通过这次设计,我更加深刻的理解了2种调度算法之间的共同点、差别、以及在不同情况下的优劣。
锻炼了我运用c++高级编程语言的能力,可以运用编程语言进行对操作系统调度算法的模拟,更直观的感受了操作系统内部的调度是如何运行如何分配系统资源的。
课程设计是联系实际的一个课题,它让我们把课本上的知识和实战演练联系起来,对于我们缺乏实际编程经验的大学生来说是必不可少的。
本科生课程设计成绩评定表
序号
评分项目
满分
实得分
学习态度认真、遵守纪律
10
设计分析合理