设计一:我假装这是进程调度算法

1 设计内容 
进程管理是操作系统中的重要功能,用来创建进程、撤消进程、实现进程状态转换,它提供了在可运行的进程之间复用CPU的方法。在进程管理中,进程调度是核心,因为在采用多道程序设计的系统中,往往有若干个进程同时处于就绪状态,当就绪进程个数大于处理器数目时,就必须依照某种策略决定哪些进程优先占用处理器。本设计模拟在单处理器情况下的进程调度,加深对进程运行状态和进程调度过程、调度算法的理解。
设计程序模拟单处理机系统中的进程调度算法,实现动态优先权进程调度算法, 对N个进程采用动态优先权算法的进程调度。
2 分析设计
每个用来标识进程的进程控制块PCB,包括以下信息:进程标识数ID,进程优先数PRIORITY,进程已占用的CPU时间CPUTIME,进程还需占用的CPU时间NEEDTIME,进程状态STATE等。
进场状态STATE有三种:就绪等待W(wait),运行R(run)以及完成F(finish)。
2.1 算法原理
动态优先级在调度进程刚进入系统时,就先安照优先级数的大小排列在就绪队列中,当运行队列里没有进程时,把就绪队列的第一个(即优先级最高)的进程调入运行,运行一个时间段后,如果没有达到所需时间则把它的优先级数减三再按照优先级高低再次插入就绪队列,且就绪队列的所有进程优先级数都加一,如果达到所需时间则插入完成队列。
单CPU系统的运行队列同一时间只能存在一个进程。
2.2 程序结构
该算法以优先级调度函数prio()为主,插入就绪队列函数insert()和创建函数create()为辅,再由主函数main()统筹完成。
优先级调度函数prio():先判断就绪队列是否为空,不空则将就绪队列的第一个进程投入运行,时间片到后将就绪状态的进程优先级数全部加1,判断运行队列进程是否达到所需时间,达到则把该进程调到完成队列,未达到则插入把该进程优先级数减三再调用插入函数insert()把该进程插入就绪队列;就绪队列空则结束。
插入函数insert():判断就绪队列是否空,空则把就绪队列头指针指向需要插入的PCB;不空则按照优先级数大小递减插入就绪队列。
创建函数create():选择输入进程个数,再输入参数,默认为就绪状态,调用插入函数insert()把进程插入就绪队列。
2.3 数据结构
定义PCB结构体:
typedef struct node{
int ID; //进程标识数
int PRIORITY; //进程优先数
int CPUTIME; //已占用的CPU时间
int NEEDTIME; //还需占用CPU的时间
char STATE; //进程状态
struct node * next; //链指针
}PCB;
定义各头指针:
PCB * READY=NULL; //就绪队列头指针
PCB * FINISH=NULL; //完成队列头指针
PCB * RUN=NULL; //运行队列头指针
2.4 程序流程图
在这里插入图片描述
2.5 关键代码
插入就绪队列函数insert():
void insert(PCB q){ //插入函数 把PCB插入就绪队列
if(READY!=NULL){ //就绪队列不空则插入
PCB p,p0;
p=READY; //就绪队列头指针
p0=p; //该指针作为p的前置指针 因为不是双链表 接上一个结点有点麻烦
while(p!=NULL){
if(p->PRIORITY>=q->PRIORITY){
p0=p;
p=p->next;
}
else{
break;
}
}
if(p0p){ //如果相等即说明待插入的PCB优先级最高,把它放入就绪队列的第一位
q->next=READY;
READY=q;
}
else{ //反之说明待插入的PCB优先级数比p0小,比p大
q->next=p;
p0->next=q;
}
}
else{
q->next=READY; //就绪队列空则创建就绪队列的第一个PCB
READY=q;
}
q->STATE=‘W’;
}
创建函数create():
void create(){ //创建函数 创建一组PCB
int needtime;
int id;
int priority;
int n;
cout<<“请选择输入进程数目:”<<endl;
cin>>n;
PCB p;
for(int i=1;i<=n;i++){
cout<<“请输入第”<<i<<“占用CPU所需时间和进程初始优先级数:”<<endl;
cin>>needtime>>priority;
p=(PCB
)malloc(sizeof(PCB)); //申请空间
p->ID=i;
p->NEEDTIME=needtime;
p->PRIORITY=priority;
p->CPUTIME=0;
p->STATE=‘W’; //新进的进程默认为就绪状态
insert§; //调用插入函数insert()插入
TAIL[i]=p; //记录该PCB
}
}
动态优先权调度算法prio():
void prio(){ //动态优先权调度算法(核心)
PCB p;
cout<<" 动态优先权算法模拟进程调用过程:"<<endl;
cout<<"
***************************************************************************"<<endl;
printT();
while(READY!=NULL){ //判断就绪队列是否为空
RUN=READY; //将就绪队列的第一个进程投入运行
READY=READY->next;
RUN->STATE=‘R’;
p=READY;
printT();
RUN->CPUTIME+=1; //时间片到
RUN->NEEDTIME-=1;
while(p!=NULL){ //就绪状态的进程优先级数全部加1
p->PRIORITY+=1;
p=p->next;
}
if(RUN->NEEDTIME0){ //判断运行队列进程是否达到所需时间 达到
RUN->next=FINISH;
FINISH=RUN;
RUN->STATE=‘F’;
RUN=NULL;
}
else{
RUN->PRIORITY-=3; //未达到
insert(RUN);
RUN=NULL;
}
printT();
}
}
3 开发环境
Windows 7 + VC++6.0
4 运行结果及分析
输入三个进程,时间和优先级数分别为:
5 6
3 2
4 7
运行结果见图4.1和图4.2
在这里插入图片描述
图4.1
在这里插入图片描述
图4.2
可以看到:就绪队列的优先级数最大的被调入运行队列,优先级数相同的按照先来先服务调度。完成顺序是3->2->1,符合动态优先权算法的调用顺序。
5 心得体会
这次为期三周的实习,真真正正让我体会到了代码的无限乐趣!
原本打算用这学期新学的java来实现进程调度,但是不够熟悉,只好还是用更熟悉的c语言来打。经过不断地磨合修改代码,从课本学习对照,上网查资料,第一周已经过了两天,而我得出了我的进程调度的简化版本,真的很满足当时。但是陆陆续续出了很多的问题却找不到解决办法,和小伙伴一起探讨了一段时间,修改了很多bug,最终把界面优化美化后看起来很舒服。
在实习期间,通过和小伙伴的讨论和上网学习,真正的学到了很多东西。从刚开始的为了完成任务而学习变成了因为兴趣而学习,养成了很好的学习习惯。这次实习令人很满足,也很令人回味。

参考文献
1.胡元义,黑新宏等.《操作系统原理》.北京:电子工业出版社,2018.08:78-79
2.耿国华等.《数据结构(第二版)》.北京:高等教育出版社,2015.07(2018.02重印):47-57

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值