操作系统的进程调度实验报告.docx
《操作系统的进程调度实验报告.docx》由会员分享,可在线阅读,更多相关《操作系统的进程调度实验报告.docx(19页珍藏版)》请在冰豆网上搜索。
操作系统的进程调度实验报告
《计算机操作系统2》实验报告
实验一题目:
操作系统的进程调度
姓名:
学号:
12125807实验日期:
2014.12
实验要求:
1.设计一个有n个进程工行的进程调度程序。
每个进程由一个进程控制块(PCB)表示。
进程控制块通常应包含下述信息:
进程名、进程优先数、进程需要运行的时间、占用CPU的时间以及进程的状态等,且可按调度算法的不同而增删。
2.调度程序应包含2~3种不同的调度算法,运行时可任意选一种,以利于各种算法的分析比较。
3.系统应能显示或打印各进程状态和参数的变化情况,便于观察诸进程的调度过程
实验目的:
1.进程是操作系统最重要的概念之一,进程调度又是操作系统核心的主要内容。
本实习要求学生独立地用高级语言编写和调试一个简单的进程调度程序。
调度算法可任意选择或自行设计。
例如,简单轮转法和优先数法等。
本实习可加深对于进程调度和各种调度算法的理解。
实验内容:
1.编制和调试示例给出的进程调度程序,并使其投入运行。
2.自行设计或改写一个进程调度程序,在相应机器上调试和运行该程序,其功能应该不亚于示例。
3.直观地评测各种调度算法的性能。
示例:
1.题目
本程序可选用优先数法或简单轮转法对五个进程进行调度。
每个进程处于运行R(run)、就绪W(wait)和完成F(finish)三种状态之一,并假设起始状态都是就绪状态W。
为了便于处理,程序进程的运行时间以时间片为单位计算。
各进程的优先数或轮转时间片数、以及进程需要运行的时间片数,均由伪随机数发生器产生。
进程控制块结构如下:
PCB
进程标识数
链指针
优先数/轮转时间片数
占用CPU时间片数
进程所需时间片数
进程状态
Ø进程控制块链结构如下:
其中:
RUN—当前运行进程指针;
HEAD—进程就绪链链首指针;
TAID—进程就绪链链尾指针。
2.算法与框图
(1)优先数法。
进程就绪链按优先数大小从高到低排列,链首进程首先投入运行。
每过一个时间片,运行进程所需运行的时间片数减1,说明它已运行了一个时间片,优先数也减3,理由是该进程如果在一个时间片中完成不了,优先级应该降低一级。
接着比较现行进程和就绪链链首进程的优先数,如果仍是现行进程高或者相同,就让现行进程继续进行,否则,调度就绪链链首进程投入运行。
原运行进程再按其优先数大小插入就绪链,且改变它们对应的进程状态,直至所有进程都运行完各自的时间片数。
(2)简单轮转法。
进程就绪链按各进程进入的先后次序排列,进程每次占用处理机的轮转时间按其重要程度登入进程控制块中的轮转时间片数记录项(相当于优先数法的优先数记录项位置)。
每过一个时间片,运行进程占用处理机的时间片数加1,然后比较占用处理机的时间片数是否与该进程的轮转时间片数相等,若相等说明已到达轮转时间,应将现运行进程排到就绪链末尾,调度链首进程占用处理机,且改变它们的进程状态,直至所有进程完成各自的时间片。
(3)程序框图如下图所示。
实验步骤
建立每个进程的数据结构,也就是计算机中的PCB。
PCB有以下一些要素构成。
①进程ID:
用来唯一标识每个进程(本次实验中随机给出)
②priority:
这个属性就在P算法中有用,数字越大优先级越高,每次执行后优先级减3,以此来照顾优先级略小的小作业。
③cputime:
表示已经占用的cpu时间资源。
④needtime:
表示距离完成还需要的cpu时间资源,needtime和cputime此消彼长
(cputime+needtime=初始的needtime)
⑤round:
这个属性就在RR算法中有用,表示该进程“已经轮到了多少次”
⑥state:
表示进程的三个状态:
就绪,工作,完成
⑦各个进程通过链表链接,指针指向下一个进程的pcb表格
实验运行结果:
P算法:
输入进程数4以后,由srand函数随机给出各个进程的needtime和priority。
之后寻找priority最大的优先做,做的过程就是将cputime=cputime+1,needtime=needtime-1做完之后将priority=priority-3,再次开始寻找新的高优先级进程。
RR算法:
在输入了进程数3,时间片大小3之后,由srand()函数给出每个函数的needtime。
然后从位置靠前的进程开始,工作3个单位时间的cputime,之后cputime=cputime+3,needtime=needtime-3,若needtime小于3,则置0.,round=round+1.由于同一个时间片只能分配给一个进程,不能分割,因此每个cputime总是时间片大小的整数倍。
实验感想:
这个实验在编程上的要求很高,由于在数据结构语法上的不扎实,在实现的时候出处碰壁。
在老师给的参考的帮助下,完成了这个实验。
在实现的过程中,对于书上概念的理解更加深入。
例如pcb在内存中利用链表的数据结构链接,pcb中也有各种进程相关的信息。
在模拟真机进程调度的同时,对每一个进程的每一步变化都很清晰。
在比较这两个算法时,如果时间片过大,就会浪费时间cpu时间(因为在进程的最后可能只需要时间片的前面一小部分),造成资源浪费。
在P算法中,优先级每次减少的数也很关键,若是过小了,不能达到照顾低优先级的小进程的作用,若是过大了,优先级这个属性的作用就不明显了。
具体的取值还要参考优先数的大小和进程needtime的大小。
思考题:
(1)示例中的程序,没有使用指针型(pointer)数据结构,如何用指针型结构改写本实例,使更能体现C语言的特性。
答:
将示例程序中的“下一个进程的进程号”把改为int*next;的数据类型,即:
structpcb{
intid;//进程号
int*next;//下一个进程的进程号
intpri;//进程优先数
intct;//占用CPU的时间片数
intat;//进程总共所需的时间片数
intstate;//进程状态(1.运行、2.就绪、3.完成)
};
(2)如何在程序中真实地模拟进程运行的时间片?
答:
通过建立一个time进行自增运算,从而真实地模拟时间片运行。
(3)如果增加进程的“等待”状态,即进程因请求输入输出等问题而挂起的状态,如何在程序中实现?
通过增加一个判断语句,if(有请求输入输出)——挂起程序,即时间片自增,但是进程需要运行的时间,还有优先级均不变。
若没有输入输出,则继续原来的操作。
实验源代码:
#include
#include
#include
#include
#include
#include
enumstate//进程的状态
{
Ready,
Working,
Finish
};
structpcb//PCB数据结构
{
intpid;
intpriority;
intcputime;
intneedtime;
intround;
stateprocess;
pcb*next;
};
inttimepiece;
pcb*get_process(){//优先数算法--输入进程个数
intproc;
pcb*q;
pcb*t;
pcb*p;
inti=0;
cout<<"InputProcessNumber(1-10):
";
cin>>proc;
while(proc<1||proc>10)
{
cout<"<";
cin>>proc;
}
//cout<!
!
\n\n";
getch();
srand((unsigned)time(NULL));//初始化随机数种子发生器
while(i{
q=(structpcb*)malloc(sizeof(pcb));
q->pid=rand()%10000;
q->needtime=rand()%10+1;
q->cputime=0;
q->priority=rand()%100;
q->process=Ready;
q->next=NULL;//利用随机数生成进程信息
if(i==0)
{
p=q;
t=q;
}
else
{
t->next=q;
t=q;
}//尾插法建立PCB节点
i++;
}//while
returnp;
}
voiddisplay(pcb*p)
{//优先数算法结果输出
cout<<"ProcessID"<<""<<"Cputime"<<""<<"Needtime"<<""<<"Priority"<<""<<"State"<while(p)
{
cout<<""<pid;
cout<<"\t\t";
cout<cputime;
cout<<"\t";
cout<needtime;
cout<<"\t";
if(p->needtime==0)
cout<<"Done";
else
cout<priority;
cout<<"\t\t";
switch(p->process){
caseReady:
cout<<"Ready"<caseWorking:
cout<<"\b\b->Working<-"<caseFinish:
cout<<"Finish"<}
p=p->next;
}
}
intprocess_finish(pcb*q)//判断是否所有进程都已完成,是则返回1
{
intbl=1;
while(bl&&q)
{
bl=bl&&q->needtime==0;
q=q->next;
}
returnbl;
}
voidcpuexe(pcb*q)
{//优先数算法模拟进程执行函数
pcb*t=q;
inttp=-1;
while(q)
{
if(q->process!
=Finish)
{//未完成的进程置Ready,完成的进程置Finish
q->process=Ready;
if(q->needtime==0)
{
q->process=Finish;
}
}
if(tppriority&&q->process!
=Finish)
{//找到下一个优先数最高且未完成的进程
tp=q->priority;
t=q;
}
q=q->next;
}
if(t->needtime!
=0)
{//修改正在执行的进程的信息,并置其状态为Working
t->priority-=3;
if(t->priority<0)t->priority=0;
t->needtime--;
t->process=Working;
t->cputime++;
}
}
voidpriority_cal()
{//优先数算法主控函数
pcb*p;
system("cls");
p=get_process();
intcpu=0;
charkey;
system("cls");
cout<<"CPUTime:
"<display(p);
cout<getch();
while(!
process_finish(p))
{//当不是所有进程都完成时不断执行进程并显示信息
cpu++;
cout<<"CPUTime:
"<cpuexe(p);
display(p);
cout<key=getch();
if(key=='q')exit(0);
}
printf("Allprocessesarefinished!
");
getch();
}
pcb*get_process_round()
{//时间片算法--输入进程个数及CPU时间片
intproc;
pcb*q;
pcb*t;
pcb*p;
inti=0;
cout<<"InputProcessNumber(1-10):
";
cin>>proc;
while(proc<1||proc>10){
cout<"<";
cin>>proc;
}
cout<<"CPUTimePiece(1-5)?
";
cin>>timepiece;
while(timepiece<1||timepiece>5){
cout<"<";
cin>>timepiece;
}
//cout<!
!
\n\n";
getch();
srand((unsigned)time(NULL));//初始化随机数种子发生器
while(iq=(structpcb*)malloc(sizeof(pcb));//利用随机数建立进程信息
q->pid=rand()%10000;
q->needtime=rand()%10+1;
q->cputime=0;
q->round=0;
q->process=Ready;
q->next=NULL;
if(i==0){//尾插法建立PCB节点
p=q;
t=q;
}
else{
t->next=q;
t=q;
}
i++;
}//while
returnp;
}
voidcpu_round(pcb*p,pcb*q){//时间片算法模拟进程执行函数
while(p){
if(p->needtime==0){//完成的进程置Finish,其它置Ready
p->process=Finish;
}
if(p->process==Working){
p->process=Ready;
}
p=p->next;
}
q->cputime+=timepiece;//修改正在执行进程的信息,并置其状态为Working
q->needtime-=timepiece;
if(q->needtime<0){
q->needtime=0;
}
q->round++;
q->process=Working;
}
pcb*get_next(pcb*k,pcb*head)
{//得到下一个应执行的进程
pcb*t;
t=k;
do
{
t=t->next;
}
while(t&&t->process==Finish);
if(t==NULL)
{
t=head;
while(t!
=k&&t->process==Finish)
{
t=t->next;
}
}
returnt;
}
voiddisplay_round(pcb*p){//时间片算法输出结果
cout<<"ProcessID"<<""<<"Cputime"<<""<<"Needtime"<<""<<"Round"<<""<<"State"<while(p){
cout<<""<pid;
cout<<"\t\t";
cout<cputime;
cout<<"\t";
cout<needtime;
cout<<"\t";
cout<round;
cout<<"\t";
switch(p->process){
caseReady:
cout<<"Ready"<caseWorking:
cout<<"\b\b->Working<-"<caseFinish:
cout<<"Finish"<}
p=p->next;
}
}
voidround_cal()
{
pcb*p;
pcb*r;
system("cls");
p=get_process_round();
intcpu=0;
charkey;
system("cls");
cout<<"CPUTime:
"<display_round(p);
cout<getch();
r=p;
while(!
process_finish(p))
{
cpu+=timepiece;
cpu_round(p,r);
r=get_next(r,p);
cout<<"CPUTime:
"<display_round(p);
cout<key=getch();
if(key=='q')exit(0);
}
}
voiddisplay_menu()
{
cout<<"1Priority"<cout<<"2RoundRobin"<cout<<"3Exit"<cout<<"Choice:
";
}
intmain()
{
charkey;
display_menu();
cin>>key;
switch(key)
{
case'1':
priority_cal();break;
case'2':
round_cal();break;
case'3':
exit(0);
}
return0;
}