操作系统作业调度实验报告
2015-10-14 22:07
281 查看
一、实验名称
作业调度算法实验。
二、实验目标
已知n个作业的进入时间和估计运行时间(以分钟计)
(1)单道环境下,分别用先来先服务调度算法、短作业优先调度算法、响应比高者优先调度算法,求出批作业的平均周转时间和带权平均周转时间;在多道环境(如2道)下,求出这些作业的平均周转时间和带权平均周转时间
(2)就同一批次作业,分别讨论这些算法的优劣;
(3)衡量同一调度算法对不同作业流的性能。
三、实验环境要求
1.PC机。
2.Windows环境。
3.CodeBlocks
四、实验基本原理
(1)先来先服务算法:按照作业提交给系统的先后顺序来挑选作业,先提交的先被挑选。
(2)最短作业优先算法:是以进入系统的作业所提出的“执行时间”为标准,总是优先选取执行时间最短的作业。
( 3)响应比高者优先算法:是在每次调度前都要计算所有被选作业(在后备队列中)的响应比,然后选择响应比最高的作业执行。
(4)两道批处理系统中最短作业优先调度算法:内存中可以进入两个作业,这两个作业按照最短作业优先调度算法调整作业执行的次序。
五、数据结构设计
使用一维数组来保存多个作业Job job[20];,采用的是顺序存储。
使用queue<Jcb *> q保存调度队列里的作业指针。
structDate//时间结构体
{
int hour;//时间的小时
int minute;//时间的分钟
};
struct Jcb//作业结构体,用来描述作业
{
int no;//作业编号
Date enter;//进入时间
int operation;//估计运行时间
Date start;//开始时间
Date over;//结束时间
int turnover;//周转时间
double weighted;//带权周转时间
int state=0;//标记改作业是否进入运行状态
};
六、流程图
单道环境下算法流程图
多道环境下的两道批处理系统中最短作业优先作业调度算法的流程图。
七、源代码
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<algorithm>
#include<queue>
usingnamespace std;
structDate//时间结构体
{
int hour;//时间的小时
int minute;//时间的分钟
};
structJcb//作业结构体,用来描述作业
{
int no;//作业编号
Date enter;//进入时间
int operation;//估计运行时间
Date start;//开始时间
Date over;//结束时间
int turnover;//周转时间
double weighted;//带权周转时间
int state=0;//标记改作业是否进入运行状态
};
//函数声明
voiddisplay(Jcb J[],int n);//输出
voidruning( queue<Jcb *> q,int n);//根据算法将就绪队列排好队后的单道作业的运行主体
voidfcfs( Jcb J[],int n);//先来先服务作业调度
voidsfc(Jcb J[],int n);//最短作业优先作业调度
voidhrfc(Jcb J[],int n);//最高响应比作业调度
voidtext(void (*dispatch)(Jcb J[], int n),Jcb J[],int n,Jcb J1[],int n1, JcbJ2[],int n2);//测试单道环境,不同批次作业,相同算法
voidmulfc(Jcb J[],int n);//两道环境,内存中可以用两个作业,内存中的这两个作业按照作业长短调整作业执行的次序。
//主函数,(1)同一批次作业,分别用先来先服务调度算法、短作业优先调度算法、响应比高者优先调度算法,得到批作业的平均周转时间和带权平均周转时间;(2)同一调度算法对不同作业流的调度。
intmain()
{
int n,n1,n2;
Jcb job[20],job1[20],job2[20];
FILE*p=fopen("example1.txt","r");
fscanf(p, "%d", &n);
//批次一作业
for(int i=0;i<n;i++)
{
job[i].no=i+1;
fscanf(p, "%d%d%d",&job[i].enter.hour, &job[i].enter.minute, &job[i].operation);
}
//批次二作业
fscanf(p, "%d", &n1);
for(int i=0;i<n1;i++)
{
job1[i].no=i+1;
fscanf(p, "%d%d%d",&job1[i].enter.hour, &job1[i].enter.minute, &job1[i].operation);
}
//批次三作业
fscanf(p, "%d", &n2);
for(int i=0;i<n2;i++)
{
job2[i].no=i+1;
fscanf(p, "%d%d%d",&job2[i].enter.hour, &job2[i].enter.minute, &job2[i].operation);
}
fclose(p);
printf("\n--------------------单道环境,同一批次作业,不同算法----------------------\n");
cout<<"先来先服务作业调度:"<<endl;
fcfs(job,n);
cout<<"最短时间优先服务作业调度:"<<endl;
sfc(job,n);
cout<<"最高响应比优先作业调度算法"<<endl;
hrfc(job,n);
printf("\n\n");
printf("------------------------单道环境,不同批次作业,同一算法--------------------\n");
cout<<".............................先来先服务作业调度................................"<<endl;
text(fcfs, job,n,job1,n1,job2,n2);
cout<<".............................最短优先服务作业调度.............................."<<endl;
text(sfc, job,n,job1,n1,job2,n2);
cout<<".............................最高响应比优先服务作业调度:......................."<<endl;
text(hrfc, job,n,job1,n1,job2,n2);
printf("-------------------------------两道环境----------------------------------------\n");
mulfc(job1,n);
printf("-------------------------------------------------------------------------------\n");
return 0;
}
//单道环境,不同批次作业,同一算法
voidtext(void (*dispatch)(Jcb J[], int n),Jcb J[],int n,Jcb J1[],int n1, JcbJ2[],int n2)
{//单道环境,不同批次作业,同一算法
cout<<"批次一作业:"<<endl;
dispatch(J,n);
cout<<"批次二作业:"<<endl;
dispatch(J1,n1);
cout<<"批次三作业:"<<endl;
dispatch(J2,n2);
}
//输出
voiddisplay(Jcb J[],int n)
{
double T=0,W=0;
printf(" 作业 进入时间 估计运行时间(分钟) 开始时间 结束时间 周转时间(分钟)带权周转时间\n");
for(int i=0;i<n;i++)
{
J[i].turnover=(J[i].over.hour*60 +J[i].over.minute)-(J[i].enter.hour*60+J[i].enter.minute);
T+=J[i].turnover;
J[i].weighted=J[i].turnover/(double)J[i].operation;
W+=J[i].weighted;
printf("Job%2d\t %2d:%02d\t%-14d\t %2d:%02d\t %2d:%02d\t %-6d\t%-5.2f\t\n",J[i].no,J[i].enter.hour, J[i].enter.minute,J[i].operation, J[i].start.hour,J[i].start.minute,J[i].over.hour, J[i].over.minute, J[i].turnover,J[i].weighted);
}
T/=n;
W/=n;
printf("作业平均周转时间 T=%.2lf 分钟\n", T);
printf("作业带权平均周转时间W=%.3lf\n\n\n",W);
}
//根据算法将就绪队列排好队后的单道作业的运行主体
voidruning( queue<Jcb *> q,int n)
{
Jcb *j;
int h,m;
j=q.front();
h=j->enter.hour;
m=j->enter.minute;
while (!q.empty())
{
j=q.front();
q.pop();
j->start.hour=h;
j->start.minute=m;
j->over.hour=j->start.hour+(j->start.minute+j->operation)/60;
j->over.minute=(j->start.minute+j->operation)%60;
j->turnover=(j->over.hour*60 +j->over.minute)-(j->enter.hour*60+j->enter.minute);
j->weighted=j->turnover/(double)j->operation;
h=j->over.hour;
m=j->over.minute;
}
// display(J,t);
}
//最高响应比优先作业调度算法
voidhrfc(Jcb J[],int n)//最高响应比优先作业调度算法
{
queue<Jcb *> qjob;
int flag[20];
for(int j=0;j<n;j++)
{
flag[j]=0;
}
qjob.push(&J[0]);
doublewait=J[0].operation+J[0].enter.hour*60+J[0].enter.minute;//记录作业流已经执行的时间
int t=n-1;
flag[0]=1;
while(t)
{
int i=1;
while(flag[i])
{
i++;
}
for(int j=i; j<n ;j++)
{
if( (J[j].enter.hour*60+J[j].enter.minute)>wait)
break;//如果这个作业还没来到,则停止继续比较,只考虑已经进入就绪队列的作业
if(flag[j]==0 )
{
doublewaiti=wait-J[i].enter.hour*60-J[i].enter.minute;//作业J[i]的等待时间
double waitj=wait-J[j].enter.hour*60-J[j].enter.minute;
if((waiti/J[i].operation)<(waitj/J[j].operation))
i=j;
}
}
qjob.push(&J[i]);
flag[i]=1;
wait+=J[i].operation;
t--;
}
runing(qjob,n);
display(J,n);
}
voidfcfs( Jcb J[],int n)//先来先服务作业调度算法
{
queue<Jcb *> qjob;
for(int i=0;i<n;i++)
{
qjob.push(&J[i]);
}
runing(qjob,n);
display(J,n);
}
//最短作业优先作业调度算法
voidsfc(Jcb J[],int n)//最短作业优先作业调度算法
{
queue<Jcb *> qjob;
qjob.push(&J[0]);
inttime=J[0].enter.hour*60+J[0].enter.minute+J[0].operation;//上一个作业的结束时间
J[0].state=1;
int t=n-1;
while(t)
{
int i=1;
while(J[i].state)
{
i++;
}
for(int j=i;j<n;j++)
{
if( (J[j].enter.hour*60+J[j].enter.minute)>time)
break;//如果这个作业还没来到,则停止继续比较,只考虑已经进入就绪队列的作业
if(J[j].state==0 &&(J[i].operation>J[j].operation))
{
i=j;
}
}
qjob.push(&J[i]);
J[i].state=1;
time+=J[i].operation;
t--;
}
runing(qjob,n);
display(J,n);
}
//两道环境,内存中可以用两个作业,内存中的这两个作业按照作业
voidmulfc(Jcb J[],int n)//两道环境,内存中可以用两个作业,内存中的这两个作业按照作业长短调整作业执行的次序。
{//至少有两个作业。
cout<<"两道批处理系统中最短作业优先作业调度算法"<<endl;
int op[20];
int i,work1=-1,work2=-1;//work1是先开始执行的作业,work2是后来进入内存的作业
for(i=0;i<n;i++)
{
op[i]=J[i].operation;
J[i].state=0;
}
work1=0;
J[0].state=1;
J[0].start.hour=J[0].enter.hour;
J[0].start.minute=J[0].enter.minute;
work2=1;
int h=J[0].enter.hour;
int m=J[0].enter.minute;
intwork=work1;
int time;
int t=2;
while(t<=n)
{
if(J[work1].operation>J[work2].operation)
{//第二个work2进入内存的作业的执行时间短于work1,就暂停执行work1,转而执行work2.
op[work1]+=J[work2].operation;
if(t==2)
{//第二个进入内存的,且运行时间较已在内存中的短,则作业开始时间为进入的时间
J[work2].start.hour=J[work2].enter.hour;
J[work2].start.minute=J[work2].enter.minute;
}
else
{//从第三个进入内存的作业,且执行时间比当前在内存中的执行时间短,则开始时间为上一个作业的结束时间
J[work2].start.hour=h;
J[work2].start.minute=m;
}
J[work2].over.hour=J[work2].start.hour+(J[work2].start.minute+op[work2])/60;
J[work2].over.minute=(J[work2].start.minute+op[work2])%60;
h=J[work2].over.hour;
m=J[work2].over.minute;
time=h*60+m;
work2=-1;//改作业执行完毕
}
else
{//第二个work2进入内存的作业的执行时间较长,所以仍然执行开始就在内存的作业work1,知道work1执行完毕
J[work1].over.hour=J[work1].start.hour+(J[work1].start.minute+op[work1])/60;
J[work1].over.minute=(J[work1].start.minute+op[work1])%60;
h=J[work2].over.hour;
m=J[work2].over.minute;
time=h*60+m;
J[work2].start.hour=h;
J[work2].start.minute=m;
work1=work2;
work2=-1;
}
int w;
int i=1;
while(J[i].state==1)
{
i++;
}
w=i;
for(int j=w; j<n;j++)
{
if( (J[j].enter.hour*60+J[j].enter.minute)>time)
break;//如果这个作业还没来到,则停止继续比较,只考虑已经进入就绪队列的作业
if(J[j].state==0 &&(J[w].operation > J[j].operation))
w=j;
}
work2=w;//第二个进入内存的作业
t++;
J[work2].state=1;
}
//最后剩下work1作业
J[work1].over.hour=J[work1].start.hour+(J[work1].start.minute+op[work1])/60;
J[work1].over.minute=(J[work1].start.minute+op[work1])%60;
display(J,n);
}
八、实验结果
(1)在单道环境下,已知n个作业的进入时间和估计运行时间(以分钟计),得到的每一个作业的开始时间、结束时间、周转时间、带权周转时间,以及这些作业的平均周转时间和带权平均周转时间;
(2)同一调度算法对不同作业流的性能,每个算法有三个测试作业流
先来先服务作业调度
最短优先服务作业调度
最高响应比优先服务作业调度
(3)在2道环境下,已知n个作业的进入时间和估计运行时间(以分钟计),得到的每一个作业的开始时间、结束时间、周转时间、带权周转时间,以及这些作业的平均周转时间和带权平均周转时间。
九、结果分析
(1)单道环境下,对于批次一作业流。
先来先服务的作业调度的作业平均周转时间T=112.5分钟
最短作业优先服务作业调度的作业平均周转时间T=90分钟
最高相应比优先服务作业调度的作业平均周转时间T=102.5分钟.
可见对于批次一作业,最短作业优先作业调度算法效率最高。
(2)单道环境下。
2.1对于3个不同批次作业,先来先服务的作业调度
批次一,作业带权平均周转时间 W=4.975
批次二,作业带权平均周转时间 W=4.188
批次三,作业带权平均周转时间 W=2.433
可见,先来先服务的作业调度,对于批次三作业的效率最高。
2.2对于3个不同批次作业,最短优先服务的作业调度
批次一,作业带权平均周转时间 W=4.975
批次二,作业带权平均周转时间 W=2.875
批次三,作业带权平均周转时间 W=2.317
可见,最短优先服务的作业调度,对于批次三作业的效率最高。
2.3对于3个不同批次作业,最高响应比优先服务的作业调度
批次一,作业带权平均周转时间 W=3.775
批次二,作业带权平均周转时间 W=3.250
批次三,作业带权平均周转时间 W=2.317
可见,最高响应比优先服务的作业调度,对于批次二作业的效率最高
十、本次实验体会
1. 先来先服务的作业调度,实现最简单。
2. 对于同批次作业,最短作业的效率最高。
3. 最高响应比优先作业调度,既照顾了短作业,又照顾了作业到来的顺序,不会使长作业长期得不到运行,但是每次调度下一个作业前要计算剩余到来作业的响应比,增加了系统的开销。
4. 两道批处理系统中最短作业优先作业调度算法,在实现时,我默认为作业之间没有时间空余,默认在处理一个作业流时处理器一直处于运行状态。所以代码有漏洞,考虑的也不是很全面。
5. 开始时对作业调度不是很那么地清晰,通过做这个实验,现在对操作系统的作业调度有了清晰的理解,感觉在这个过程中自己就是充当了调度员的角色。开始写好的代码比较繁杂,于是写了display 和running函数来简化代码。
6.最初忽略了作业的进入时间问题,和同学讨论了一下,意见不太一致,但我觉得这个问题是应该考虑的。
7.实验代码修改了好多次,一些细小的问题,如输入、输出和如何简化代码等比较耗费时间。通过这个实验,发现自己的C\C++功底太差了,做实验时可谓是边做边翻书。通过这个实验,也回顾了一下C\C++的一些基础知识。
十一、参考资料
(1) 郭浩志 《计算机软件实践教程》 西安电子科技大学出版社(2) 庞丽萍 《计算机操作系统》 华中科技大学出版社
相关文章推荐
- 1043_输出PATest
- 支线任务1
- hdu1018Big number(N!的位数-斯特林公式)
- android sqlite的SqliteDataBase.insert()方法,以及如何在事务管理中使用
- MySql学习笔记一
- 安装apache——centos7
- [C++] Memory Retrieval(内存检索)
- C语言中简单的for循环和浮点型变量
- HDFS File System Shell Guide
- ivy相关的文档以及相关例子
- PostgreSQL earth distance module
- 转载一:OSM-Web服务器(一) PostgreSql 配置以及osm2pgsql原始PBF数据导入
- 本博简介
- HDOJ 题目1828 Picture (线段树+扫描线)
- 技巧:快速提高 Vi/Vim 使用效率的原则与途径
- 学习小结20151014--小标签
- 转换java keytools的keystore证书到OPENSSL的PEM格式文件
- Objective-C:KVO机制
- KMP算法的理解
- Hadoop和YARN的关系