用C语言模拟Linux操作系统下处理机调度实验报告Word下载.docx
《用C语言模拟Linux操作系统下处理机调度实验报告Word下载.docx》由会员分享,可在线阅读,更多相关《用C语言模拟Linux操作系统下处理机调度实验报告Word下载.docx(10页珍藏版)》请在冰豆网上搜索。
2、按时间片轮转法实现处理机调度:
1)每个进程用一个进程控制块PCB来代表,进程控制块包括进程名(进程的标识)、指针(把进程连成循环队列,用指针指出下一个进程的进程控制块首地址,最后一个进程中的指针指出第一个进程的进程控制块首地址)、已运行时间、状态(就绪、结束);
3)用指针把给定的进程按顺序排成循环队列,用另一标志单元记录轮到的进程;
4)每模拟运行一次进程,已运行时间加一;
5)进程运行一次后,把该进程控制块的指针值送到标志单元,以指示下一个轮到的进程。
若该进程要求运行时间≠已运行时间,未执行结束,待到下一轮再执行;
若要求运行时间=已运行时间,状态改为结束,退出队列;
6)若就绪队列不为空,重复步骤四和五;
3、程序设计:
1、优先数调度算法:
/*我的思路:
先主函数输入要进行调度的进程数,然后调用函数create(),把进程的信息输入,再调用函数insert(),把输入的函数按照优先数的大小排成链表,然后调用函数prio()实现优先数调度*/
#include<
stdio.h>
stdlib.h>
string.h>
typedefstructnode
{charname[10];
/*进程名*/
intprio;
/*优先数*/
intcputime;
/*占用cpu时间*/
intneedtime;
/*要求运行时间*/
charstate;
/*状态*/
structnode*next;
/*指针*/
}PCB;
PCB*ready,*run,*finish;
/*就绪执行结束指针*/
intN;
voidprt()/*输出函数,可以方便看到进程执行的演示*/
{
PCB*p;
printf("
NAMECPUTIMENEEDTIMEPRIORITYSTATUS\n"
);
if(run!
=NULL)printf("
%-10s%-10d%-10d%-10d%c\n"
run->
name,run->
cputime,run->
needtime,run->
prio,run->
state);
/*输出执行的进程的信息*/
p=ready;
while(p!
=NULL)
{printf("
p->
name,p->
cputime,p->
needtime,p->
prio,p->
/*输出就绪进程的信息*/
p=p->
next;
}
p=finish;
=NULL)
/*输出结束队列的信息*/
getchar();
}/*使用getchar()函数可以让输出时停留画面,等待人按回车继续*/
voidinsert(PCB*q)/*插入新进程,把进程按优先数大小排序*/
{PCB*p1,*s,*r;
intb;
s=q;
/*指针s指向新要插入的进程*/
p1=ready;
/*指针p1指向原来的进程队列的队首*/
r=p1;
/*使用指针r是指向p1前面的进程*/
b=1;
while((p1!
=NULL)&
&
b)
if(p1->
prio>
=s->
prio){r=p1;
p1=p1->
}/*新进程的优先数小,则p1
elseb=0;
指向下一个进程继续比*/
if(r!
=p1){r->
next=s;
s->
next=p1;
}/*新进程找到位置,插在r和p1之间*/
else{s->
ready=s;
}}/*新进程的优先数最大,插在队首,并
voidcreate()修改就绪队首ready指针*/
{PCB*p;
inti;
ready=NULL;
run=NULL;
finish=NULL;
printf("
PleaseenterthenameandtimeandpriorityofPCB:
\n"
/*输入进程名、和*/
for(i=0;
i<
N;
i++)
{p=malloc(sizeof(PCB));
/*为新进程开辟空间*/
scanf("
%s"
name);
/*输入进程名*/
%d"
&
p->
needtime);
/*输入进程要求运行时间*/
prio);
/*输入进程优先数*/
p->
cputime=0;
state='
W'
;
/*表示就绪队列中未在队首先执行,但也是就绪状态*/
if(ready!
=NULL)insert(p);
/*就绪队首不为NULL,插入新进程*/
else{p->
next=ready;
ready=p;
}}/*否则先插在NULL前*/
Displayisgoingtostart:
\n"
***********************************************\n"
prt();
run=ready;
/*队列排好,run指向就绪队列队首*/
ready=ready->
/*ready指向下一个进程,这样当进程执行时如果优先数小于其他的进程,应该先进行优先数最大的进程*/
run->
R'
}/*队首进程的状态为就绪*/
voidprio()
{while(run!
{run->
cputime=run->
cputime+1;
/*运行一次cpu占用时间加一*/
needtime=run->
needtime-1;
/*运行一次要求运行时间减一*/
prio=run->
prio-1;
/*运行一次优先数减一*/
if(run->
needtime==0)/*若要求运行时间为0时*/
next=finish;
/*退出队列*/
finish=run;
/*finish为结束进程的队列*/
E'
/*修改状态为结束*/
/*释放run指针*/
=NULL)/*创建新就绪队列的头指针*/
{run=ready;
}}
else
if((ready!
(run->
prio<
ready->
prio))
/*队首进程的优先数比它下一个小,且下一个进程不为NULL时执行*/
next=NULL;
/*队首进程退出进程队列*/
insert(run);
/*在进程队列中重新插入原来的队首进程*/
/*重新置就绪队列的头指针*/
voidmain()
{printf("
PleaseenterthetotalnumberofPCB:
N);
create();
/*模拟创建进程,并输入相关信息*/
prio();
}/*优先数调度算法*/
2、时间片轮转法:
intcount;
/*计数器,判断是否=时间片的大小*/
PCB*ready,*run,*finish,*tail;
/*就绪执行结束尾指针*/
intN,round;
{/*略同优先数法*/}
voidinsert(PCB*q)/*在队尾插入新的进程*/
{tail->
next=q;
tail=q;
q->
voidcreate()
PleaseenterthenameandtimeofPCB:
else{p->
tail=p;
}}
/*ready指向下一个进程*/
voidcount()
count=run->
count+1;
/*运行一次计数器加一*/
count==round)/*如果时间片到*/
count=0;
/*计数器置0*/
if(ready!
=NULL)/*如就绪队列不空*/
Pleaseenterthetimeround(don'
tbetoobig,1or2isbest):
round);
/*输入时间片的大小,不应太大*/
count();
四、程序运行的初值及执行结果:
以下是输出的结果(符合优先数调度):
2、时间片轮转法调度算法:
以下是输出结果(符合时间片轮转法调度):
五、结果分析:
在优先数调度中,程序首先输出各个进程的初始值,按回车之后,由于进程p1的优先数最大,排在就绪队列的队首,首先执行,执行一次后优先数减一,要求运行时间减一,cpu占用时间加一,再和其他的进程比较优先数,还是最大,继续执行,再执行一次后优先数小于进程p3,所以下一个执行的是p3,按这样的顺序,在就绪队列队首的进程状态为"
R"
,不在队首的就绪进程状态为"
W"
,结束的进程状态为"
E"
,一直执行,直到所有进程状态都为"
,调度完成。
在时间片轮转法调度中,先设置了时间片的大小为1,然后各个进程按循环队列依次执行,每执行一次,要求运行时间减一,若等于0了,则状态改为"
,退出队列,直到所有进程的状态为"
6、实验小结:
本次实验虽然为模拟在单处理机情况下处理机的调度,但深深帮我理解了处理机调度的工作,也对进程的几种状态就绪、结束等有了明确的认识。
优先数调度的思考度更强点,在编写C程序的时候,对于其中的进程插入和优先数调度两个函数思考了蛮久,每执行一次进程后,优先数的改变将又要重新排就绪队列,这也是实验的难点所在,自己原来学C的时候对于队列不是很熟,也借本次实验又巩固了原来的知识。
也许是有了优先数调度的基础,时间片轮转法调度的编写来得相对轻松,它的insert()函数比较简单,不用根据优先数来排队,而是直接插在队尾即可。
另外,通过本次实验,我对函数的分模块书写的优点感受颇深,方便了移植和修改,减轻了下次编写的负担,这也是我们以后面向程序设计的要求所在。