重庆理工大学 进程调度算法模拟 操作系统课程设计报告.docx
《重庆理工大学 进程调度算法模拟 操作系统课程设计报告.docx》由会员分享,可在线阅读,更多相关《重庆理工大学 进程调度算法模拟 操作系统课程设计报告.docx(82页珍藏版)》请在冰豆网上搜索。
重庆理工大学进程调度算法模拟操作系统课程设计报告
《操作系统原理及应用》课程设计报告
进程调度算法模拟
学院(系):
计算机科学与工程学院
班级:
学号11403070
学生姓名:
同组人员:
时间:
从2016年12月27日到2017年01月03日
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)结构体
/***先来先服务调度算法结构体***/
structfcfs{
charname[10];//作业名
floatarrivetime;//作业到达时间
floatservicetime;//作业服务时间
floatstarttime;//作业开始时间
floatfinishtime;//作业完成时间
floatzztime;//周转时间
floatdqzztime;//带权周转时间
};
/***短作业优先调度算法结构体***/
structjcb//作业控制块JCB,定义为结构体
{
charname[10];//作业名
floatarrivetime;//作业到达时间
floatservicetime;//作业服务时间
floatstarttime;//作业开始时间
floatfinishtime;//作业完成时间
floatzztime;//周转时间
floatdqzztime;//带权周转时间
};
/***时间片轮转调度算法结构体***/
structrr{//定义时间片轮转调度算法结构体,里面包含得有一个进程相关的信息
charname[10];//作业名
floatarrivetime;//作业到达时间
floatservicetime;//作业服务时间
floatstarttime;//作业开始时间
floatfinishtime;//作业结束时间
floatzztime;//作业周转时间
floatdqzztime;//作业带权周转时间
floatavzztime;//作业平均周转时间
floatavdqzztime;//作业平均带权周转时间
floatlefttime;//剩余时间
floatstoptime;//停止时间
inttimeprice;//时间片设置的大小
};
/***静态优先级调度算法结构体***/
structsp{
charname[10];//作业号
floatarrivetime;//作业到达时间
floatservicetime;//服务时间
floatwaittime;//等待时间
floatstarttime;//开始运行时间
floatfinishtime;//结束运行时间
floatzztime;//周转时间
floatdqzztime;//带权周转时间
floatpriority;//优先权
floatfinish;//是否已经完成
}sta[10];//作业控制块,这是一个结构体数组
/***最高响应比调度算法结构体***/
structtask{
charname[10];//作业号
floatarrivetime;//作业到达时间
floatservicetime;//服务时间
floatwaittime;//等待时间
floatstarttime;//开始运行时间
floatfinishtime;//结束运行时间
floatzztime;//周转时间
floatdqzztime;//带权周转时间
floatpriority;//优先权
floatfinish;//是否已经完成
}JCB[10];//作业控制块,这是一个结构体数组
(2)基本变量
charname[10];//作业名
floatarrivetime;//作业到达时间
floatservicetime;//作业服务时间
floatstarttime;//作业开始时间
floatfinishtime;//作业完成时间
floatzztime;//周转时间
floatdqzztime;//带权周转时间
floatavzztime;//作业平均周转时间
floatavdqzztime;//作业平均带权周转时间
floatlefttime;//剩余时间
floatstoptime;//停止时间
inttimeprice;//时间片设置的大小
floatpriority;//优先权
floatfinish;//是否已经完成
5.具体实现
5.1菜单选择模块
(1)功能说明
按照工作台提示,选择调度算法。
(2)函数实现过程
(3)关键程序
charMenu()//用来输出相关信息的函数
{
charchoice;//用户选择
while
(1)
{
system("cls");//清屏
fflush(stdin);//清空缓存
cout<cout<cout<cout<cout<<"\t"<<""<<"\t************进程调度算法模拟*************"<<"\t\t"<<""<cout<<"\t"<<""<cout<<"\t"<<""<<"\t*\t1.先来先服务调度算法"<<"\t*\t"<<""<cout<<"\t"<<""<cout<<"\t"<<""<<"\t*\t2.短作业优先调度算法"<<"\t*\t"<<""<cout<<"\t"<<""<cout<<"\t"<<""<<"\t*\t3.时间片轮转调度算法"<<"\t\t*\t"<<""<cout<<"\t"<<""<cout<<"\t"<<""<<"\t*\t4.静态优先级调度算法"<<"\t\t*\t"<<""<cout<<"\t"<<""<cout<<"\t"<<""<<"\t*\t5.最高响应比优先调度算法"<<"\t*\t"<<""<cout<<"\t"<<""<cout<<"\t"<<""<<"\t*\t0.退出系统"<<"\t*\t"<<""<cout<<"\t"<<""<<"\t*****************************************"<<"\t\t"<<""<cout<cout<<"\t\t请输入您的选择(0/1/2/3/4/5):
"<choice=getchar();
if(choice<'0'||choice>'5')//若输入有误
{
cout<cout<<"您的输入有误!
请重新输入正确的字符!
"<cout<system("PAUSE");//输出“按任意键继续”,等待用户按一个键,然后返回主菜单
}
else
break;
}
returnchoice;
}
5.2调度算法模块
(1)先来先服务调度算法
a、功能说明
按照先来先服务原则调度用户输入的进程
b、函数实现过程
c、关键程序
voidDealByFCFS(fcfs*p,floatarrivetime,floatservicetime,floatstarttime,floatfinishtime,float&zztime,float&dqzztime,intN)//运行阶段,根据先来先服务的原则进行处理
{
intk;
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;//带权周转时间=周转时间/服务时间
}
}
voidFCFS(fcfs*p,intN)
{
floatsumzztime=0,sumdqzztime=0,avzztime,avdqzztime;//总的周转时间、总的带权周转时间、平均周转时间、平均带权周转时间
floatarrivetime=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(intk=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、关键程序
voidDealBySJF(jcb*p,floatarrivetime,floatservicetime,floatstarttime,floatfinishtime,float&zztime,float&dqzztime,intN)//按短作业优先原则进行进程服务处理
{
intk;
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;//带权周转时间=周转时间/服务时间
}
}
voidSJF(jcb*p,intN)//短作业优先调度算法处理过程
{
floatsumzztime=0,sumdqzztime=0,avzztime,avdqzztime;//总的周转时间、总的带权周转时间、平均周转时间、平均带权周转时间
floatarrivetime=0,servicetime=0,starttime=0,finishtime=0,zztime=0,dqzztime=0;
Sort(p,N);//按进程的到达时间进行排序(参数为存放作业的数组和作业个数)
for(intm=0;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;//完成时间=前一个作业的完成时间+服务时间
inti=0;
for(intn=m+1;n<=N-1;n++)
{
if(p[n].arrivetime<=p[m].finishtime)//找出服务时间较短的作业的个数i
i++;
}
floatmin=p[m+1].servicetime;//min为服务时间最短的作业,先将服务时间较短的作业队列中的第一个付给min
intnext=m+1;//m+1=n,next为服务时间最短的作业序号
for(intk=m+1;k{
if(p[k+1].servicetime{
min=p[k+1].servicetime;//第k+1个作业为新的服务时间最短的作业
next=k+1;
}
}
jcbtemp;
//第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(intk=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、