操作系统——使用动态优先权的进程调度算法的模拟
来源:互联网 发布:知乎周刊怎么看 编辑:程序博客网 时间:2024/06/05 19:12
实验目的:通过动态优先权算法的模拟加深进程概念和进程调度过程的理解,并学习撰写规范的科学研究报告。
设计思路:
1.对N个进程采用动态优先权算法的进程调度;
2.每个用来标识进程的进程控制块PCB用结构描述,包括以下字段:进程标识数ID,进程优先数PRIORITY,进程以占用的CPU时间CPUTIME,进程还需占用的CPU时间ALLTIME,进程状态STATE等。
3.优先数改变的原则:进程在就绪队列中呆一个时间片,优先数增加1,进程每运行一个时间片优先数减3。
4.设置调度前的初始状态。
5.将每个时间片内的进程情况显示出来。
(二)涉及的内容或知识点
本实验涉及到动态优先权算法,进程调度过程等知识点。
(三)采用的方法和手段
学生查阅资料,设计方案,编写源程序,上机调试,测试,结果分析。在规定的时间内,由学生独立完成实验过程,并对结果进行科学分析,撰写出规范的实验报告。
(四)考察点
对等动态优先权算法,进程调度过程掌握情况;考查学生的写算法和编程能力等;考查学生的分析问题和解决问题的能力;实验报告的撰写能力等。
设计思路:
(1)先对就绪队列,阻塞队列,cpu的进行初始化。
(2)进行进程调度的选择。
1)cpu,就绪队列和阻塞队列中的进程数不为0。判断cpu是否空闲。
a.cpu空闲的话,从就绪队列中选取优先级最大的;而如果就绪队列为空,则从阻塞队列中选取第一个进程。选中的进程的cputime设置为0。
b.cpu上有进程,则更新cpu上进程的状态,打印cpu上进程的id。如果cpu上的进程的alltime已经为0,即进程已经完成了,更新该进程的状态为finish,将cpu清空。如果进程在cpu上的时间达到starttime,将其放到阻塞队列,清空cpu。
2)更新阻塞队列和就绪队列中的进程中的状态,打印就绪队列和阻塞队列的进程的id。
3)打印每个进程的状态。
(3)重复上面的步骤,直到没有cpu,就绪队列,阻塞队列中都没有进程了。
在实现的程序实现过程中就绪队列和阻塞队列都设置为双向指针,方便查找,取出,插入进程。
就绪队列在插入时,是根据优先级的大小插入到队列中,并且由于每一个时间片后,进程在就绪队列中等待,优先级数值增加相同,所以保证了就绪队列的优先级由头指针开始呈递减状态。因此每次从就绪队列取出优先级最大的进程放到cpu上,都能直接取就绪队列的第一个进程。
阻塞队列在插入时,是根据blocktime的时间的大小来插入到队列中,blocktime的大小是不能发生改变的,所以设置了另外一个变量waittime,记录了进程在阻塞队列中等待的时间。每等待一个时间片,waittime+1,当等待时间到(即waittime > blocktime)的时候,则将该进程插入到就绪队列中。
每个时间片运行后,在更新进程状态时,都将其现在的状态记录到rec中。
下面先对本程序中涉及的函数进行简单解释(除了main()函数在程序的最后,其他函数按照出现的先后顺序介绍)。
主函数——main():初始化cpu,就绪队列和阻塞队列。主要工作进行进程的调度,每一个时间片后,调用函数进行cpu,就绪队列,阻塞队列中进程的状态更新,该时间片后,对每个进程状态进行打印。
就绪队列的函数分析——ready_push(),ready_pop(),ready_updata(),ready_work()四个函数。
分析:
ready_push()函数,作用:将新的进程按照优先级大小插入就绪队列,保证队列按优先级大小呈递减状态。
ready_pop()函数,作用:将就绪队列中优先级最大的进程弹出队列,由于就绪队列中是按优先级大小排列的,所以也是弹出第一个就绪进程。
ready_updata()函数,作用:每个时间片后,更新就绪队列中进程的优先级。每过一个时间片段后,就绪队列中每个进程的优先级+1。
ready_work()函数,作用:按照优先级打印就绪队列中的进程id,如果就绪队列中没有进程那就打印为NULL。并且记录经过一个时间片后就绪队列中每个进程的状态RECORD[pro->id]。
阻塞队列的函数分析——block_push(),block_pop(),block_updata(),block_work()四个函数。
block_push()函数,作用:将新的进程按照blocktime的大小插入阻塞队列中,保证队列按阻塞时间大小呈递增的状态。
block_pop()函数,作用:取出阻塞队列的第一个进程。
block_updata()函数,作用:每个时间片后,更新阻塞队列中进程的等待时间,每过一个时间片,阻塞队列中每个进程的等待时间加一。如果进程的阻塞时间等于等待时间,那么将该进程放到就绪队列中。
block_work()函数,作用:打印阻塞队列中进程的id,如果阻塞队列中没有进程那就打印NULL,并且记录经过一个时间片后,就绪队列中每个进程的状态。
关于cpu的函数分析——cpu_work()
cpu_work()函数,作用打印cpu上进程的id,更新cpu上进程的状态,priority-3; alltime-1;cputime+1;并且记录经过一个时间片后,cpu上进程的状态。
init()函数,作用:根据给的原始数据对cpu,就绪队列,阻塞队列进行初始化。
print_table()函数,作用:每个时间片后,按照规格打印出每个进程的状态。
由于代码是使用纯c语言实现的,而且构造了双向链表故代码长了点。
源代码:
#include <stdio.h>
#include <stdlib.h>
#define N 5
enum State{Ready,Run,Block,Finish};
struct PCB //数据结构
{
intid;
intpriority;
intcputime;
intalltime;
intstartblock;//在cpu中能运行的时间
intblocktime;//阻塞了多久后,进入就绪队列
intwaittime;//*在阻塞队列中等待的时间
Statestate;
PCB*next;
PCB*pre;
}*ready_pro,*block_pro,*ready_tail,*block_tail;//就绪,阻塞队列,记录其头指针,
int ready_num,block_num;//就绪,运行,阻塞队列中进程的数量。
PCB record[N];
//原始数据
int id[] = {0,1,2,3,4};
int priority[] = {9,38,30,29,0};
int cputime[] = {0,0,0,0,0};
int alltime[] = {3,3,6,3,4};
int startblock[] = {2,-1,-1,-1,-1};
int blocktime[] = {3,0,0,0,0};
State state[] ={Ready,Ready,Ready,Ready,Ready};
//将新的进程插入到就绪队列中
//用插入排序的方法,保证了就绪队列的值是按照大小排序的,
void ready_push(PCB* pro)
{
pro->state= Ready;
if(!ready_num)//如果是就绪队列为空,则放在头指针的位置,尾指针也赋值为pro
{
ready_pro= pro;
ready_tail= pro;
}
else
{
PCB*this_pro = ready_pro;
while(this_pro!= NULL)//插入的进程和就绪队列中的进程进行比较,插入到合适的位置
{
if(this_pro->priority> pro->priority)//如果当前进程的优先级高则和下一个进程比较
this_pro= this_pro->next;
else//如果当前进程的优先级比pro低,则插在当前进程前面
{
if(this_pro== ready_pro)//如果是头指针则要改ready_pro的值
{
pro->next= this_pro;
this_pro->pre= pro;
ready_pro= pro;
}
else//如果不是头指针则,插入队列中
{
pro->next= this_pro;
pro->pre= this_pro->pre;
this_pro->pre->next= pro;
this_pro->pre= pro;
}
break;//插入后退出循环
}
}
if(this_pro== NULL)//如果pro的优先级最小则插到队伍的最后
{
ready_tail->next= pro;
pro->pre= ready_tail;
ready_tail= pro;//把ready_tail赋值为pro;
}
}
ready_num++;
}
PCB* ready_pop()//就绪进程出队,将优先级最高的进程pop出去
{
PCB*max_pro;
//优先级最高的进程就是第一个进程
max_pro= ready_pro;
ready_pro= ready_pro->next;
if(ready_pro== NULL)//如果就绪队列出队后为空,则尾指针也需要赋值为NULL
ready_tail= NULL;
else//否则就绪队列头指针的前驱为空
{
ready_pro->pre= NULL;
max_pro->next= NULL;
}
ready_num--;
returnmax_pro;
}
void ready_updata()//每个时刻就绪队列中进程优先级的更新
{
PCB*pro = ready_pro;
while(pro!= NULL)
{
pro->priority++;
pro= pro->next;
}
}
void ready_work()
{
printf("READY_QUEUE:");
PCB*pro = ready_pro;
if(pro== NULL)
printf("NULL");
while(pro!= NULL)
{
printf("->%d",pro->id);
record[pro->id].id= pro->id;
record[pro->id].priority= pro->priority;
record[pro->id].cputime= pro->cputime;
record[pro->id].alltime= pro->alltime;
record[pro->id].startblock= pro->startblock;
record[pro->id].blocktime= pro->blocktime;
record[pro->id].state= pro->state;
pro= pro->next;
}
printf("\n");
}
void block_push(PCB* pro)//进入阻塞队列
{
block_num++;
pro->state= Block;
if(block_pro== NULL)//如果是阻塞队列空,则加入放在第一位
{
pro->next= NULL;
pro->pre= NULL;
block_pro= pro;
block_tail= pro;
}
else//如果非空,插入排序,则按照所需要的时间长短放在阻塞队列中,时间越短越靠前,
{
PCB*this_pro = block_pro;
while(this_pro!= NULL)
{
if(this_pro->blocktime< pro->blocktime)//如果当前进程的阻塞时间小于pro则pro与下一个比较
this_pro= this_pro->next;
else
{
if(this_pro== block_pro)//如果是头指针则要改block_pro的值
{
pro->next= this_pro;
pro->pre= NULL;
this_pro->pre= pro;
block_pro= pro;
}
else//如果不是头指针则,插入队列中
{
pro->next= this_pro;
pro->pre= this_pro->pre;
this_pro->pre->next= pro;
this_pro->pre= pro;
}
break;//插入后退出循环
}
if(this_pro== NULL)//如果在最后则修改尾指针
{
block_tail->next= pro;
pro->pre= block_tail;
block_tail= pro;
}
}
}
}
PCB* block_pop()//取阻塞队列的队首
{
PCB*pro;
pro= block_pro;
block_num--;
if(!block_num)//只有一个值
{
block_pro= NULL;
block_tail= NULL;
}
else//不止一个值
{
block_pro= block_pro->next;
block_pro->pre= NULL;
}
pro->next= NULL;
returnpro;
}
void block_updata()
{
PCB*pro = block_pro;
while(pro!= NULL)
{
pro->waittime++;
//如果等待时间大于阻塞时间,则将进程放到就绪队列中
if(pro->waittime> pro->blocktime)//如果等待时间大于阻塞时间,则将进程放到就绪队列中
{
PCB*process = pro;
process->priority--;//先运行阻塞队列,需要减去1,在就绪队列中加回
if(process== block_pro)//如果是在队首
{
process= block_pop();//取出队首元素
pro= block_pro;//下一个需要判断的pro就等于队首元素
}
elseif(process == block_tail)//如果在队尾
{
block_tail= block_tail->pre;
process->pre= NULL;
process->waittime= 0;
pro= NULL;
}
else//如果在队伍中间
{
pro->pre->next= pro->next;
pro->next->pre= pro->pre;
pro= pro->next;
process->pre= NULL;
process->next= NULL;
process->waittime= 0;
}
ready_push(process);
}
else
pro= pro->next;
}
}
void block_work()//打印阻塞队列的信息
{
printf("BLOCK_QUEUE:");
PCB*pro = block_pro;
if(pro== NULL)
printf("NULL");
while(pro!= NULL)
{
printf("->%d",pro->id);
record[pro->id].id= pro->id;
record[pro->id].priority= pro->priority;
record[pro->id].cputime= pro->cputime;
record[pro->id].alltime= pro->alltime;
record[pro->id].startblock= pro->startblock;
record[pro->id].blocktime= pro->blocktime;
record[pro->id].state= pro->state;
pro= pro->next;
}
printf("\n");
}
void cpu_work(PCB *cpu_pro)
{
if(cpu_pro== NULL)
{
printf("RUNNINGPROG:NULL\n");
return;
}
if(!cpu_pro->alltime)
return;
cpu_pro->priority-= 3;
cpu_pro->alltime--;
cpu_pro->cputime++;
printf("RUNNINGPROG:%d\n",cpu_pro->id);
record[cpu_pro->id].id= cpu_pro->id;
record[cpu_pro->id].priority= cpu_pro->priority;
record[cpu_pro->id].cputime= cpu_pro->cputime;
record[cpu_pro->id].alltime= cpu_pro->alltime;
record[cpu_pro->id].startblock= cpu_pro->startblock;
record[cpu_pro->id].blocktime= cpu_pro->blocktime;
record[cpu_pro->id].state= cpu_pro->state;
}
void init()//初始化
{
//初始化就绪队列,运行队列和阻塞队列
block_pro= NULL;
block_tail= NULL;
block_num= 0;
ready_num= 0;
ready_pro= NULL;
ready_tail= NULL;
inti;
PCB*pro;
for(i= 0;i < N;i++)
{
pro= (PCB*)malloc(sizeof(PCB));
pro->id= id[i];
pro->priority= priority[i];
pro->cputime= cputime[i];
pro->alltime= alltime[i];
pro->startblock= startblock[i];
pro->blocktime= blocktime[i];
pro->waittime = 0;
pro->pre= NULL;
pro->next= NULL;
ready_push(pro);
}
}
void print_table()
{
inti;
printf("===========================================================\n");
printf("ID \t%d \t%d \t%d \t%d \t%d \n",
record[0].id,record[1].id,record[2].id,record[3].id,record[4].id);
printf("PRIORITY \t%d \t%d \t%d \t%d \t%d \n",
record[0].priority,record[1].priority,record[2].priority,record[3].priority,record[4].priority);
printf("CPUTIME \t%d \t%d \t%d \t%d \t%d \n",
record[0].cputime,record[1].cputime,record[2].cputime,record[3].cputime,record[4].cputime);
printf("ALLTIME \t%d \t%d \t%d \t%d \t%d \n",
record[0].alltime,record[1].alltime,record[2].alltime,record[3].alltime,record[4].alltime);
printf("STARTBLOCK\t%d \t%d \t%d \t%d \t%d \n",
record[0].startblock,record[1].startblock,record[2].startblock,record[3].startblock,record[4].startblock);
printf("BLOCKTIME\t%d \t%d \t%d \t%d \t%d \n",
record[0].blocktime,record[1].blocktime,record[2].blocktime,record[3].blocktime,record[4].blocktime);
printf("STATE \t");
for(i= 0;i < N;i++)
{
if(record[i].state== Run)
printf("RUN \t");
elseif(record[i].state == Ready)
printf("READY \t");
elseif(record[i].state == Finish)
printf("FINISH\t");
elseif(record[i].state == Block)
printf("BLOCK \t");
}
printf("\n");
}
int main()
{
init();//初始化;
PCB*cpu_pro = NULL;
intcpu_num = 0;
inttimes = 0;
inti = 0;
printf("第%d个时间片后:\n",times);
cpu_work(cpu_pro);
ready_work();
block_work();
print_table();
while(1)
{
//如果三个队列中都没有进程则推出调用
if(!ready_num&&!block_num&&!cpu_num)
break;
if(!cpu_num)//如果cpu空闲则调用一个就绪队列中的进程
{
if(ready_num> 0)//如果就绪队列非空,则调出优先级最高的进程
{
cpu_pro= ready_pop();
}
else//如果就绪队列为空,则调出阻塞队列的第一个值
{
cpu_pro= block_pop();
}
cpu_num= 1;
cpu_pro->state= Run;
cpu_pro->cputime= 0;//开始运行的时间为0;
}
times++;
printf("\n第%d个时间片后:\n",times);
cpu_work(cpu_pro);
//如果alltime == 0,进程结束,释放内存
if(!cpu_pro->alltime)
{
cpu_pro->state= Finish;
record[cpu_pro->id].id= cpu_pro->id;
record[cpu_pro->id].priority= cpu_pro->priority;
record[cpu_pro->id].cputime= cpu_pro->cputime;
record[cpu_pro->id].alltime= cpu_pro->alltime;
record[cpu_pro->id].startblock= cpu_pro->startblock;
record[cpu_pro->id].blocktime= cpu_pro->blocktime;
record[cpu_pro->id].state= cpu_pro->state;
free(cpu_pro);
cpu_num= 0;
}
//更新阻塞和就绪队列中的信息
block_updata();
ready_updata();
//显示就绪、阻塞队列的信息
ready_work();
block_work();
print_table();
//如果在cpu上运行时间达到了startblock并且alltime还不为0,则放到阻塞队列中,
if(cpu_pro->cputime== cpu_pro->startblock&&cpu_pro->alltime > 0)
{
//在放入阻塞队列中;
cpu_pro->cputime= 0;
cpu_pro->waittime= 0;
block_push(cpu_pro);
cpu_num= 0;
}
}
printf("\n模拟进程调度算法结束!\n");
return0;
}
- 操作系统——使用动态优先权的进程调度算法的模拟
- 操作系统-使用动态优先权的进程的调度算法的模拟
- 使用动态优先权的进程调度算法的模拟
- 使用动态优先权的进程调度算法的模拟
- OS 使用动态优先权的进程调度
- 动态优先权进程调度算法
- 操作系统——动态高优先权优先调度算法(无到达时间)
- 操作系统--动态高优先权算法的Java实现
- 用C++模拟操作系统进程调度的几种算法
- FCFS,高优先权算法进程调度程序模拟
- 操作系统的进程调度算法
- 操作系统的进程调度算法
- 模拟操作系统进程调度算法
- 处理机调度模拟(优先权调度算法)
- 常用的操作系统的进程调度算法
- 几个常用的操作系统进程调度算法
- 几个常用的操作系统进程调度算法
- 操作系统---OS的进程调度算法
- scrum项目管理
- HDU2492 Ping pong 树状数组求逆序数
- 股票接口
- 字典树
- 善用Condition设置,解决Source Insight中的parse too complex问题
- 操作系统——使用动态优先权的进程调度算法的模拟
- java 并发编程读书笔记
- java自学之路-----线程(3) String
- 设计模式入门之迭代器模式Iterator
- 【think in java】wait和sleep的区别
- Java 输出整数的二进制
- struts2 验证
- Openstack当中xvpvnc的连接方法
- exit,_exit,_Exit的区别