一、实验目的
本实验的目的是通过作业或进程调度算法模拟设计,进一步加深对作业或进程调度算法的理解,通过计算平均周转时间和带权平均周转时间,进一步加深对算法的评价方法的理解。
二、实验预备内容
-
掌握作业或进程调度算法
-
平均周转时间和带权平均周转时间计算。
三、实验内容
设定一组作业或进程,给定相关参数,对这组进程或作业按照调度算法实时调度,输出调度次序,并计算平均周转时间和带权平均周转时间,使用的调度算法有:
- 先来先服务调度算法;
- 优先级调度算法;
- 短作业(或进程)优先调度算法;
- 响应比高优先调度算法。
四、分析设计
1.提示:使用的主要数据结构
- 定义一个结构体,结构体的主要成员有序号、作业(进程)号或名称、提交时间、运行时间、优先数、进入输入井时间、开始运行时间、尚需运行时间、运行结束时间、周转时间、带权周转时间和运行次序等。
- 利用定义的结构体,定义一个结构体数组,用来记录系统中的作业或进程。
主控程序算法、数据输入算法、数据输出算法、先来先服务调度算法、响应比高优先调度算法、优先级调度算法和短作业(或进程)优先调度算法描述分别如图10.2至图10.8所示。
2.文件的结构
3.基础部分
- 结构体:
struct process {
int serial;//序号
char name;//进程名
int num;//进程号
float submit;//提交时间
float runtime;//运行时间
int priority;//优先级
float starttime;//开始运行时间
float endtime;//最终结束时间
float Turnaround;//周转时间,endtime-submit
float Wturnaround;//带权周转时间,Turnaround/runtime
int sort;//运行状态,运行次序,非0即为已经运行
};
- 模拟进程调度数据初始化及打印
void initproc(struct process p[]){
int i;
char flag='A';
float time;
int priority;
for( i=1;i<=4;i++){
p[i].serial=i;
p[i].name=flag;
flag++;
p[i].num=i;
printf("the time of %dth process's submit is :\n",i);
scanf("%f",&time);
p[i].submit=time;
printf("the time of %dth process's runtime is :\n",i);
scanf("%f",&time);
p[i].runtime=time;
printf("the priority of %dth process is :\n",i);
scanf("%d",&priority);
p[i].priority=priority;
p[i].sort=0;
p[i].starttime=0;
p[i].endtime=0;
p[i].Turnaround=0;
p[i].Wturnaround=0;
}
}
void Print(struct process p[]){
printf("%s\t%s\t%s\t%s\t%s\t%s %s %s\t%s\t%s\t%s\n","serial","name","num","submit","runtime","priority","starttime","endtime","Turnaround","Wturnaround","sort");
int i;
for(i=1;i<=4;i++){
printf("%d\t%c\t%d\t%.2f\t%.2f\t%d\t %.2f\t %.2f\t%.2f\t\t%.2f\t\t%d\n",p[i].serial,p[i].name,p[i].num,p[i].submit,p[i].runtime,p[i].priority,p[i].starttime,p[i].endtime,p[i].Turnaround,p[i].Wturnaround,p[i].sort);
}
}
- 主函数
int main(void){
char i,j;
struct process p[5];
printf("select dispatch of process: 1.(FCFS)2.(PS) 3.(JSF) 4.(HRRN) 0.(exit)\n");
while(i=getchar()){
if(i=='0'){
printf("exit");
exit(0);
}
switch(i){
case '1':
printf("-------------------(FCFS)-------------------\n");
initproc(p);
Fcfsprocess(p);
Print(p);
break;
case '2':
printf("-------------------(PS)-------------------\n");
initproc(p);
Psprocess(p);
Print(p);
break;
case '3':
printf("------------------------(JSF)------------------------\n");
initproc(p);
Sjfprocess(p);
Print(p);
break;
case '4':
printf("--------------------(HRRN)--------------------\n");
initproc(p);
Hrrnprocess(p);
Print(p);
break;
default:
printf("select dispatch of process: 1.(FCFS)2.(PS) 3.(JSF) 4.(HRRN) 0.(exit)\n");
break;
}
}
return 0;
}
4.调度算法(主要部分)
1.先来先服务(FCFS) void Fcfsprocess(struct process p[])
void Fcfsprocess(struct process p[]){
int i=0,j=0;
int s=1;
float earlytime=0;
float starttime=0;
float endtime=0;
for(i=1;i<5;i++ )
{
earlytime=p[i].submit;
s=i;
for(j=1;j<5;j++)
{
if(p[j].sort!=0){ continue;}//运行过的进程不参与比较
if(earlytime>p[j].submit)
{
earlytime=p[j].submit;
s=j;//优先级s=提交时间最早的p的序号;
}
}
if(i==1){//比较完成后,开始运行
starttime=earlytime;
}
p[s].sort=i;
p[s].starttime=starttime;
endtime=starttime+p[s].runtime;
p[s].endtime=endtime;
p[s].Turnaround=endtime-p[s].submit;
p[s].Wturnaround=p[s].Turnaround/p[s].runtime;
starttime=endtime;
}
}
思想:就是通过比较进程提交时间,确定每个进程的优先级,之后进行相应的运算
即if(earlytime>p[j].submit) {
earlytime=p[j].submit;
s=j;
}
p[s].sort=i;
p[s].starttime=starttime;……//确定开始运行下一进程的进程编号,将进程结构体的数据更新
2.优先调度 void Psprocess(struct process p[]);
void Psprocess(struct process p[]){
int i=0,j=0;
int s=1;//当前应该进行的作业号
float pmin=0;//优先最小的
float starttime=0;
float endtime=0;
for(i=1;i<5;i++ )
{
if(i==1)//初始化提交时间最早的调度为第一个调度
{
starttime=p[i].submit;
}
else
{
for(j=2;j<5;j++)//找出没有运行的调度
{
if((p[j].sort==0) &&(p[j].submit<=starttime))//未运行的且提交时间已经到的进程
{
pmin=p[i].priority;
s=j;
break;//跳出循环
}
}
}//上面一段作用:找出未运行的作业现暂时设为下一个要进行作业
for(j=2;j<5;j++)//找出作业最优
{
if((p[j].sort==0) &&(p[j].submit<=starttime))
{
if(pmin>p[j].priority)
{
pmin=p[j].priority;
s=j;
}
}
}
//比较完成后,开始运行
p[s].sort=i;
p[s].starttime=starttime;
endtime=starttime+p[s].runtime;
p[s].endtime=endtime;
p[s].Turnaround=endtime-p[s].submit;
p[s].Wturnaround=p[s].Turnaround/p[s].runtime;
starttime=endtime;
}
}
思想:就是通过比较进程优先级,确定每个进程的优先级,之后进行相应的运算
即if(pmin>p[j].priority) {
pmin=p[j].priority;
s=j;
}
p[s].sort=i;;
p[s].starttime=starttime;……//确定开始运行下一进程的进程编号,将进程结构体的数据更新
3.短作业(JSF)void Sjfprocess(struct process p[])
void Sjfprocess(struct process p[]){
int i=0,j=0;
int s=1;
float runtime=0;
float starttime=0;
float endtime=0;
for(i=1;i<5;i++ )
{
if(i==1)//初始化提交时间最早的调度为第一个调度
{
starttime=p[i].submit;
for(j=2;j<5;j++)
{
if(starttime>p[j].submit){
starttime=p[j].submit;
s=j;//优先级s=提交时间最早的p的序号;
}
}
}
else
{
for(j=2;j<5;j++)//找出没有运行的调度
{
if((p[j].sort==0) &&(p[j].submit<=starttime))//未运行的且提交时间已经到的
{
runtime=p[i].runtime;
s=j;
break;//跳出循环
}
}
for(j=2;j<5;j++)//找出段作业最优调度
{
if((p[j].sort==0) &&(p[j].submit<=starttime))
{
if(runtime>p[j].runtime)
{
s=j;
}
}
}
}
//比较完成后,开始运行
p[s].sort=i;
p[s].starttime=starttime;
endtime=starttime+p[s].runtime;
p[s].endtime=endtime;
p[s].Turnaround=endtime-p[s].submit;
p[s].Wturnaround=p[s].Turnaround/p[s].runtime;
starttime=endtime;
}
}
思想:比较在未运行的作业中选择运行时间最短的作业
即:if(runtime>p[j].runtime){s=j;}//比较选出算法的作业
p[s].priority=i;……//将运行次序填上,计算其他相应数据
4.响应比高者(HRRN)void Hrrnprocess(struct process p[])
void Hrrnprocess(struct process p[]){
int i=0,j=0;
int s=1;
float respone=0;//响应比
float starttime=0;
float endtime=0;
for(i=1;i<5;i++ ){
if(i==1)//初始化模拟数据提交时间最早的调度为第一个调度,后来思考认为实际调度,第一个调度就为提交时间最早的,因此一号进程为第一个运行
{
s=i;
starttime=p[i].submit;
}
else
{
for(j=2;j<5;j++)//找出没有运行的调度,第一个进程不用比较
{
if((p[j].sort==0) &&(p[j].submit<=starttime))//符合则为下一个调度
{
respone=(starttime-p[j].submit+p[j].runtime)/p[j].runtime;//(等待时长+运行时长)/运行时长
s=j;
break;//跳出循环
}
}
for(j=2;j<5;j++)//找出响应比高的作业最优调度
{
if((p[j].sort==0) &&(p[j].submit<=starttime))//未运行的且提交时间已经到的
{
float rs=(starttime-p[j].submit+p[j].runtime)/p[j].runtime;
if(respone<rs)
{
respone=rs;
s=j;
}
}
}
}
//比较完成后,开始运行
p[s].sort=i;
p[s].starttime=starttime;
endtime=starttime+p[s].runtime;
p[s].endtime=endtime;
p[s].Turnaround=endtime-p[s].submit;
p[s].Wturnaround=p[s].Turnaround/p[s].runtime;
starttime=endtime;
}
}
思想:在未运行的作业中选择一个响应比最高的作业进行作业
即:float rs=(starttime-p[j].submit+p[j].runtime)/p[j].runtime;
if(respone<rs)
{
respone=rs;
s=j;
}