p=p->next;
}
}
这个函数是优先级调度算法程序的界面函数,主要为程序运行时能够直观的显示结果
voidinsert(PCB*p)
{
PCB*S1,*S2;
if(ready==NULL)//判断队列是否为空
{
p->next=NULL;
ready=p;//插入就绪队列
}else{
S1=ready;
S2=S1;
while(S1!
=NULL)
{
if(S1->pri>=p->pri)//判断优先级大小
{
S2=S1;//置换位置
S1=S1->next;
}else{
break;//跳出循环
}
}
if(S2->pri>=p->pri)
{
S2->next=p;
p->next=S1;
}else{
p->next=ready;
ready=p;
}
}
}
这是程序优先级排序的函数,也是优先级调度算法的核心思想函数,对程序的优先级通过指针进行排序,再将队首的程序调入运行队列,通过置换的方法,将运行队列队首即占用CPU的程序调入就绪队列,如此循环直至所有程序终止为止。
莫友芝编写的代码:
voidpriority()
{
run=ready;
ready=ready->next;
run->state="运行";
while(run!
=NULL)/*当运行队列不空时,有进程正在运行*/
{
Dtime(3);//调用延时函数,延时3秒
run->runtime=run->runtime+1;//运行时间+1
run->needOftime=run->needOftime-1;//完成需要时间-1
run->pri=run->pri-1;/*//优先级-1每运行一次优先数降低1个单位*/
if(run->needOftime==0)/*如所需时间为0将其插入完成队列*/
{
run->state="完成";
run->next=finish;
finish=run;
run=NULL;/*运行队列头指针为空*/
if(ready!
=NULL)/*如就绪队列不空*/
{
run=ready;
run->state="运行";
ready=ready->next;
}
}elseif((ready!
=NULL)&&(run->pripri)){//就绪队列不为空,就绪队列队首优先级大于运行队列队首
run->state="就绪";
insert(run);//运行中的进程重新比较优先级大小
run=ready;//对队列队首的进程调入CPU
run->state="运行";
ready=ready->next;
}
Prinft();/*输出进程PCB信息*/
}
}
这是程序运行时的实时程序,通过循环的方法在程序等候3秒后,调用德新设计的优先级排序算法,进行排序。
voidCTProcessOfPri()//创建进程
{
PCB*Node;
stringc[5]={"P1","P2","P3","P4","P5"};//模拟设计5条进程
srand((int)time(0));//设置随机种子
for(intj=0;j<5;j++)
{
Node=newPCB;
if(Node==NULL)
{
return;
}else{
Node->procname=c[j];//为进程名赋值
Node->needOftime=1+(int)(15.0*rand()/(RAND_MAX+1.0));//为进程随机分配占用CPU时间.
Node->runtime=0;//为运行时间赋值
Node->state="就绪";//设置初始状态为“就绪”状态
Node->pri=1+(int)(20.0*rand()/(RAND_MAX+1.0));//为进程随机分配优先数.
}
insert(Node);//出入就行队列
}
}
随机创建5个模拟程序,为其赋上初值后,调用优先级排序函数,进行第一次排序
张德华编写的程序代码:
voidinsert(PCB*p){//时间片插入函数
if(start->next==NULL){
PCB*q=start;
if(p->Arrive_timeArrive_time){
start=p;
p->next=q;
q->next=NULL;
end=q;
}else{
q->next=p;
p->next=NULL;
end=p;
}
}else{
PCB*q=start;
PCB*s=start->next;
while(s!
=NULL){
if(q->Arrive_time>p->Arrive_time){
p->next=q;
start=p;
return;
}else{
if(s->Arrive_time>p->Arrive_time){
q->next=p;
p->next=s;
return;
}else{
q=q->next;
s=s->next;
}
}
}
s->next=p;
end=p;
}
}
这个是时间片插入函数,也是轮转调度模拟程序的核心函数,首先对到达时间进行排序,将队首调入CPU后,运行时间片的时间后,调入就绪队列队尾,等候下一次的资源.
voidfirstin(){//将就绪队列的第一个进程放入运行队列
run=start;
run->State='W';//改变其状态
start=start->next;
}
模拟占用CPU的函数
voidshow(PCB*p)//输出函数
{
cout<<"进程名"<<"\t"<<"到达时间"<<"\t"<<"剩余时间"<<"\t"<<"状态\n";//
if(run!
=NULL)//如果运行指针不为空,就输出当前正在运行的进程的PCB
{cout<name<<"\t"<Arrive_time<<"\t""\t"<Need_time<<"\t""\t"<State<<"\n\n";
}
}
这是一个程序初始值的输出函数,验证输入的各程序的初始值是否是预期输入
袁马龙编写的代码:
voidcreate()//时间片算法创建进程函数
{
cout<<"请输入所需要运行的进程个数:
";
cin>>N;
PCB*p;
intTime_piece;
start=NULL;//就绪队列头指针
finish=NULL;//完成队列头指针
run=NULL;//运行队列指针
cout<<"请输入时间片长度:
";
cin>>Time_piece;
for(inti=1;i<=N;i++){//输入进程名字和所需时间,创建进程的PCB
p=(PCB*)malloc(sizeof(PCB));
cout<<"请输入第"<
";
cin>>p->name;
cout<<"预计运行的时间:
";
cin>>p->Need_time;
cout<<"到达时间:
";
cin>>p->Arrive_time;
Cpu_time=0;
p->Count=0;//计数器
p->State='W';//进程的初始状态设为就绪'W'
p->Time_piece=Time_piece;//时间片的初始值
if(start!
=NULL){
insert(p);//若就绪队列不为空,将其插入就绪队列
}else{//创建就绪队列的第一个PCB
p->next=start;
start=p;//头指针
end=p;//尾指针
}
}
cout<(W为就绪状态,F为终止状态)\n";
cout<<"*********************************************************\n";
run=start;//将就绪队列的第一个进程投入运行
start=start->next;
run->State='W';
}
这是一个设置程序运行初始的条件函数,如需要运行的程序数目,程序名称,运行时间等,在调用德华设计的排序函数进行排序,调入队列中
voidroundrobin(){//时间片算法函数
intm=0;
while(run!
=NULL){
if(run->Arrive_time>Cpu_time){
Cpu_time=Cpu_time+1;//每运行一次cputime加一
}else{
if(m==0){
cout<<"~~~~~~~~~~~~~~~~~~~~~~~~进程"<name<<"开始~~~~~~~~~~~~~~~~~~~~~~~\n\n";
m++;
}
run->Need_time=run->Need_time-1;//每运行一次needtime减一
if(run->Need_time!
=0)
show(run);
Cpu_time=Cpu_time+1;//每运行一次cputime加一
run->Count=run->Count+1;//每运行一次计数器count加一
if(run->Need_time==0){//若运行完后
run->next=finish;
finish=run;//将其插入完成队列头部
run->State='F';//将其状态改为完成态"F"
show(run);
cout<<"~~~~~~~~~~~~~~~~~~~~~~~~进程"<name<<"结束~~~~~~~~~~~~~~~~~~~~~~~\n\n";
run=NULL;//将运行队列清空
if(start!
=NULL){
firstin();//若就绪对列不空,将第一个进程投入运行
cout<<"~~~~~~~~~~~~~~~~~~~~~~~~进程"<name<<"开始~~~~~~~~~~~~~~~~~~~~~~~\n\n";
}
}else{
if(run->Count==run->Time_piece){//如果时间片到
run->Count=0;//计数器置0
if(start!
=NULL){//若就绪队列不空
run->State='W';
insert2(run);//将进程插入到就绪队列中等待轮转
firstin();//将就绪队列的第一个进程投入运行
cout<<"~~~~~~~~~~~~~~~~~~~~~~~~进程"<name<<"开始~~~~~~~~~~~~~~~~~~~~~~~\n\n";
}
}
}
}
}
cout<<"*********************************************************\n";}
这是一个程序运行结果的输出函数,输出程序的结果内容,在什么时间段完成,什么时间段到达,以及程序的状态等信息
5、设计过程
进程是进程实体的运行过程是系统进行资源分配和调度的一个独立单位。
另有一种定义方法是“程序在处理器上的执行”。
为了模拟的方便,本设计采用这种定义。
简单地说,进程包括三种状态:
运行状态、就绪状态、完成状态
优先级调度算法:
按照进程的优先级大小来调度,是高优先级进程得到优先的处理的调度策略,可使用非抢占或可抢占两种策略
用C++模拟设计一个进程模拟类classPCB{
public:
stringprocname;//进程名
intpri;//进程优先数
stringstate;//进程状态
intruntime;//进程已运行CPU时间
intneedOftime;//还需要时间
PCB*next;//指针
};
来记录进程的基本信息,如进程名称,优先级,进程状态,进程运行时间,进程所需时间
再设计模拟进程所需要的各种算法,运行调试结果
时间片轮转调度算法:
是一种最古老,最简单,最公平且使用最广的算法。
每个进程被分配一时间段,称作它的时间片,即该进程允许运行的时间.如果在时间片结束时进程还在运行,则CPU将被剥夺并分配给另一个进程。
如果进程在时间片结束前阻塞或结束,则CPU当即进行切换。
调度程序所要做的就是维护一张就绪进程列表,当进程用完它的时间片后,它被移到队列的末尾.
用C语言模拟设计一个类typedefstructnode{
charname[10];//进程名
intTime_piece;//时间片
intNeed_time;//还需要的时间
intCount;//计数器
charState;//进程的状态
structnode*next;//链指针
intArrive_time;//到达时间
}PCB;
用这个类根据算法的基本思想来设计程序,模拟算法的运行情况
优先级抢占式调度算法:
(过程图)
时间片轮转调度算法:
(过程图)
六、运行结果
优先级抢占式:
时间片轮转调度算法:
七、结果分析
程序的结果很好体现的进程运行的优先级处理,对于优先级高的程序,采用抢占式,分配程序CPU使用,优先级较低的进入就绪队列等待CPU资源
而时间片轮转调度算法也很好的实行预期情况,程序进入CPU运行时间片长度的时间后,调入就绪队列队尾,完成则进入完成队列。
队首调入CPU,占用资源,循环直到所有程序都进入就绪队列.
八、设计总结
1.设计基本实现了我们小组想要的功能和预测情况,虽然中间关于指针的使用我们做了许多的调试,但是我们还是做出来了。
2.然后就是进程算法的调用过程和知识,发现自己对知识的遗忘程度有点大,边做边补,实验结束的会后发现自己的知识巩固了不少。
对操作系统的了解也更加深入了。
3.和队友合作然后团队意识有一定的提高
附录:
优先级抢占式调度算法:
///////////////////////////优先级抢占式线程调度算法/////////////////////////
#include"stdlib.h"
#include
#include
#include
usingnamespacestd;
intn;
classPCB
{
public:
stringprocname;//进程名
intpri;//进程优先数
stringstate;//进程状态
intruntime;//进程已运行CPU时间
intneedOftime;//还需要时间
PCB*next;//指针
};
PCB*run=NULL;//运行队列头指针
PCB*ready=NULL;//就绪队列头指针
PCB*finish=NULL;//完成队列头指针
/////////////////////////////////延时函数,模拟CPU占用时间/////////////////////////////
voidDtime(intt){//此代码块参考网上资料
time_tcurrent_time;
time_tstart_time;
time(&start_time);
do{
time(¤t_time);
}while((current_time-start_time)}
//////////////////////////////输出函数,调整输出界面//////////////////////////////////////
voidPrinft(){
PCB*p;
system("cls");//清屏
p=run;//运行队列
if(p!
=NULL)
{
p->next=NULL;
}
cout<<"当前正在运行的进程:
"<cout<<"进程名称"<<"\t"<<"优先数"<<"\t"<<"还需要时间"<<"\t"<<"已运行时间"<<"\t"<<"状态:
"<while(p!
=NULL)
{
cout<procname<<"\t\t"<pri<<"\t"<needOftime<<"\t\t"<runtime<<"\t\t"<state<p=p->next;
}
cout<cout<<"当前的就绪队列:
"<"<p=ready;