标签:
一、 实验目的
1.用高级语言完成一个进程调度程序,以加深对进程的概念及进程调度算法的理解。
2.实验要求
3.设计一个有 N(N不小于5)个进程并发执行的进程调度模拟程序。
4.进程调度算法:“时间片轮转法”调度算法对N个进程进行调度。
二、 实验内容和要求
完成两个算法(简单时间片轮转法、多级反馈队列调度算法)的设计、编码和调试工作,完成实验报告。
1) 每个进程有一个进程控制块(PCB)表示。进程控制块包含如下信息:进程名、优先级、到达时间、需要运行时间、已用CPU时间、进程状态等等。
2) 每个进程的状态可以是就绪 r(ready)、运行R(Running)、或完成F(Finished)三种状态之一。
3) 就绪进程获得 CPU后都只能运行一个时间片。用已占用CPU时间加1来表示。
4) 如果运行一个时间片后,进程的已占用 CPU时间已达到所需要的运行时间,则撤消该进程,如果运行一个时间片后进程的已占用CPU时间还未达所需要的运行时间,也就是进程还需要继续运行,应把它插入就绪队列等待下一次调度。
5) 每进行一次调度,程序都打印一次运行进程、就绪队列中各个进程的 PCB,以便进行检查。
6) 重复以上过程,直到所要进程都完成为止。
三、 实验方法、步骤及结果测试
1.源程序名:1125.c
可执行程序名:1125.exe
2.原理分析及流程图
1)理解简单轮转法与多级反馈队列调度算法;
2)流程图:
3.主要程序段及其解释:
#include<stdio.h>
#define MAX 24
typedef struct node
{
char name[10];//作业名
int arrivetime;//作业到达时间
int runtime;//作业所需的运行时间
int usetime; //已用CPU时间
char stage; //进程的状态
int starttime; //开始时间
int endtime; //结束时间
int zztime; //作业周转时间
float zzxs; //周转系数
}JCB;
static unsigned int N=5; //作业数
static int current=0, current1=0; //当前时间
static unsigned int j=-1, j1=-1;
JCB job[MAX];
void Line();
void FCFS();
void getValue();
void getValue1();
void input();
void print();
void choice();
void SJF();
void getValue()
{
unsigned int i;
current=job[0].arrivetime;
for(i=0; i<N; i++)
{
if(job[i].stage==‘r‘ && current>=job[i].arrivetime)
{
if(job[i].usetime==0)
job[i].starttime=current;
job[i].stage=‘R‘; //程序正在运行
job[i].usetime++; //CPU的运行时间加1
current++;
}
if(job[i].usetime==job[i].runtime && job[i].stage==‘R‘)
{
j++; //用来标记有多少进程完成了
job[i].stage=‘F‘;
job[i].endtime=current;
job[i].zztime=job[i].endtime-job[i].arrivetime;
job[i].zzxs=(float)job[i].zztime/(float)job[i].runtime;
}
if(job[i].stage!=‘F‘)
job[i].stage=‘r‘; //运行完之后变回就绪态
if(i==N-1) //进入死循环了
i=-1;
if(j==N-1)
break;
}
}
void getValue1()
{
unsigned int i=0, h, rest;
current1=job[0].arrivetime;
for(; i<N; i++)
{
if(job[i].stage==‘2‘)
{
h=0;
while(h<N) //判断当前时刻的这一级是否有进程
{
if(job[h].stage==‘r‘ && current1>=job[h].arrivetime)
{
i=h;
h=N;
}
h++;
}
}
else if(job[i].stage==‘3‘)
{
h=0;
while(h<N) //判断当前时刻的这一级是否有进程
{
if(job[h].stage==‘2‘)
{
i=h;
h=N;
}
h++;
}
}
if(job[i].stage==‘r‘ && current1>=job[i].arrivetime)
{
if(job[i].usetime==0)
job[i].starttime=current1;
job[i].stage=‘R‘; //程序正在运行
job[i].usetime++; //CPU的运行时间加1
current1++;
if(job[i].usetime==job[i].runtime)
{
j1++;
job[i].stage=‘F‘;
job[i].endtime=current1;
job[i].zztime=job[i].endtime-job[i].arrivetime;
job[i].zzxs=(float)job[i].zztime/(float)job[i].runtime;
}
else //还没完成则进入下一级
job[i].stage=‘2‘;
}
else if(job[i].stage==‘2‘)
{
job[i].stage=‘R‘;
job[i].usetime+=2;
current1+=2;
if(job[i].usetime>=job[i].runtime)
{
j1++;
job[i].stage=‘F‘;
rest=job[i].usetime-job[i].runtime;
current1=current1-rest;
job[i].endtime=current1;
job[i].zztime=job[i].endtime-job[i].arrivetime;
job[i].zzxs=(float)job[i].zztime/(float)job[i].runtime;
}
else //还没完成则进入下一级
job[i].stage=‘3‘;
}
else if(job[i].stage==‘3‘)
{
job[i].stage=‘R‘;
job[i].usetime+=4;
current1+=4;
if(job[i].usetime>=job[i].runtime)
{
j1++;
job[i].stage=‘F‘;
rest=job[i].usetime-job[i].runtime;
current1=current1-rest;
job[i].endtime=current1;
job[i].zztime=job[i].endtime-job[i].arrivetime;
job[i].zzxs=(float)job[i].zztime/(float)job[i].runtime;
}
else //还没完成则在最后一级继续轮转
job[i].stage=‘3‘;
}
if(i==N-1) //进入死循环了
i=-1;
if(j1==N-1)
break;
}
}
void input()
{
int i, jobNum, choi;
printf("1.自选作业个数\n");
printf("2.系统默认作业个数\n");
printf("你的选择是:");
scanf("%d", &choi);
switch(choi)
{
case 1:
{
do{
printf("\nEnter process number(作业个数应在2~24之间):");
scanf("%d", &jobNum); //输入作业数
N=jobNum;
printf("\n");
}while(N<2 || N>24);
break;
}
case 2:
printf("\n系统默认作业个数为5");
break;
}
for(i=0; i<jobNum; i++)
{
printf("\njob %d name:",i+1);
scanf(" ");
gets(job[i].name); //输入作业名
printf("arrive time:");
scanf(" %d",&job[i].arrivetime); //输入作业达到时间
printf("running time:");
scanf(" %d",&job[i].runtime); //输入作业执行时间
}
}
void print()
{
unsigned int i;
printf(" name arrivetime runtime starttime endtime zztime zzxs\n");
for(i=0; i<N; i++)
{
printf("jod%d",i+1);
printf(" %s\t\t%d %d %d %d %d %.2f\n",job[i].name,job[i].arrivetime,job[i].runtime,job[i].starttime,job[i].endtime,job[i].zztime,job[i].zzxs);
}
}
void choice()
{
int mark;
do{
printf("\n\n1. 简单轮转法;\n2. 多级反馈队列调度算法;\n3. 退出.");
printf("\nMake choice: ");
scanf("%d", &mark);
switch(mark)
{
case 1:
FCFS(); //先来先服务
break;
case 2:
SJF(); //短作业优先
break;
case 4:
return;
default:
printf("\nerror!");
}
}while(mark!=4);
}
void Line()
{
unsigned int a, b;
JCB mark;
current=0; current1=0;
j=-1; j1=-1;
for(a=0; a<N; a++)
{
job[a].usetime=0;
job[a].stage=‘r‘; //就绪态
job[a].starttime=0;
job[a].endtime=0;
job[a].zztime=0;
job[a].zzxs=0;
}
for(a=0;a<N-1; a++) //通过到达时间整体排序
{
for(b=a+1; b<N; b++)
{
if(job[b].arrivetime<job[a].arrivetime)
{
mark=job[b];
job[b]=job[a];
job[a]=mark;
}
}
}
}
void FCFS()
{
Line();
getValue(); //给每个作业内的相关参数赋值
print(); //打印出来
}
void SJF()
{
Line();
getValue1();
print(); //打印出来
}
void main()
{
input(); //输入
print(); //打印输出
choice(); //选择方式
}
4.运行结果及分析
图4.1 提示用户输入信息
图4.2 简单轮转法结果
图4.3 多级反馈队列调度算法结果
四、 实验总结
在前一次作业调度程序的基础上,改进成进程调度其实并不难,因为有那样的思维在里面,但是在做这次实验的过程中,首先理解简单轮转法和多级反馈跳读算法是很关键的,理解后顺着算法的思路编程,即使出现问题了,也能很快的找到是哪里的问题,并且不断地调试、改正,最后得到结果。
标签:
原文地址:http://www.cnblogs.com/1994-ann/p/5020897.html