操作系统进程调度算法的模拟Word下载.doc
《操作系统进程调度算法的模拟Word下载.doc》由会员分享,可在线阅读,更多相关《操作系统进程调度算法的模拟Word下载.doc(11页珍藏版)》请在冰点文库上搜索。
D
5
E
8
(2)每个用来标识进程的进程控制块PCB可用结构来描述,包括以下字段(用不到的字段可以不定义)。
²
进程标识数ID。
进程优先数PRIORITY,并规定优先数越大的进程,其优先权越高。
进程已占用CPU时间CPUTIME。
进程还需占用的CPU时间ALLTIME。
当进程运行完毕时,ALLTIME变为0。
进程的阻塞时间STARTBLOCK,表示当进程再运行STARTBLOCK个时间片后,进程将进入阻塞状态。
进程被阻塞的时间BLOCKTIME,表示已阻塞的进程再等待BLOCKTIME个时间片后,将转换成就绪状态。
进程状态STATE。
队列指针NEXT,用来将PCB排成队列。
(3)优先数改变的原则:
进程在就绪队列中呆一个时间片,优先数增加1。
进程每运行一个时间片,优先数减3。
(4)为了清楚地观察每个进程的调度过程,程序应将每个时间片内的进程的情况显示出来,包括正在运行的进程,处于就绪队列中的进程和处于阻塞队列中的进程。
(5)分析程序运行的结果,谈一下自己的认识。
四、实验结果及分析
(1)实验关键代码
①模拟PCB数据结构定义:
///枚举进程的状态:
新建、就绪、执行、阻塞、终止
enumSTATE_PROCESS{New,Ready,Run,Block,Finish};
typedefenumSTATE_PROCESSSTATE;
///建立PCB结构体
structPCB_NODE{
intid;
///进程标识数
intpriority;
///进程优先数
intarriveTime;
///进程到达时间
intcpuTime;
///进程已占用CPU时间
intallTime;
///进程还需占用CPU时间
intblockTime;
///进程已阻塞时间
STATEstate;
///进程状态
structPCB_NODE*prev;
///PCB前指针
structPCB_NODE*next;
///PCB后指针
};
typedefstructPCB_NODEPCB;
②模拟进程队列操作函数定义:
///进程入列
voidqueuePush(PCB*process,PCB*queueHead)
///进程出列
voidqueuePop(PCB*process,PCB*queueHead)
///查看队列中进程信息
voidqueueWalk(PCB*queueHead)
③模拟就绪队列操作函数定义:
///进程插入到就绪队列
voidreadyQueuePush(PCB*process)
///优先数最大的进程出列
PCB*readyQueuePop()
///每个时间片更新就绪队列中的进程信息
voidreadyQueueUpdate(inttimeSlice,PCB*pcb)
///返回就绪队列最大优先数的值
intreadyMaxPriority()
///查看就绪队列中的进程信息
voidreadyQueueWalk()
④模拟阻塞队列操作函数定义:
///进程插入到阻塞队列
voidblockQueuePush(PCB*process)
PCB*blockQueuePop()
///每个时间片更新阻塞队列中进程的信息
voidblockQueueUpdate()
///查看阻塞队列中的进程信息
voidblockQueueWalk()
⑤模拟动态优先权进程调度函数定义:
///初始化进程PCB数据,返回PCB头指针
PCB*initData()
///模拟CPU执行1个时间片的操作
voidcpuWord(PCB*cpuProcess)
⑥主函数关键代码:
inttimeSlice=0;
///模拟CPU时间片
intcpuBusy=0;
///模拟CPU状态
PCB*cpuProcess=NULL;
///当前CPU执行的进程
PCB*pHead,*pro;
///进程PCB头指针
pHead=initData();
///初始化进程PCB,返回进程头指针
pro=pHead+1;
///pro指向PCB中第一个进程
readyQueueUpdate(timeSlice,pro);
///根据进程到达时间将新建进程加入绪队列
///模拟动态优先权进程调度
while(true){
if(readyQueueNum==0&
&
blockQueueNum==0&
cpuBusy==0){
printf("
就绪队列、阻塞队列和CPU当前无进程运行,退出\n"
);
break;
}///endif
if(cpuBusy==0){///CPU空闲,选择一个进程进入CPU
if(readyQueueNum>
0){
///选择就绪队列优先级最高的进程作为CPU运行进程
cpuProcess=readyQueuePop();
}else{
///就绪队列中没有进程,改为选择阻塞队列优先级最高的进程
cpuProcess=blockQueuePop();
}
cpuProcess->
cpuTime=0;
///设置当前运行进程占用CPU时间
state=Run;
///设置当前运行进程的状态
cpuBusy=1;
///设置CPU当前状态为忙
}///endif
timeSlice++;
///当前时间片加1
printf("
\n第%d个时间片后:
\n"
timeSlice);
cpuWord(cpuProcess);
///模拟CPU执行1个时间片的操作
if(cpuProcess->
allTime==0){///若当前执行进程还需CPU时间片为0
state=Finish;
///设置当前进程状态为终止
free(cpuProcess);
///释放该进程的PCB内存空间
cpuBusy=0;
///CPU状态设置为空闲
///更新就绪队列和阻塞队列中的进程信息
blockQueueUpdate();
readyQueueUpdate(timeSlice,pro);
///查看就绪队列和阻塞队列的进程信息
readyQueueWalk();
blockQueueWalk();
if(cpuBusy==1&
readyQueueNum>
0&
cpuProcess->
priority<
readyMaxPriority()){
blockQueuePush(cpuProcess);
///需抢占CPU,当前执行的进程调入阻塞队列
cpuProcess=readyQueuePop();
///从就绪队列中选择优先级最高的进程运行
}
printf("
\n模拟进程动态优先权调度算法结束.\n"
return0;
(2)动态优先权调度算法流程图
(2)实验结果
①第1个时间片后:
②第2个时间片后:
③第3个时间片后:
④第4个时间片后:
⑤第5个时间片后:
⑥第6个时间片后:
⑦第7个时间片后:
⑧第8个时间片后:
⑨第9个时间片后:
⑩第10个时间片后:
⑪第11个时间片后:
⑫第12个时间片后:
⑬第13个时间片后:
⑭第14个时间片后:
⑮第15个时间片后:
⑯第16个时间片后:
⑰第17个时间片后:
⑱第18个时间片后:
⑲第19个时间片后:
⑳第20个时间片后:
(3)实验结果分析
①调度算法开始之前进程PCB信息为:
②调度算法结束之后进程PCB信息为:
③调度算法分析:
进程ID
到达时间
结束时间
周转时间
带权周转时间
10
3.3
1
20
18
3.0
16
12
2.4
13
2.5
(4)实验心得
通过进程动态优先权调度算法的模拟,对进程的运行状态,进程PCB数据结构,进程调度算法有了更深的理解。
动态优先权调度算法为了防止高优先级进程无休止地运行下去,调度程序在每个时钟滴答(即每个时钟中断)降低当前进程的优先级。
如果这个动作导致该进程的优先级低于次高优先级的进程,则进行进程切换,可以避免低优先级进程长时间的饥饿等待。
此外,优先级可以由系统动态确定。
例如有些进程为I/O密集型,其多数时间用来等待I/O结束。
当这样的进程需要CPU时,应立即分配给它CPU,以便启动下一个I/O请求,这样就可以在另一个进程计算的同时执行I/O操作。
使这类I/O密集型进程长时间等待只会造成它无谓地长时间占用内存。
使I/O密集型进程获得较好服务的一种简单算法是,将其优先级设为1/f,f为该进程在上一时间片中所占的部分。
如果一个在其50ms的时间片中只使用1ms的进程的优先级为50,而在阻塞之前用掉25ms的进程优先级为2,使用掉全部时间片的进程优先级为1。
这样,可以很方便地将一组进程按优先级分成若干类,并在各类之间采用优先级调度,而在各类进程的内部采用轮转调度。
如下图为一个具有4类优先级的系统,其调度算法如下:
只要存在优先级为第4类的可运行进程,就按照轮转法为每个进程运行一个时间片,此时不理会较低优先级的进程。
若第4类进程为空,则按照轮转法运行第3类进程。
若第4类和第3类均为空,则按照轮转法运行第2类进程。
如果不偶尔对优先级进行调整,则低优先级进程很可能会产生饥饿现象。
队列头可运行进程
最高优先级
最低优先级
教师评价
评定项目
算法正确
界面美观,布局合理
程序结构合理
操作熟练
语法、语义正确
解析完整
实验结果正确
文字流畅
报告规范
题解正确
其他:
评价教师签名:
年月日
第10页