c语言课程设计处理机低级调度模拟系统
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
《高级程序设计语言》课程设计报告题目:处理机低级调度模拟系统
专业:网络工程
班级: 10….
学号: 00000000000
姓名: *********
指导教师: *******
完成日期: 2013年 3月 30 日
一、课程设计的目的
1、掌握C语言数组、函数、指针、结构体的综合应用。
2、掌握使用C语言,进行应用性的开发。
3、掌握系统数据结构与算法的设计。
二、课程设计的内容
课程设计题目:处理机低级调度模拟系统
课程设计内容:根据操作系统处理机不同的调度算法,使用C语言模拟实现处理机调度过程。
1、系统数据结构
(1)进程控制块(pcb):进程名称、到达时间、进程要求运行时间、进程已运行时间、指针、进程状态等等(要根据不同算法的需要定义全面的数据结构)(2)进程队列(PQueue):链表……
2、调度算法
(1)先来先服务调度(FCFS):按照进程提交给系统的先后顺序来挑选进程,先提交的先被挑选。
(2)多级反馈队列调度(FB,第i级队列的时间片=2i-1):
(a)应设置多个就绪队列,并为各个队列赋予不同的优先级。
(b)当一个新进程进入内存后,首先将它放入第一队列的末尾,按FCFS的原则排队等待调度。
当轮到该进程执行时,如他能在该时间片内完成,便可准备撤离系统;如果它在一个时间片结束时尚未完成,调度程序便将该进程转入第二队列的末尾,再同样地按FCFS原则等待调度执行;如果它在第二队列中运行一个时间片后仍未完成,再依次将它放入第三队列……,如此下去,当一个长作业进程从第一
队列依次降到第N队列后,在第N队列中便采取时间片轮转的方式运行。
(c)仅当第一队列空闲时,调度程序才调度第二队列中的进程运行。
三、课程设计的要求
1、按照给出的题目内容
(1)完成系统数据结构设计与实现、系统算法设计与实现、系统模块设计与实现、系统总体的设计与实现。
(2)系统需要一个简单操作界面,例如:
===========================
1. 先来先服务调度
2. 多级反馈队列调度
3. 退出
(按数字1、2、3、,选择操作)
===========================
(3)对每种调度算法都要求输出每个进程(进程数不少于5)开始运行时刻、完成时刻、周转时间,以及这组进程的平均周转时间。
(4)画出每种调度算法流程图。
1.先来先服务调度:
2.多级反馈队列调度:
四:课程设计过程:
1.系统中所使用的数据结构及说明
……..数据结构的定义…………..
定义进程控制块PCB
struct PCB{
char name[10]; //进程名字
float arrivetime; //进程到达时间
float servicetime;//进程服务时间
float super; //响应比
float starttime; //开始运行时间
float finishtime; //完成时间
float TurnaroundTime; //周转时间
char state; //进程的状态,W就绪态,R执行态,F完成态
int prio; //优先级
int round; //时间片
int cputime; //cpu时间
int needtime; //进程运行时间
int count; //计数器
struct PCB *next;
}*ready=NULL,*p,*q;
定义就绪队列:
typedef struct Queue //多级就绪队列节点信息
{
PCB *LinkPCB; //就绪队列中的进程队列指针
int prio; //本就绪队列的优先级
int round; //本就绪队列所分配的时间片
struct Queue *next; //指向下一个就绪队列的链表指针
}ReadyQueue;
2.系统功能结构
本系统是处理机低级调度模拟系统,主要通过模拟来实现处理机调度,调度方式有先来先服务调度(FCFS)、短进程优先调度(SJF)、高响应比优先调度(HRN)、多级反馈队列调度(FB)四种调度方式。
系统运行过程如下:输入进程个数,输入进程详细信息,通过简单操作界面来选择调度方式,调度的过程和结果,重新选择调度方式或者选择结束。
3.程序清单及描述
#define NULL 0
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <windows.h>
struct PCB{
char name[10]; //进程名字
float arrivetime; //进程到达时间
float servicetime;//进程服务时间
float super; //响应比
float starttime; //开始运行时间
float finishtime; //完成时间
float TurnaroundTime; //周转时间
char state; //进程的状态,W就绪态,R执行态,F完成态
int prio; //优先级
int round; //时间片
int cputime; //cpu时间
int needtime; //进程运行时间
int count; //计数器
struct PCB *next;
}*ready=NULL,*p,*q;
typedef struct Queue //多级就绪队列节点信息
{
PCB *LinkPCB; //就绪队列中的进程队列指针
int prio; //本就绪队列的优先级
int round; //本就绪队列所分配的时间片
struct Queue *next; //指向下一个就绪队列的链表指针
}ReadyQueue;
PCB a[100];
int N;
void createProcess(PCB *p)//创建进程函数
int i;
printf("输入进程名& 到达时间& 服务时间:\n例如: a 0 100\n");
for(i=0;i<=N-1;i++)
{
printf("输入第%d个进程的信息:\n",i+1);
scanf("%s%f%f",&p[i].name,&p[i].arrivetime,&p[i].servicetime);
}
}
void sort(PCB *p,int N)//到达时间排序
{
for(int i=0;i<=N-1;i++)
for(int j=0;j<=i;j++)
if(p[i].arrivetime<p[j].arrivetime)
{
PCB temp;
temp=p[i];
p[i]=p[j];
p[j]=temp;
}
}
void running(PCB *p, float arrivetime,float servicetime,float starttime,float finishtime,float &TurnaroundTime,int N)//计算进程时间
{
int k;
for(k=0;k<=N-1;k++)
{
if(k==0)
{
p[k].starttime=p[k].arrivetime;
p[k].finishtime=p[k].arrivetime+p[k].servicetime;
}
else
{
p[k].starttime=p[k-1].finishtime;
p[k].finishtime=p[k-1].finishtime+p[k].servicetime;
}
}
for(k=0;k<=N-1;k++)
{
p[k].TurnaroundTime=p[k].finishtime-p[k].arrivetime;
}
}
void print(PCB *p,float arrivetime,float servicetime,float starttime,float finishtime,float TurnaroundTime,int N)//进程输出各种时间
{ int k;
printf("运行次序:");
printf("%s",p[0].name);
for(k=1;k<N;k++)
{
printf("-->%s",p[k].name);
}
printf("\n进程的信息:\n");
printf("\n进程名\t到达\t服务\t开始\t完成\t周转\n");
for(k=0;k<=N-1;k++)
{
printf("%s\t%-.2f\t%-.2f\t%-.2f\t%-.2f\t%-.2f\t\n",p[k].name,p[k].arrivetime,p[k].servicetime,p[k].starttime,p[ k].finishtime,p[k].TurnaroundTime);
}
}
void fcfs(PCB *p)//先来先服务调度算法
{
system("cls");
printf("请输入作业数:");
scanf("%d",&N);
while( N < 5) //进程小于5的话,重新选择输入
{
system("cls");
printf("\n\7\7作业数小于5,重新输入:\n");
printf("请输入作业数:");
scanf("%d",&N);
}
createProcess(a);
float arrivetime=0,servicetime=0,starttime=0,finishtime=0,TurnaroundTime=0;
sort(p,N); //排序
running(p,arrivetime,servicetime,starttime,finishtime,TurnaroundTime,N);//模拟运行
print(p,arrivetime,servicetime,starttime,finishtime,TurnaroundTime,N);//打印输入结果
}
PCB *run=NULL,*finish=NULL; //定义三个队列,就绪队列,执行队列和完成队列
ReadyQueue *Head = NULL; //定义第一个就绪队列
int num; //进程个数
int ReadyNum; //就绪队列个数
void Output(); //进程信息输出函数
void InsertFinish(PCB *in); //将进程插入到完成队列尾部
void InsertPrio(ReadyQueue *in); //创建就绪队列,规定优先数越小,优先级越低
void PrioCreate(); //创建就绪队列输入函数
void GetFirst(ReadyQueue *queue); //取得某一个就绪队列中的队头进程
void InsertLast(PCB *in,ReadyQueue *queue); //将进程插入到就绪队列尾部
void ProcessCreate(); //进程创建函数
void RoundRun(ReadyQueue *timechip); //时间片轮转调度算法
void MultiDispatch(); //多级调度算法,每次执行一个时间片
void Output() //进程信息输出函数
{
ReadyQueue *print = Head;
PCB *p;
printf("进程名\t优先级\t轮数\tcpu时间\t需要时间\t进程状态\t计数器\n");
while(print)
{
if(print ->LinkPCB != NULL)
{
p=print ->LinkPCB;
while(p)
{
printf("%s\t%d\t%d\t%d\t%d\t\t%c\t\t%d\n",p->name,p->prio,p->round,p->cputime,p->needtime,p->sta te,p->count);
p = p->next;
}
}
print = print->next;
}
p = finish;
while(p!=NULL)
{
printf("%s\t%d\t%d\t%d\t%d\t\t%c\t\t%d\n",p->name,p->prio,p->round,p->cputime,p->needtime,p->sta te,p->count);
p = p->next;
}
p = run;
while(p!=NULL)
{
printf("%s\t%d\t%d\t%d\t%d\t\t%c\t\t%d\n",p->name,p->prio,p->round,p->cputime,p->needtime,p->state,p->count);
p = p->next;
}
}
void InsertFinish(PCB *in) //将进程插入到完成队列尾部
{
PCB *fst;
fst = finish;
if(finish == NULL)
{
in->next = finish;
finish = in;
}
else
{
while(fst->next != NULL)
{
fst = fst->next;
}
in ->next = fst ->next;
fst ->next = in;
}
}
void InsertPrio(ReadyQueue *in) //创建就绪队列,规定优先数越小,优先级越低
{
ReadyQueue *fst,*nxt;
fst = nxt = Head;
if(Head == NULL) //没有队列,则为第一个元素
{
in->next = Head;
Head = in;
}
else //查到合适的位置进行插入
{
if(in ->prio >= fst ->prio) //比第一个还要大,则插入到队头
{
in->next = Head;
Head = in;
}
else
{
while(fst->next != NULL) //移动指针查找第一个别它小的元素的位置进行插入
{
nxt = fst;
fst = fst->next;
}
if(fst ->next == NULL) //已经搜索到队尾,则其优先级数最小,将其插入到队尾即可
{
in ->next = fst ->next;
fst ->next = in;
}
else //入到队列中
{
nxt = in;
in ->next = fst;
}
}
}
}
void PrioCreate() //创建就绪队列输入函数
{
ReadyQueue *tmp;
int i;
printf("输入就绪队列的个数:");
scanf("%d",&ReadyNum);
printf("输入每个就绪队列的CPU时间片:(一次行输完所有,再按回车结束,如:1 2 3 )\n");
for(i = 0;i < ReadyNum; i++)
{
if((tmp = (ReadyQueue *)malloc(sizeof(ReadyQueue)))==NULL)
{
perror("malloc");
exit(1);
}
scanf("%d",&(tmp->round)); //输入此就绪队列中给每个进程所分配的CPU时间片
tmp ->prio = 50 - tmp->round; //置其优先级,时间片越高,其优先级越低
tmp ->LinkPCB = NULL; //初始化其连接的进程队列为空
tmp ->next = NULL;
InsertPrio(tmp); //照优先级从高到低,建立多个就绪队列
}
}
void GetFirst(ReadyQueue *queue) //取得某一个就绪队列中的队头进程
{
run = queue ->LinkPCB;
if(queue ->LinkPCB != NULL)
{
run ->state = 'R';
queue ->LinkPCB = queue ->LinkPCB ->next;
run ->next = NULL;
}
}
void InsertLast(PCB *in,ReadyQueue *queue) //将进程插入到就绪队列尾部
{
PCB *fst;
fst = queue->LinkPCB;
if( queue->LinkPCB == NULL)
{
in->next = queue->LinkPCB;
queue->LinkPCB = in;
else
{
while(fst->next != NULL)
{
fst = fst->next;
}
in ->next = fst ->next;
fst ->next = in;
}
}
void ProcessCreate() //针对多级反馈队列算法的进程创建函数
{
PCB *tmp;
int i;
printf("请输入作业数:");
scanf("%d",&num);
if( num < 5)
{
system("cls");
printf("\n\7\7作业数小于5,重新输入:\n");
ProcessCreate();
}
printf("输入进程名字和进程所需时间:(一次性输完,再按回车结束如:a 1 b 2 c 3 d 4 e 5)\n");
for(i = 0;i < num; i++)
{
if((tmp = (PCB *)malloc(sizeof(PCB)))==NULL)
{
perror("malloc");
exit(1);
}
scanf("%s",tmp->name);
getchar();
scanf("%d",&(tmp->needtime));
tmp ->cputime = 0;
tmp ->state ='W';
tmp ->prio = 50 - tmp->needtime; //置其优先级,需要的时间越多,优先级越低
tmp ->round = Head ->round;
tmp ->count = 0;
InsertLast(tmp,Head); //照优先级从高到低,插入到就绪队列
}
void RoundRun(ReadyQueue *timechip) //时间片轮转调度算法{
int flag = 1;
GetFirst(timechip);
while(run != NULL)
{
while(flag)
{
run->count++;
run->cputime++;
run->needtime--;
if(run->needtime == 0)
{
run ->state = 'F';
InsertFinish(run);
flag = 0;
}
else if(run->count == timechip ->round)//间片用完
{
run->state = 'W';
run->count = 0; //数器清零,为下次做准备
InsertLast(run,timechip);
flag = 0;
}
}
flag = 1;
GetFirst(timechip);
}
}
void MultiDispatch() //多级调度算法,每次执行一个时间片{
int flag = 1;
int k = 0;
system("cls");
printf("您选择的是多级反馈队列算法\n");
PrioCreate(); //建就绪队列
ProcessCreate();//创建就绪进程队列
ReadyQueue *point;
point = Head;
GetFirst(point);
while(run != NULL)
{
Output();
if(Head ->LinkPCB!=NULL)
point = Head;
while(flag)
{
run->count++;
run->cputime++;
run->needtime--;
if(run->needtime == 0) //程执行完毕
{
run ->state = 'F';
InsertFinish(run);
flag = 0;
}
else if(run->count == run->round)//间片用完
{
run->state = 'W';
run->count = 0; //数器清零,为下次做准备
if(point ->next!=NULL)
{
run ->round = point->next ->round;//置其时间片是下一个就绪队列的时间片
InsertLast(run,point->next); //进程插入到下一个就绪队列中
flag = 0;
}
else
{
RoundRun(point); //果为最后一个就绪队列就调用时间片轮转算法
break;
}
}
++k;
if(k == 3)
{
ProcessCreate();
}
}
flag = 1;
if(point ->LinkPCB == NULL)//绪队列指针下移
point =point->next;
if(point ->next ==NULL)
{
RoundRun(point);
break;
}
GetFirst(point);
}
Output();
}
void opration()
{
int select;
system("cls");
printf("\n\n\n\t\t\t请选择调度方式:\n");
printf("\t\t\t===========================\n");
printf("\t\t\t1.先来先服务调度");
printf("\n\t\t\t2.多级反馈队列调度");
printf("\n\t\t\t3.退出\n");
printf("\t\t\t===========================\n");
printf("按数字1、2、3 选择操作:");
scanf("%d",&select);
switch(select)
{
case 1:
fcfs(a);
printf("请按任意键继续。
");
getch();
system("cls");
opration();
break;
case 2:
MultiDispatch();/*算法开始*/
printf("\n");
printf("请按任意键继续。
");
getch();
system("cls");
opration();
break;
case 3:
printf("退出\n");
Sleep(1000);//系统延时两秒,自动退出
break;
default:
printf("\t\t选择错误,请重新选择:");
getch();
system("cls");
opration();
}
}
void main() //主函数
{
opration();
}
4.系统运行结果截图
五:课程设计体会
处理机调度问题实际上是处理机分配问题。
只有那些参与竞争处理机所必须的资源都已得到满足的进程才能享受竞争处理机的资格,这时它们处于内存就绪状态。
这些必须的资源包括内存、外设及有关数据结构等。
作业调度程序必须先调用存储管理、外设管理,分配资源,让它们能有竞争资格。
为了提高资源利用率,一部分在内存中处于就绪、等待状态而短期内不能执行进程、作业换出内存,所以外存中除了处于后备状态的作业,还有处于就绪状态的作业。
这就需要一定的方法和策略来为这部分作业分配空间。
上学期学习过《操作系统原理》课程,通过这次课程设计的训练,使我更好地掌握操作系统的原理及实现方法,加深对操作系统基础理论和重要算法的理解。