操作系统课程设计报告-进程调度算法模拟
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1.课程设计的目的
《操作系统原理》课程设计我们专业实践性环节之一,是学习完《操作系统原理》课程后进行的一次较全面的综合练习。
其目的在于加深对操作系统的理论、方法和基础知识的理解,掌握操作系统结构、实现机理和各种典型算法,系统地了解操作系统的设计和实现思路,培养学生的系统设计能力,并了解操作系统的发展动向和趋势。
2.课程设计的内容及要求
先来先服务、短作业优先、时间片轮转、基于静态优先级的调度,基于高响应比优先的动态优先级调度算法实现,能够输出调度情况,并计算周转时间和平均周转时间。
要求使用链表,进程个数由用户提供,按照进程的实际个数生成PCB,程序能够让用户选择使用哪种调度算法,能够在Linux环境运行并验证结果。
程序要考虑用户界面的友好性和使用方便性。
进程基本信息可从文件读入,也可手动输入。
3、设计原理
3.1先来先服务调度算法
每次调度都是从后备作业队列中选择一个或多个最先进入该队列的作业,将它们调入内存,为它们分配资源创建进程,然后放入就绪队列
3.2短作业优先调度算法
短作业优先调度算法是从就绪队列中选出一个估计运行时间最短的进程,将处理机分配给它,使它立即执行并一直执行到完成,或发生某事件而被阻塞放弃处理机时再重新调度。
3.3时间片轮转调度算法
系统将所有的就绪进程按先来先服务的原则排成一个队列,每次调度时,把CPU分配给队首进程,并令其执行一个时间片。
时间片的大小从几ms到几百ms。
当执行的时间片用完时,由一个计时器发出时钟中断请求,调度程序便据此信号来停止该进程的执行,并将它送往就绪队列的末尾;然后,再把处理机分配给就绪队列中新的队首进程,同时也让它执行一个时间片。
3.4静态优先级调度算法
把处理机分配给优先级最高的进程,使之执行。
但在其执行期间,只要出现了另一个比其优先级更高的进程,调度程序就将处理机分配给新到的优先级最高的进程。
这样就可以保证紧迫性作业优先运行。
3.5最高响应比优先的动态优先级调度算法
优先权调度算法是为了照顾紧迫型作业,使之在进入系统后便获得优先处理,引入最高优先权优先调度算法。
动态优先权是指在创建进程时所赋予的优先权,是可以随进程的推进或随其等待时间的增加而改变的,以便获得更好的调度性能。
4.设计说明
4.1结构设计
(1) 菜单选择模块。
选择相应的进程调度方式,选择相应的数字,进入相应的功能。
(2) 调度算法模块。
选择相应的进程调度算法。
(3) 显现输出模块。
显示每种进程调度算法情况。
(4) 平均周转时间与平均带权周转时间的计算结果。
(5) 退出系统模块。
4.2功能设计
(1)菜单选择模块
设计方案:首先将各种进程调度算法放入不同的头文件,在主函数引用,是系统结构更加清晰。
实现方法:设置一个menu()方法,让用户选择不同的进程调度算法,menu()方法返回一个char类型字符,以便在主函数的switch语句中选择调用不同的进程调度方法。
(2)调度算法模块
A、先来先服务调度算法
设计方案:对于先到达的进程优先分配CPU,按照先来先服务的原则依次执行各进程。
实现方法:每次调度都是从后备作业队列中选择一个或多个最先进入该队列的作业,将它们调入内存,为它们分配资源创建进程,然后放入就绪队列
B、短作业优先调度算法
设计方案:短作业优先调度算法是从就绪队列中选出一个估计运行时间最短的进程,将处理机分配给它,使它立即执行并一直执行到完成,或发生某事件而被阻塞放弃处理机时再重新调度。
实现方法:先找到运行时间最短的程序,然后执行,再从剩余的程序中找到运行时间最短的在执行,依次每次都执行运行时间最短的,直到程序执行完毕。
C、时间片轮转调度算法
设计方案:系统将所有的就绪进程按先来先服务的原则排成一个队列,每次调度时,把CPU分配给队首进程,并令其执行一个时间片。
时间片的大小从几ms到几百ms。
当执行
的时间片用完时,由一个计时器发出时钟中断请求,调度程序便据此信号来停止该进程的执行,并将它送往就绪队列的末尾;然后,再把处理机分配给就绪队列中新的队首进程,同时也让它执行一个时间片。
实现方法:按照轮转的次序分配给每个程序一定的时间执行,执行完成后执行后面的进程,依次循环执行直到所有进程执行完成。
D、静态优先级调度算法
设计方案:把处理机分配给优先级最高的进程,使之执行。
但在其执行期间,只要出现了另一个比其优先级更高的进程,调度程序就将处理机分配给新到的优先级最高的进程。
这样就可以保证紧迫性作业优先运行。
实现方法:按照优先级从高到低依次执行程序。
E、最高响应比优先的动态优先级调度算法
设计方案:优先权调度算法是为了照顾紧迫型作业,使之在进入系统后便获得优先处理,引入最高优先权优先调度算法。
动态优先权是指在创建进程时所赋予的优先权,是可以随进程的推进或随其等待时间的增加而改变的,以便获得更好的调度性能。
实现方法:按照优先级从高到低依次执行程序。
(3)平均周转时间与平均带权周转时间的计算
设计方案:周转时间=完成时间-到达时间
带权周转时间=周转时间/服务时间
平均周转时间=总的周转时间/进程个数
平均带权周转时间=总的带权周转时间/进程个数
实现方法:系统自行根据程序及输入的数据计算出平均周转时间和平均带权周转时
4.3程序中使用的数据结构及使用的变量说明和作用
(1)结构体
/***先来先服务调度算法结构体***/
struct fcfs{
char name[10]; //作业名
float arrivetime; //作业到达时间
float servicetime; //作业服务时间
float starttime; //作业开始时间
float finishtime; //作业完成时间
float zztime; //周转时间
float dqzztime; //带权周转时间
};
/***短作业优先调度算法结构体***/
struct jcb //作业控制块JCB,定义为结构体
{
char name[10]; //作业名
float arrivetime; //作业到达时间
float servicetime;//作业服务时间
float finishtime; //作业完成时间
float zztime; //周转时间
float dqzztime; //带权周转时间
};
/***时间片轮转调度算法结构体***/
struct rr{ //定义时间片轮转调度算法结构体,里面包含得有一个进程相关的信息char name[10]; //作业名
float arrivetime; //作业到达时间
float servicetime; //作业服务时间
float starttime; //作业开始时间
float finishtime; //作业结束时间
float zztime; //作业周转时间
float dqzztime; //作业带权周转时间
float avzztime; //作业平均周转时间
float avdqzztime; //作业平均带权周转时间
float lefttime; //剩余时间
float stoptime; //停止时间
int timeprice; //时间片设置的大小
};
/***静态优先级调度算法结构体***/
struct sp {
char name[10]; //作业号
float arrivetime; //作业到达时间
float servicetime; //服务时间
float waittime; //等待时间
float starttime; //开始运行时间
float finishtime; //结束运行时间
float zztime; //周转时间
float dqzztime; //带权周转时间
float priority; //优先权
float finish; //是否已经完成
}sta[10];//作业控制块,这是一个结构体数组
/***最高响应比调度算法结构体***/
struct task {
char name[10]; //作业号
float arrivetime; //作业到达时间
float servicetime; //服务时间
float waittime; //等待时间
float finishtime; //结束运行时间
float zztime; //周转时间
float dqzztime; //带权周转时间
float priority; //优先权
float finish; //是否已经完成
}JCB[10];//作业控制块,这是一个结构体数组(2)基本变量
char name[10]; //作业名
float arrivetime; //作业到达时间
float servicetime; //作业服务时间
float starttime; //作业开始时间
float finishtime; //作业完成时间
float zztime; //周转时间
float dqzztime; //带权周转时间
float avzztime; //作业平均周转时间
float avdqzztime; //作业平均带权周转时间float lefttime; //剩余时间
float stoptime; //停止时间
int timeprice; //时间片设置的大小
float priority; //优先权
float finish; //是否已经完成
5.具体实现
5.1菜单选择模块
(1)功能说明
按照工作台提示,选择调度算法。
(2)函数实现过程
(3)关键程序
char Menu()//用来输出相关信息的函数
{
char choice;//用户选择
while(1)
{
system("cls");//清屏
fflush(stdin);//清空缓存
cout<<endl;
cout<<endl;
cout<<endl;
cout<<endl;
cout<<"\t"<<" "<<"\t************进程调度算法模拟*************"<<"\t\t"<<" "<<endl;
cout<<"\t"<<" "<<endl;
cout<<"\t"<<" "<<"\t*\t 1.先来先服务调度算法"<<"\t*\t"<<" "<<endl;
cout<<"\t"<<" "<<endl;
cout<<"\t"<<" "<<"\t*\t 2.短作业优先调度算法"<<"\t*\t"<<" "<<endl;
cout<<"\t"<<" "<<endl;
cout<<"\t"<<" "<<"\t*\t 3.时间片轮转调度算法"<<"\t\t*\t"<<" "<<endl;
cout<<"\t"<<" "<<endl;
cout<<"\t"<<" "<<"\t*\t 4.静态优先级调度算法"<<"\t\t*\t"<<" "<<endl;
cout<<"\t"<<" "<<endl;
cout<<"\t"<<" "<<"\t*\t 5.最高响应比优先调度算法"<<"\t*\t"<<" "<<endl;
cout<<"\t"<<" "<<endl;
cout<<"\t"<<" "<<"\t*\t 0.退出系统"<<"\t*\t"<<" "<<endl;
cout<<"\t"<<"
"<<"\t*****************************************"<<"\t\t"<<" "<<endl;
cout<<endl;
cout<<"\t\t 请输入您的选择(0/1/2/3/4/5):"<<endl;
choice=getchar();
if(choice<'0'||choice>'5')//若输入有误
{
cout<<endl;
cout<<"您的输入有误!请重新输入正确的字符! "<<endl;
cout<<endl;
system("PAUSE");//输出“按任意键继续”,等待用户按一个键,然后返回主菜单}
else
break;
}
return choice;
}
5.2调度算法模块
(1)先来先服务调度算法
a、功能说明
按照先来先服务原则调度用户输入的进程
b、函数实现过程
c、关键程序
void DealByFCFS(fcfs *p, float arrivetime,float servicetime,float starttime,float finishtime,float &zztime,float &dqzztime,int N)//运行阶段,根据先来先服务的原则进行处理
{
int k;
for(k=0;k<=N-1;k++)
{
if(k==0)//进程个数为1
{
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].zztime=p[k].finishtime-p[k].arrivetime; //周转时间=完成时间-到达时间
p[k].dqzztime=p[k].zztime/p[k].servicetime; //带权周转时间=周转时间/服务时间}
}
void FCFS(fcfs *p,int N)
{
float sumzztime=0, sumdqzztime=0, avzztime, avdqzztime;//总的周转时间、总的带权周转时间、平均周转时间、平均带权周转时间
float arrivetime=0, servicetime=0, starttime=0, finishtime=0, zztime=0, dqzztime=0;
Sort(p,N);//按进程的到达时间进行排序(参数为存放进程的数组和进程个数)
DealByFCFS(p,arrivetime,servicetime,starttime,finishtime,zztime,dqzztime,N);//运行阶
段,根据先来先服务的原则进行处理
Print(p,arrivetime,servicetime,starttime,finishtime,zztime,dqzztime,N); //屏幕输出处理for(int k=0; k<=N-1; k++)
{
sumzztime=sumzztime+p[k].zztime;//总的周转时间=前一个作业的周转时间+本次作业的周转时间(循环加)
sumdqzztime=sumdqzztime+ p[k].dqzztime;//总的带权周转时间=前一个作业的带权周转时间+本次作业的带权周转时间(循环加)
}
avzztime=sumzztime/N;//平均周转时间=总的周转时间/进程个数
printf("*
*\n");
printf("*该算法的平均周转时间为:%-.2f\t",avzztime);
avdqzztime= sumdqzztime/N; //平均带权周转时间=总的带权周转时间/进程个数
printf("该算法的平均带权周转时间为:%-.2f\t *",avdqzztime);
printf("\n***************************************************************** **************\n ");
}
(2)短作业优先调度算法
a、功能说明
按照短作业优先原则调度用户输入的进程
b、函数实现过程
c、关键程序
void DealBySJF(jcb *p,float arrivetime,float servicetime,float starttime,float finishtime,float &zztime,float &dqzztime,int N) //按短作业优先原则进行进程服务处理
{
int k;
for(k=0; k<=N-1; k++)
{
if(k==0)//进程个数为1
{
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].zztime=p[k].finishtime-p[k].arrivetime;//周转时间=完成时间-到达时间
p[k].dqzztime=p[k].zztime/p[k].servicetime;//带权周转时间=周转时间/服务时间}
}
void SJF(jcb *p,int N) //短作业优先调度算法处理过程
{
float sumzztime=0, sumdqzztime=0,avzztime,avdqzztime;//总的周转时间、总的带权周转时间、平均周转时间、平均带权周转时间
float arrivetime=0,servicetime=0,starttime=0,finishtime=0,zztime=0,dqzztime=0;
Sort(p,N); //按进程的到达时间进行排序(参数为存放作业的数组和作业个数)
for(int m=0; m<N-1; m++)
{
if(m==0) //进程个数为0
p[m].finishtime=p[m].arrivetime+p[m].servicetime; //完成时间=到达时间+服务时间
else
p[m].finishtime=p[m-1].finishtime+p[m].servicetime; //完成时间=前一个作业的完成时间+服务时间
int i=0;
for(int n=m+1;n<=N-1;n++)
{
if(p[n].arrivetime<=p[m].finishtime) //找出服务时间较短的作业的个数i
i++;
}
float min=p[m+1].servicetime;//min为服务时间最短的作业,先将服务时间较短的作业队列中的第一个付给min
int next=m+1;//m+1=n ,next为服务时间最短的作业序号
for(int k=m+1;k<m+i;k++) //在i个服务时间较短的作业队列中找出服务时间最短的作业
{
if(p[k+1].servicetime<min) //再从剩余的作业中找出运行时间最短的,从队列中第二个作业开始比较
{
min=p[k+1].servicetime; //第k+1个作业为新的服务时间最短的作业
next=k+1;
}
}
jcb temp;
//第m+1个作业的服务时间小于第k+1个,所以交换顺序
temp=p[m+1];
p[m+1]=p[next];
p[next]=temp;
}
//找到了服务时间最短的作业后
DealBySJF(p,arrivetime,servicetime,starttime,finishtime,zztime,dqzztime,N);//按短作业优先原则进行进程服务处理
Print(p,arrivetime,servicetime,starttime,finishtime,zztime,dqzztime,N);//屏幕输出处理
for(int k=0; k<=N-1; k++)
{
sumzztime=sumzztime+p[k].zztime;//总的周转时间=前一个作业的周转时间+本次作业的周转时间(循环加)
sumdqzztime=sumdqzztime+ p[k].dqzztime;//总的带权周转时间=前一个作业的带权周转时间+本次作业的带权周转时间(循环加)
}
avzztime=sumzztime/N;//平均周转时间=总的周转时间/进程个数
printf("*
*\n");
printf("*该算法的平均周转时间为:%-.2f\t",avzztime);
avdqzztime= sumdqzztime/N; //平均带权周转时间=总的带权周转时间/进程个数
printf("该算法的平均带权周转时间为:%-.2f\t *",avdqzztime);
printf("\n***************************************************************** **************\n ");
getchar();//此处必须要有这个函数,否则就看不到显示器上面的输出,可以看到的结果只是一闪而过的一个框剪
}
(3)时间片轮转调度算法
a、功能说明
按照时间片轮转原则调度用户输入的进程
b、函数实现过程
c 、关键程序 voi
d Print(rr *p,float arrivetime,float servicetime,float starttime,float finishtime,float
zztime,float dqzztime,int N) //屏幕打印输出处理
{
int k;
printf("*调用时间片轮转调度算法以后进程的调度顺序是: ");
//输出进程调度顺序
printf("%s",p[0].name); //输出第一个
for(k=1;k<N;k++)
{
printf("-->%s",p[k].name); //输出第2到第N
}
cout<<endl; printf("*具体的进程调度信息: *\n");
printf("*
*\n");
printf("* 进程名 到达时间 服务时间 开始时间 结束时间 周转时间 带权周转时间
*\n");
for(k=0;k<=N-1;k++)
{
printf("\t%s\t%-.2f\t %-.2f\t %-.2f\t %-.2f\t %-.2f\t %-.2f\n",p[k].name,
p[k].arrivetime,
p[k].servicetime,p[k].starttime,p[k].finishtime,p[k].zztime,p[k].dqzztime);
}
//getchar();
}
void ptt(rr *p,float arrivetime,float servicetime,float starttime,float finishtime,float
zztime,float dqzztime,float avzztime,float avdqzztime,float lefttime,int timeprice,int N) //时
间片设置处理与程序运行
{
float w=0;//记录作业的停止时间
int c=0;
float stoptime=0; printf("请输入时间片的值:
");
cin>>timeprice;
Sort(p,N); //按进程的到达时间排序
float d[20],h[20];//分别用在服务时间和开始时间
for(int k=0; k<=N-1; k++)
{
d[k]=p[k].servicetime;//将队首进程的服务时间赋给d[k]
if(k==0) //进程个数为1
{
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;//完成时间=前一个作业的完成时间+服务时间
}
h[k]=p[k].starttime;//将队首进程的开始时间赋给d[k]
p[k].lefttime=p[k].servicetime-timeprice;//作业的剩余时间=服务时间-时间片的大小
if(p[k].lefttime>0)//剩余时间>0(服务时间>时间片大小)
{
c=c+1;//记录还未执行完的作业个数
p[k].stoptime=p[k].starttime+timeprice;//停止时间=开始时间+时间片大小
p[k].finishtime=p[k].stoptime;//完成时间=停止时间
}
else//剩余时间<=0(服务时间<=时间片大小)
p[k].stoptime=p[k].finishtime;//停止时间=完成时间
w=p[k].stoptime;//记录作业的停止时间
}
printf("\n***********************************结果如下************************************\n");
printf("*第1轮进程调度信息: *\n");
printf("*
*\n");
printf("* 进程名到达时间服务时间开始时间停止时间剩余时间*\n");
for(k=0; k<=N-1; k++)
{
printf("*\t%s\t%-.2f\t %-.2f\t %-.2f\t %-.2f\t%-.2f\n",p[k].name,p[k].arriv etime, p[k].servicetime,p[k].starttime,p[k].stoptime,p[k].lefttime);
}
getchar();
int i=2;//从第2轮开始,初值为2
while(c>0)//还有未执行完的作业
{
printf("*
*");
printf("\n*第%d 轮具体进程调度信息(时间片为%d ): *\n",i,timeprice);
printf("*
*\n");
printf("* 进程名服务时间开始时间停止时间剩余时间*\n");
for(k=0;k<=N-1;k++)
{
if(p[k].lefttime>0)//剩余时间>0(服务时间>时间片大小)
{
p[k].servicetime=p[k].lefttime;//本次的服务时间=运行一次过后的剩余时间
p[k].starttime=w;//上一个作业的停止时间就是本次作业的开始时间
p[k].finishtime=p[k].starttime+p[k].servicetime;//完成时间=开始时间+服务时间
p[k].lefttime=p[k].servicetime-timeprice;//剩余时间=服务时间-时间片的大小
if(p[k].lefttime>0)//若作业的剩余时间仍>0(服务时间仍>时间片大小)
p[k].stoptime=p[k].starttime+timeprice; //停止时间=开始时间+时间片的大小
if(p[k].lefttime<=0)////剩余时间<=0(服务时间<=时间片大小)
{
c=c-1;//完成一个作业,c减1
p[k].stoptime=p[k].finishtime;//停止时间=完成时间
}
w=p[k].stoptime;//记录作业的停止时间
printf("*\t%s\t%-.2f\t %-.2f %-.2f %-.2f\n",p[k].name,
p[k].servicetime,p[k].starttime,p[k].stoptime,p[k].lefttime);
printf("*
*\n");
}
}
i=i+1;
}
if(c<=0)//所有作业调度完毕
printf("\n*时间片轮转调度过程结束!*\n");
printf("*
*");
for(k=0;k<=N-1;k++) //记录信息
{
p[k].servicetime=d[k];//服务时间
p[k].starttime=h[k];//开始时间
p[k].zztime=p[k].finishtime-p[k].arrivetime;//周转时间=完成时间-到达时间
p[k].dqzztime=p[k].zztime/p[k].servicetime; //带权周转时间=周转时间/服务时间}
}
void tt(rr *p,int N)
{
float sumzztime=0, sumdqzztime=0, avzztime=0, avdqzztime=0;//总的周转时间、总的带权周转时间、平均周转时间、平均带权周转时间
int timeprice=0;//时间片大小
float
arrivetime=0,servicetime=0,starttime=0,finishtime=0,zztime=0,dqzztime=0,lefttime=0;
ptt(p,arrivetime,servicetime,starttime,finishtime,zztime,dqzztime,avzztime,avdqzztime ,lefttime,timeprice,N);//时间片设置处理与程序运行
printf("\n*综合信息为:*\n");
Print(p,arrivetime,servicetime,starttime,finishtime,zztime,dqzztime,N);//屏幕打印输出处理
for(int k=0;k<=N-1;k++)
{
sumzztime=sumzztime+p[k].zztime;//总的周转时间=前一个作业的周转时间+本次作业的周转时间(循环加)
sumdqzztime=sumdqzztime+ p[k].dqzztime;//总的带权周转时间=前一个作业的带权周转时间+本次作业的带权周转时间(循环加)
}
avzztime=sumzztime/N;//平均周转时间=总的周转时间/进程数
printf("*
*\n");
printf("*该算法的平均周转时间为:%-.2f\t",avzztime);
avdqzztime= sumdqzztime/N;//平均带权周转时间=总的带权周转时间/进程数
printf("该算法的平均带权周转时间为:%-.2f\t *",avdqzztime);
printf("\n************************************************************* ******************\n ");
getchar();
}
(4)静态优先级调度算法
a、功能说明
按照优先级调度原则调度用户输入的进程
b
c、关键程序
int prio(int pre) //设置优先权//优先权=(等待时间+服务时间)/服务时间
{
int current=1,i,j;//current为当前作业
for(i=0; i<N1; i++)
{
sta[i].waittime=sta[pre].finishtime-sta[i].arrivetime; //等待时间=上一个作业的完成时间-到达时间
sta[i].priority=(sta[i].waittime+sta[i].servicetime)/sta[i].servicetime;//优先权=(等待时间+服务时间)/服务时间
}
for(i=0; i<N1; i++)
{
if(!sta[i].finish)//未完成
{
current=i; //找到第一个还没完成的作业
break;
}
}
for(j=i; j<N1; j++) //第一个还未完成的作业和后面的作业比较
{
if(!sta[j].finish) //还没完成(运行)
{
if(sta[current].arrivetime<=sta[pre].finishtime) //如果作业在上一个作业完成之前到达
{
if(sta[j].arrivetime<=sta[pre].finishtime && sta[j].priority>sta[current].priority )
current=j;// 找出到达时间在上一个作业完成之前,优先权高的作业}
else //如果作业是在上一个作业完成之后到达
{
if(sta[j].arrivetime<sta[current].arrivetime)
current=j; //找出比较早到达的一个
if(sta[j].arrivetime==sta[current].arrivetime) //如果同时到达
if(sta[j].priority>sta[current].priority)
current=j; //找出优先权高的一个作业,即服务时间比较短的一个//优先权=(等待时间+服务时间)/服务时间
}
}
}
return current;//返回当前作业
}
void run(int i, int n, int pre, int staTime, int endTime)
{
if(n==0)//进程个数为1
{
sta[i].starttime=sta[i].arrivetime; //开始时间=到达时间
sta[i].finishtime=sta[i].starttime+sta[i].servicetime; //完成时间=到达时间+服务时间
sta[i].zztime=sta[i].servicetime;//周转时间=服务时间
sta[i].dqzztime=1.0;
staTime=sta[i].starttime;//记录开始时间
}
else
{
if(sta[i].arrivetime>sta[pre].finishtime)//如果作业在上一个作业完成之后到达
sta[i].starttime=sta[i].arrivetime; //开始时间=到达时间
else//如果作业在上一个作业完成之前到达
sta[i].starttime=sta[pre].finishtime; //开始时间=上一个作业的结束时间sta[i].finishtime=sta[i].starttime+sta[i].servicetime;//完成时间=开始时间+服务时间
sta[i].zztime=sta[i].finishtime-sta[i].arrivetime; //周转时间=完成时间-到达时间
sta[i].dqzztime=sta[i].zztime/sta[i].servicetime; //带权周转时间=周转时间/服务时间
}
if(n==N1-1)//到最后一个作业
endTime=sta[i].finishtime;//结束时间=最后一个作业完成的时间
sta[i].finish=1;//完成!!!!
}
void print(int i,int n)
{
if(n==0)
{
printf("* 名称到达时间服务时间开始时间完成时间周转时间带权周转时间*\n");
}
printf("*%7s%7.1f%10.1f%10.1f%10.1f%11.1f%11.1f *\n",
sta[i].name,sta[i].arrivetime,sta[i].servicetime,
sta[i].starttime,sta[i].finishtime,sta[i].zztime,sta[i].dqzztime);
printf("*
*\n");
}
void spsa( )
{
int i,k;
float staTime, endTime, sumzztime=0.0, sumdqzztime=0.0, avzztime, avdqzztime;
int current=0, n=0, pre=0;
sta[pre].finishtime=0;
for(i=0; i<N1; i++)
{
sta[i].finish=0;//所有作业未完成
}
printf("\n***********************************结果如下************************************\n");
printf("*调用短作业优先调度算法以后进程的调度顺序是:");
//输出进程调度顺序
printf("%s",sta[0].name);//输出第一个
for(k=1;k<N1;k++)
{
printf("-->%s",sta[k].name);//输出第2到第N
}
printf("\n");
printf("*具体的进程调度信息是: *\n");
printf("*
*\n");
for(n=0; n<N1; n++)
{
current=prio(pre);//设置优先权
run(current, n, pre, staTime, endTime);//执行作业
print(current, n);//输出进程信息
pre=current;
}
for(i=0; i<N1; i++)
{
sumzztime+=sta[i].zztime;//计算总的周转时间
sumdqzztime+=sta[i].dqzztime;//计算总的带权周转时间
}
avzztime=sumzztime/N1;//平均周转时间=总的周转时间/进程个数
avdqzztime=sumdqzztime/N1;//平均带权周转时间=总的带权周转时间/进程个数
printf("*该算法的平均周转时间为:%-.2f\t",avzztime);
printf("该算法的平均带权周转时间为:%-.2f\t *",avdqzztime);
printf("\n************************************************************* ******************\n ");
}
(5)最高响应比动态优先级调度算法
a、功能说明
按照最高响应比优先原则调度用户输入的进程
b、函数实现过程
c、关键程序
int HRN(int pre) //设置优先权//优先权=(等待时间+服务时间)/服务时间
{
int current=1,i,j;//current为当前作业
for(i=0; i<N; i++)
{
JCB[i].waittime=JCB[pre].finishtime-JCB[i].arrivetime; //等待时间=上一个作业的完成时间-到达时间
JCB[i].priority=(JCB[i].waittime+JCB[i].servicetime)/JCB[i].servicetime;//优先权=(等待时间+服务时间)/服务时间
}
for(i=0; i<N; i++)
{
if(!JCB[i].finish)//未完成
{
current=i; //找到第一个还没完成的作业
break;
}
}
for(j=i; j<N; j++) //第一个还未完成的作业和后面的作业比较
{
if(!JCB[j].finish) //还没完成(运行)
{
if(JCB[current].arrivetime<=JCB[pre].finishtime) //如果作业在上一个作业完成之前到达
{
if(JCB[j].arrivetime<=JCB[pre].finishtime && JCB[j].priority>JCB[current].priority )
current=j;// 找出到达时间在上一个作业完成之前,优先权高的作业}
else //如果作业是在上一个作业完成之后到达
{
if(JCB[j].arrivetime<JCB[current].arrivetime)
current=j; //找出比较早到达的一个
if(JCB[j].arrivetime==JCB[current].arrivetime) //如果同时到达
if(JCB[j].priority>JCB[current].priority)
current=j; //找出优先权高的一个作业,即服务时间比较短的一个//优先权=(等待时间+服务时间)/服务时间
}
}
}
return current;//返回当前作业
}
void runing(int i, int n, int pre, int staTime, int endTime)
{
if(n==0)//进程个数为1
{
JCB[i].starttime=JCB[i].arrivetime; //开始时间=到达时间
JCB[i].finishtime=JCB[i].starttime+JCB[i].servicetime; //完成时间=到达时间+服务时间
JCB[i].zztime=JCB[i].servicetime;//周转时间=服务时间
JCB[i].dqzztime=1.0;
staTime=JCB[i].starttime;//记录开始时间
}
else
{
if(JCB[i].arrivetime>JCB[pre].finishtime)//如果作业在上一个作业完成之后到达JCB[i].starttime=JCB[i].arrivetime; //开始时间=到达时间
else//如果作业在上一个作业完成之前到达
JCB[i].starttime=JCB[pre].finishtime; //开始时间=上一个作业的结束时间JCB[i].finishtime=JCB[i].starttime+JCB[i].servicetime;//完成时间=开始时间+服务时间
JCB[i].zztime=JCB[i].finishtime-JCB[i].arrivetime; //周转时间=完成时间-到达时间
JCB[i].dqzztime=JCB[i].zztime/JCB[i].servicetime; //带权周转时间=周转时间/服务时间
}
if(n==N-1)//到最后一个作业
endTime=JCB[i].finishtime;//结束时间=最后一个作业完成的时间
JCB[i].finish=1;//完成!!!!
}
void check( )
{
int i;
float staTime, endTime, sumzztime=0.0, sumdqzztime=0.0, avzztime, avdqzztime;
int current=0, n=0, pre=0;
JCB[pre].finishtime=0;
for(i=0; i<N; i++)
{
JCB[i].finish=0;//所有作业未完成
}
printf("\n***********************************结果如下************************************\n");
printf("*具体的进程调度信息是: *\n");
printf("*
*\n");
for(n=0; n<N; n++)
{
current=HRN(pre);//设置优先权
runing(current, n, pre, staTime, endTime);//执行作业
Print(current, n);//输出进程信息
pre=current;
}
for(i=0; i<N; i++)
{
sumzztime+=JCB[i].zztime;//计算总的周转时间
sumdqzztime+=JCB[i].dqzztime;//计算总的带权周转时间
}
avzztime=sumzztime/N;//平均周转时间=总的周转时间/进程个数
avdqzztime=sumdqzztime/N;//平均带权周转时间=总的带权周转时间/进程个数
printf("*该算法的平均周转时间为:%-.2f\t",avzztime);
printf("该算法的平均带权周转时间为:%-.2f\t *",avdqzztime);
printf("\n************************************************************* ******************\n ");
}
6.软件运行环境及限制
VC++ 6.0
7.结果输出及分析
7.1先来先服务调度算法
(1)输入值
(2)运行结果
7.2短作业优先调度算法
(1)输入值
(2)运行结果
7.3时间片轮转调度算法(1)输入值
(2)运行结果
7.4静态优先级调度算法 (1)输入值
(2)运行结果
7.5最高响应比动态优先级调度算法
(1)输入值
(2)运行结果
8.心得体会
经过一周的努力,课程设计基本完成了,这次课程设计培养了我们耐心、慎密、全面地考虑问题的能力,从而加快了问题解决的速度、提高了个人的工作效率,以及锻炼围绕问题在短时间内得以解决的顽强意志。
课程设计是我们专业课程知识综合应用的实践训练,也是为我们以后的工作夯实基础。
通过改程序对操作系统的基础知识了解得更透彻了,同时对磁盘调度的5种算法——先来先服务算法,短作业优先调度算法,时间片轮转调度算法,静态优先级调度算法,最高响应比动态优先级调度算法有了更深刻的理解和掌握,使我能够为进程调度选择适当的算法,提高CPU工作效率。
经过自己的动手操作和同学老师的指导我成功的做出了课程设计自己感到。