实验三、进程调度模拟程序
专业 网络工程 姓名 方俊晖 学号 201406114309
一、 实验目的
通过本实验可以加深对有关进程控制块、进程队列的概念的进一步理解。
二、 实验内容和要求
1.进程PCB的结构体定义
2.定义结构体
3.输入进程序列
4.排序(按到位时间)
5.输出进程运行的结果
三、 实验方法、步骤及结果测试
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<windows.h>
#include<time.h>
typedef struct node
{
char name[10]; //进程名
int prio; //进程优先数
int cputime; //进程占用CPU时间
int needtime; //进程到完成还要的时间
int arrivetime; //进程到达时间
int starttime; //进程开始时间
int finishtime; //进程完成时间
int servicetime; //进程服务时间
char state; //进程的状态
struct node *next;
}PCB;
PCB *finish,*ready,*run; //队列指针
int N; //进程量
void firstin()
{
run=ready; //就绪队列头指针赋值给运行头指针
run->state=‘R‘; //进程状态变为运行态
ready=ready->next; //就绪对列头指针后移到下一进程
}
void prt1(char a)
{
switch(a)
{
case 1: /*优先数法*/
printf("名字\t进程占用CPU时间\t需要的时间\t优先级数\t状态\n");break;
case 2: /*先来先服务算法*/
printf("名字\t到达时间\t开始时间\t服务时间\t完成时间\t状态\n");break;
default:break;
}
}
void prt2(char a,PCB *q)
{
switch(a)
{
case 1: printf("%s\t%d\t\t%d\t\t%d\t\t%c\n",q->name,q->cputime,q->needtime,q->prio,q->state);
break;
case 2: printf("%s\t%d\t\t%d\t\t%d\t\t%d\t\t%c\n",q->name,q->arrivetime,q->starttime,q->servicetime,q->finishtime,q->state);
break;
default:break;
}
}
void prt(char algo)
{
PCB *p;
prt1(algo); //输出文字格式
if(run!=NULL) //如果运行指针不空
prt2(algo,run); //输出当前正在运行的PCB
p=ready; //输出就绪队列PCB
while(p!=NULL)
{
prt2(algo,p);
p=p->next;
}
p=finish; //输出完成队列的PCB
while(p!=NULL)
{
prt2(algo,p);
p=p->next;
}
getchar(); //压任意键继续
}
void insert1(PCB *q)
{
PCB *p1,*s,*r;
int b;
s=q; //待插入的PCB指针
p1=ready; //就绪队列头指针
r=p1; //做p1的前驱指针
b=1;
while((p1!=NULL)&&b) //根据优先数确定插入位置
if(p1->prio>=s->prio)
{
r=p1;
p1=p1->next;
}
else
b=0;
if(r!=p1) //如果条件成立说明插入在r与p1之间
{
r->next=s;
s->next=p1;
}
else
{
s->next=p1; //否则插入在就绪队列的头
ready=s;
}
}
void insert2(PCB *q)
{
PCB *p1,*s,*r;
int b;
s=q; //指针s指向新要插入的进程
p1=ready; //指针p1指向原来的进程的对首
r=p1; //使用指针r指向p1前面的进程
b=1;
while((p1!=NULL)&&b)
{
if(p1->arrivetime<s->arrivetime)
{
r=p1;
p1=p1->next;
}
else
b=0;
}
if(r!=p1)
{
r->next=s;
s->next=p1;
}
else
{
s->next=p1;
ready=s;
}
}
void create1(char alg)
{
PCB *p;
int i,time;
char na[10];
ready=NULL; //就绪队列头指针
finish=NULL; //完成队列头指针
run=NULL; //运行队列头指针
//输入N个进程名和所需时间创建PCB
for(i=1;i<=N;i++)
{
printf("请输入第%d个进程的名字和运行时间\n进程名:",i);
p=(PCB *)malloc(sizeof(PCB));
scanf("%s",na);
printf("所需时间:");
scanf("%d",&time);
strcpy(p->name,na);
p->cputime=0;
p->needtime=time;
p->state=‘W‘;
p->prio=rand()%15+1; //随机分配优先数[1,15]
if(ready!=NULL) //就绪队列不空则调用插入函数插入
insert1(p); //对新进程插入就绪队列
else
{
p->next=ready; //创建就绪队列的第一个PCB
ready=p;
}
}
system("cls");
printf(" 优先数算法结果输出\n");
printf("---------------------------------------------------------------------------\n");
prt(alg); //输出进程PCB信息
run=ready; //将就绪队列的第一个进程投入运行
ready=ready->next;
run->state=‘R‘;
}
void create2(char alg)
{
PCB *p;
int i;
ready=NULL;
run=NULL;
finish=NULL;
for(i=0;i<N;i++)
{
p=(PCB *)malloc(sizeof(PCB));
printf("进程名:");
scanf("%s",p->name);
printf("到达时间:");
scanf("%d",&p->arrivetime);
printf("需要时间:");
scanf("%d",&p->servicetime);
p->starttime=0;
p->finishtime=0;
p->state=‘W‘;
if(ready!=NULL)
insert2(p);//将新进程插入就绪队列
else
{
p->next=ready;//创建就绪队列的第一个
ready=p;
}
}
system("cls");
printf(" 先来先服务算法结果输出\n");
printf("---------------------------------------------------------------------------\n");
prt(alg);
}
void priority(char alg)
{
while(run!=NULL) //当运行队列不空时,有进程正在运行
{
run->cputime=run->cputime+1;
run->needtime=run->needtime-1;
run->prio=run->prio-1; //每运行一次优先数-1
if(run->prio<0) //如果优先数减到小于0,则转换成0
run->prio=0;
if(run->needtime==0) //如果所需时间为0,即完成,将其插入完成队列
{
run->next=finish;
finish=run;
run->state=‘F‘; //置状态为完成态
run=NULL; //运行队列头指针为空
if(ready!=NULL) //如果就绪队列不空
firstin(); //将就绪对列的第一个进程投入运行
}
else //没有运行完同时优先数不是最大,则将其变为就绪态插入到就绪队列
if((ready!=NULL)&&(run->prio<ready->prio))
{
run->state=‘W‘; //状态改为就绪
insert1(run); //将进程按优先数大小插入
firstin(); //将就绪队列的第一个进程投入运行
}
prt(alg); //输出进程PCB信息
}
}
void FCFS(char alg)
{ int time=0;//系统时间从0开始
do{
run=ready;//就绪序列的第一个进程放入run队列进行执行
run->state=‘R‘;//进程开始执行
ready=ready->next;//指向下一个
time=run->arrivetime>time? run->arrivetime:time;
run->starttime=time;//进程开始
prt(alg);//显示正在执行的进程
time=time+run->servicetime;//计算下个进程最小可开始时间
run->finishtime=time;//进程结束时间
run->state=‘F‘;//结束状态标识
prt(alg);//进程结束再显示
run->next=finish;
finish=run;//进程结束放入结束队列
run=NULL;
}while(ready!=NULL);
}
/*菜单显示函数*/
void Menu()
{
system("cls");
printf("\t\t+━━━━━━━━━━━━━━━━━━━━━━+\n");
printf("\t\t| pcb进程调度 | \n");
printf("\t\t|━━━━━━━━━━━━━━━━━━━━━━| \n");
printf("\t\t| | \n");
printf("\t\t| [1]优先数算法 | \n");
printf("\t\t| | \n");
printf("\t\t| [2]先来先服务算法 | \n");
printf("\t\t| | \n");
printf("\t\t| [3]退出系统 | \n");
printf("\t\t| | \n");
printf("\t\t|━━━━━━━━━━━━━━━━━━━━━━| \n");
printf("\t\t| By:FJH | \n");
printf("\t\t+━━━━━━━━━━━━━━━━━━━━━━+\n");
printf("\t\t请输入编号:");
}
int main()
{
char algo; //接收算法编号
char mainmenu;//判断是否继续
srand((unsigned)time(NULL));
system("cls");//清屏
do{
Menu();//显示菜单
scanf("%d",&algo); //输入算法编号
switch(algo)
{
case 1:
system("cls");
printf("您选择的是优先数算法\n");
printf("请输入进程数目:");
scanf("%d",&N); //输入进程数
create1(algo); //创建队列
priority(algo);//优先数
break;
case 2:
system("cls");
printf("您选择的是先来先服务算法\n");
printf("请输入进程数目:");
scanf("%d",&N); //输入进程个数
create2(algo);//创建队列
FCFS(algo);//先来先服务
break;
case 3:
printf("\t\tI want to see you again!886! \n");
exit(0);
break;
default:
printf("输入有误\n");
break;
}
printf("\n是否继续操作(Y/N) ");
fflush(stdin);
mainmenu=getchar();
}
while(mainmenu==‘y‘||mainmenu==‘Y‘);
return 0;
}
四、 实验总结
本次实验需要应用以前所学的C语言的知识,定义结构体、指针等方法去完成本次实验,在这过程中需要对PCB进程管理反复试验,才能完成。