实验1 进程调度(C)
1.目的和要求
进程调度是处理机管理的核心内容。本实验要求用C语言编写和调试一个简单的进程调度程序。通过本实验可以加深理解有关进程控制块、进程队列的概念,并体会和了解优先数和时间片轮转调度算法的具体实施办法。
2.实验内容
①设计进程控制块PCB表结构,分别适用于优先数调度算法和循环轮转调度算法。
②建立进程就绪队列。对两种不同算法编制入链子程序。
③编制两种进程调度算法:1)优先数调度;2)循环轮转调度 3)先来先服务调度
3.实验环境
①PC兼容机
②Windows、DOS系统、Turbo c 2.0
③C语言
4.实验提示
①本程序用两种算法对五个进程进行调度,每个进程可有三个状态,并假设初始状态为就绪状态。
②为了便于处理,程序中的某进程运行时间以时间片为单位计算。各进程的优先数或轮转时间数以及进程需运行的时间片数的初始值均由用户给定。
③在优先数算法中,优先数可以先取值为50-进程执行时间,进程每执行一次,优先数减3,CPU时间片数加1,进程还需要的时间片数减1。在轮转算法中,采用固定时间片(即:每执行一次进程,该进程的执行时间片数为已执行了2个单位),这时,CPU时间片数加2,进程还需要的时间片数减2,并排列到就绪队列的尾上。
④对于遇到优先数一致的情况,采用FIFO策略解决。
⑤把当前处于就绪队列之首的那个进程调度到运行状态。也就说,它只考虑进程进入就绪队列的先后,而不考虑它的下一个CPU周期的长短及其他因素。FCFS算法简单易行,是一种非抢占式策略
5.实验程序
/*①本程序用两种算法对五个进程进行调度,每个进程可有三个状态,并假设初始状态为就绪状态(ready)。
②为了便于处理,程序中的某进程运行时间以时间片为单位计算。各进程的优先数或轮转时间数以及进程需运行的时间片数的初始值均由用户给定。
③在优先数算法中,优先数可以先取值为50-进程执行时间,进程每执行一次,优先数减3,CPU时间片数加1,进程还需要的时间片数减1。在轮转算
法中,采用固定时间片(即:每执行一次进程,该进程的执行时间片数为已执行了2个单位),这时,CPU时间片数加2,进程还需要的时间片数减2,
并排列到就绪队列的尾上。
④对于遇到优先数一致的情况,采用FIFO策略解决。
*/
//增加算法,先来先服务
#include <stdio.h>
#include <dos.h>
#include <stdlib.h>
#include <conio.h>
#include <io.h>
#include<Windows.h>
#define P_NUM 5 //5个进程,可改变
#define P_TIME 50//优先级初始值
#define sleep
enum state{ /*枚举类型*/
ready,//就绪
execute,//执行
block,//阻塞
finish//完成
};//设置进程的状态
struct pcb{ /*进程控制块数据结构*/
char name[4];//进程名
int arrivaltime;//到达时间
int priority;//优先级
int cputime;//cpu执行的时间
int needtime;//进程执行所需时间
int count;// 记录执行的次数
int round;//轮转次数
enum state process;
struct pcb * next;//链表指针
};
struct fcfs{//FCFS数据结构
char name[10];
int arrivaltime;//到达时间
int starttime;//开始时间
int finishtime;
int cputime;//cpu运行时间
int needtime;//需要时间
int count;//次数
enum state process;
};
struct fcfs a[5];//最大进程数
struct fcfs t;
struct pcb * get_process(); /*进程建立*/
struct pcb * get_process(){
struct pcb *q;
struct pcb *t;
struct pcb *p;
int i=0;
printf("input name and needtime, please input 5 processes\n");
while (i<P_NUM){//有5个进程需要调度
q=(struct pcb *)malloc(sizeof(struct pcb));//分配空间
scanf("%s", &(q->name) );//输入进程名
scanf( "%d", &(q->needtime));//输入进程所需时间
q->cputime=0;//令cpu执行时间初始值为0
q->priority=P_TIME-q->needtime;//令其优先级为刚开始的固定值50-已经执行的时间
q->process=ready;//进程状态为就绪
q->next=NULL;//当前指针位置的下一节点为空
if (i==0){//如果 i=0
p=q;//设置p头指针
t=q;
}
else{
t->next=q;
t=q;
}
i++;
}/*while*/
return p;
}
void display(struct pcb *p){//展示
printf("name cputime needtime priority state\n");
while(p){
printf("%s", p->name);//输出进程名
printf(" ");
printf("%d", p->cputime);//输出cpu执行的时间
printf(" ");
printf("%d", p->needtime);//输出进程执行所需时间
printf(" ");
printf("%d", p->priority);//输出优先级
printf(" ");
switch(p->process){//输出进程状态
case ready:
printf("ready\n");
break;
case execute:
printf("execute\n");
break;
case block:
printf("block\n");
break;
case finish:
printf("finish\n");
break;
}
p=p->next;//指向下一个进程
}
}
int process_finish(struct pcb *q){ /*进程是否结束,当还有进程没有结束时返回0*/
int bl=1;
while(bl&&q){
bl=bl&&q->needtime==0;
q=q->next;
}
return bl;
}
void cpuexe(struct pcb *q){
struct pcb *t=q;
int max_priority=0;//设最大优先级为0
while(q){
if (q->process!=finish){//如果进程没完成
q->process=ready;//进程就处于就绪状态
if(q->needtime==0){//若进程所需执行时间为0,则该进程调度完成
q->process=finish;
}
}
if(max_priority<q->priority&&q->process!=finish){//如果最大优先级比q的优先级小且进程没完成,那么,最大优先级就为q的优先级
max_priority=q->priority;
t=q;//令t=q
}
q=q->next;//指向下一个进程
}
if(t->needtime!=0){//如果q的所需时间不为0
t->priority-=3;//优先级=优先级-3
t->needtime--;//所需时间-1
t->process=execute;//进程阻塞
t->cputime++;//cpu执行时间+1
}
}
void priority_cal(){ /*优先数调度*/
struct pcb * p;
int cpu =0;
p=get_process();//创建p进程
while(!process_finish(p)){//p没处于完成状态
cpu++;//cpu时间+1
printf( "cputime:%d\n" ,cpu);//输出cpu运行时间
cpuexe(p);// 调用函数
display(p);//展示
sleep(5);//睡眠
}
printf("All processes have finished,press any key to exit");
getch();
}
void display_menu(){//目录
printf("CHOOSE THE ALGORITHM:\n" );
printf("1 PRIORITY\n" );
printf("2 ROUNDROBIN\n" );
printf("3 FirstComeFirstService\n");
printf("4 EXIT\n" );
}
struct pcb * get_process_round(){ /*轮转进程建立*/
struct pcb *q;
struct pcb *t;
struct pcb *p;
int i=0;
printf("input name and time,please input 5 processes\n");
while (i<P_NUM){//5个进程进行轮转
q=(struct pcb *)malloc(sizeof(struct pcb));//分配空间
scanf( "%s", &(q->name));//输入进程名
scanf( "%d", &(q->needtime));//输出进程执行所需时间
q->cputime=0;//令cpu执行时间,轮转数和执行次数初始值都为0
q->round=0;
q->count=0;
q->process=ready;//让进程处于就绪状态
q->next=NULL;//当前指针位置的下一节点为空
if (i==0){//没有进程时
p=q;
t=q;
}
else{//i!=0时,将q赋值给t->next
t->next=q;
t=q;
}
i++;
} /*while*/
return p;
}
void cpu_round(struct pcb *q){ /*处理机轮转*/
q->cputime+=2;//每轮转一次,cpu时间加2
q->needtime-=2;//进程运行所需时间减2
if(q->needtime<0) {//当进程运行所需时间小于0时,说明该进程调度完成
q->needtime=0;
}
q->count++;//每调度一次,记录次数+1
q->round++;// 轮转次数加1
q->process=execute;//进程进入执行状态
}
struct pcb * get_next(struct pcb * k, struct pcb * head){ /*返回没有结束的进程*/
struct pcb * t;
t=k;
do{
t=t->next;
}while (t && t->process==finish);//当t和该t进程未完成时就执行
if(t==NULL){//如果t为空,那么t=head
t=head;
while (t->next!=k && t->process==finish){//若t的下一个进程不是k且t已经完成,那么,将下一个进程赋给k
t=t->next;
}
}
return t;
}
void set_state(struct pcb *p){//改变进程状态
while(p){
if (p->needtime==0){
p->process=finish;
}
if (p->process==execute){
p->process=ready;
}
p=p->next;
}
}
void display_round(struct pcb *p){
printf("NAME CPUTIME NEEDT*IME COUNT ROUND STATE\n");
while(p){//输出RR调度算法的运行情况
printf("%s",p->name);
printf(" ");
printf("%d",p->cputime);
printf(" ");
printf("%d",p->needtime);
printf(" ");
printf("%d",p->count);
printf(" ");
printf("%d",p->round);
printf(" ");
switch(p->process){//判断进程所处状态
case ready:
printf("ready\n");
break;
case execute:
printf("execute\n");
break;
case finish:
printf("finish\n");
break;
}
p=p->next;//跳向下一进程
}
}
void round_cal(){ /*循环轮转调度*/
struct pcb * p;
struct pcb * r;
int cpu=0;
p=get_process_round();//调用RR调度
r=p;
while(!process_finish(p)){//进程没完成就一直循环
cpu+=2;
cpu_round(r);
r=get_next(r,p);
printf("cpu %d\n", cpu );
display_round(p);
set_state(p);
sleep(5);
}
printf("All processes have finished,press any key to exit");
getch();
}
//新增调度算法,先来先服务
void FCFS()
{
int i,j;
int nowtime=0;
int count=0;
int flag=1;
int cpu=0;
int needtime=0;
printf("input name and needtime and arrivaltime, please input 5 processes:\n");
for(i=0;i<5;i++)//输入进程的名称,服务所需时间,到达时间
{
printf("请输入第%d进程的名称,服务所需时间,到达时间\n",i+1);
scanf("%s%d%d",&(a[i].name),&(a[i].needtime),&(a[i].arrivaltime));
}
for(i=0;i<5;i++)
{
for(j=0;j<=i;j++)
{
if(a[i].arrivaltime<a[j].arrivaltime)
{
t=a[i];
a[i]=a[j];
a[j]=t;
}
}
}
int k;
printf("\n执行顺序:\n");
printf("%s",a[0].name);
for(k=1;k<5;k++)
{
printf("-%s",a[k].name);
}//执行顺序的输出
//看开始时间
a[0].starttime=a[0].arrivaltime;
nowtime=a[0].arrivaltime+a[0].needtime;
for(i=1;i<5;i++)
{
if(a[i].arrivaltime>(a[i-1].arrivaltime+a[i-1].needtime+nowtime))
{
a[i].starttime=a[i].arrivaltime;
}
else{
a[i].starttime=a[i-1].starttime+a[i-1].needtime;
}
nowtime=a[i].arrivaltime+a[i].needtime;
} //看开始时间结束
//进程调度过程
printf("\ncputime:%d",cpu);
printf("\nname\t needtime\t arrivaltime\t starttime \t state\n");
for(j=0;j<5;j++)
{
printf("\n%s\t\t%d\t\t%d\t\t%d\t",a[j].name,a[j].needtime,a[j].arrivaltime,a[j].starttime);
printf(" ready\n");
}
for(i=0;i<5;i++)
{
while(a[i].needtime>0){
count++;
a[i].cputime++;
a[i].needtime--;
printf("cputime:%d",count);
printf("\nname\t needtime\t arrivaltime\t starttime \t state\n");
for(j=0;j<5;j++)
{
printf("\n%s\t\t%d\t\t%d\t\t%d\t",a[j].name,a[j].needtime,a[j].arrivaltime,a[j].starttime);
if(i<j)
{
printf(" ready\n");
}
else if(i==j&&a[i].needtime!=0)
{
printf(" execute\n");
}
if(i>j||a[i].needtime==0)
{
printf(" finish\n");
}
}
}
}
}
/* 主程序*/
void main(){
int user_input;//用户输入
display_menu();//目录
scanf("%d",&user_input);//输入用户选项
switch(user_input){
case 1:priority_cal();break;//优先级调度
case 2:round_cal();break;//时间片轮转
case 3:FCFS();break;
case 4:break;//退出
default://switch中都不成立就执行一下语句 ,即再次输入选项
display_menu();
scanf("%d",&user_input);
break;
}
}
6.1 优先级调度算法结果截图
6.2 时间片轮转调度算法结果截图
6.3 先来先服务调度算法结果截图