实验三 进程调度模拟实验
物联网工程 张学玲 201306104140
一、 实验目的
用高级语言完成一个进程调度程序,以加深对进程的概念及进程调度算法的理解。
二、 实验内容和要求
实验内容
完成两个算法(简单时间片轮转法、多级反馈队列调度算法)的设计、编码和调试工作,完成实验报告。
1) 每个进程有一个进程控制块(PCB)表示。进程控制块包含如下信息:进程名、优先级、到达时间、需要运行时间、已用CPU时间、进程状态等等。
2) 每个进程的状态可以是就绪 r(ready)、运行R(Running)、或完成F(Finished)三种状态之一。
3) 就绪进程获得 CPU后都只能运行一个时间片。用已占用CPU时间加1来表示。
4) 如果运行一个时间片后,进程的已占用 CPU时间已达到所需要的运行时间,则撤消该进程,如果运行一个时间片后进程的已占用CPU时间还未达所需要的运行时间,也就是进程还需要继续运行,应把它插入就绪队列等待下一次调度。
5) 每进行一次调度,程序都打印一次运行进程、就绪队列中各个进程的 PCB,以便进行检查。
6) 重复以上过程,直到所要进程都完成为止。
实验要求
设计一个有 N(N不小于5)个进程并发执行的进程调度模拟程序。
进程调度算法:“时间片轮转法”调度算法对N个进程进行调度。
三、 实验方法、步骤及结果测试
1. 源程序名:压缩包文件(rar或zip)中源程序名:zxl3.c
可执行程序名:zxl3.exe
2. 原理分析及流程图
主要总体设计问题(包括存储结构,主要算法,关键函数的实现等)
1.设置一个进程控制块(PCB)以保存进程的信息,包括进程名、优先级、到达时间、需要运行时间、已用时间以及进程状态;
2.用于输入进程的函数Input(),当输入进程不足5个时会要求继续输入;
3.用于对输入完成的进程排序的函数Sort(),先按照进程的优先级进行排序;
4.用于打印进程的函数Print(),将已经排序完的进程打印出来;
5.用于处理进程的函数Attemper(),将优先级较高的进程先处理一个时间片,然后按照顺序继续执行;
6.用于选择功能的函数Select();
7.main()函数。
3. 主要程序段及其解释:
实现主要功能的程序段,重要的是程序的注释解释。
#include<stdio.h>
#define Max 50
typedef struct job
{
char name[Max]; //进程名
int priority; //优先级
int arrtime; //到达时间
int needtime; //需要运行时间
int usedtime; //已用时间
char state; //进程状态
}PCB;
int n=0;
PCB pcb[Max];
int pTime; //时间片
void Input()
{
char ch;
do{
do{
printf("\n***请输入第%d个进程进程***\n",n);
printf("\n进程名");
scanf("%s",pcb[n].name);
printf("进程优先级");
scanf("%d",&pcb[n].priority);
printf("进程需要的时间");
scanf("%d",&pcb[n].needtime);
pcb[n].arrtime=n;
pcb[n].usedtime=0;
pcb[n].state='W';
n++;
printf("Do you want to continue?'Y'es or 'N'o:");
do{
ch=getchar();
}while(ch!='Y'&&ch!='N'&&ch!='y'&&ch!='n');
}while(ch=='Y'||ch=='y');
}while(n<5);
}
void Sort()
{
int i,j;
PCB temp;
for(i=0;i<n-1;i++) //按照到达时间排序
{
for(j=n-2;j>=i;j--)
{
if(pcb[j+1].arrtime<pcb[j].arrtime)
{
temp=pcb[j];
pcb[j]=pcb[j+1];
pcb[j+1]=temp;
}
}
}
for(i=0;i<n-1;i++) //按照优先级排序
{
for(j=n-2;j>=i;j--)
{
if(pcb[j+1].priority>pcb[j].priority)
{
temp=pcb[j];
pcb[j]=pcb[j+1];
pcb[j+1]=temp;
}
}
}
if(pcb[0].state!='F')
{
pcb[0].state='R';
}
}
void Print()
{
int i;
Sort();
printf("\n*进程名 *优先级 *到达时间 *需要时间 *已用时间 *进程状态*\n");
for(i=0;i<n;i++)
{
printf("%8s%8d %8d %10d %10d %10c\n",pcb[i].name,pcb[i].priority,pcb[i].arrtime,pcb[i].needtime,pcb[i].usedtime,pcb[i].state);
}
}
void Attemper()
{
do{
if((pcb[0].needtime-pcb[0].usedtime)>pTime) //判断进程剩余的运行时间是否大于时间片
{
pcb[0].usedtime+=pTime;
pcb[0].priority--;
pcb[0].state='W';
}
else //已完成的进程
{
pcb[0].usedtime=pcb[0].needtime;
pcb[0].priority=-1;
pcb[0].state='F';
}
Print();
}while(pcb[0].state!='F');
}
char Select()
{
char select;
printf("各按键功能:");
printf("\n0:结束当前任务");
printf("\n1:增加并调度进程");
printf("\n2:打印进程");
printf("\n请选择:");
do{
select=getchar();
}while(select!='0'&&select!='1'&&select!='2');
return select;
}
void main()
{
char choose;
n=0;
printf("\n*******************************************************\n");
printf("\t\t***欢迎使用进程调度模拟***\n\n");
choose=Select();
do{
if(choose=='0')
{
return;
}
if(choose=='1')
{
printf("请设置时间片的大小:");
scanf("%d",&pTime);
Input();
printf("\n*****************************\n");
Print();
printf("\n*****************************\n");
Attemper();
}
if(choose=='2')
{
Print();
}
choose=Select();
}while(1);
}
4. 运行结果及分析
一般必须配运行结果截图,结果是否符合预期及其分析。
当进程不足5个时自动继续要求输入:
当进程满5个后,可以退出也可以继续输入:
排序:
进程处理:
四、 实验总结
在实验过程中,我想用一个确定的值来循环输入进程的有关数据,但是这样显示不出进程名和状态,而且进程的显示也会出错,所以用do-while来边输入边确定值。这个程序是借鉴其他的程序来完成的,最重要的是要理解简单时间片轮转法、多级反馈队列调度算法的思想。