【操作系统】实验二 作业调度模拟程序
实验一、作业调度模拟程序实验
商业软件工程 杨晶晶 201406114102
一、 实验目的
(1)加深对作业调度算法的理解;
(2)进行程序设计的训练。
二、 实验内容和要求
实验内容
根据指定的实验课题,完成设计、编码和调试工作,完成实验报告。
实验要求
用高级语言编写一个或多个作业调度的模拟程序。
单道批处理系统的作业调度程序。作业一投入运行,它就占有计算机的一切资源直到作业完成为止,因此调度作业时不必考虑它所需要的资源是否得到满足,它所运行的时间等因素。
一、 模拟数据的生成
1. 允许用户指定作业的个数(2-24),默认值为5。
2. 允许用户选择输入每个作业的到达时间和所需运行时间。
3. (**)从文件中读入以上数据。
4. (**)也允许用户选择通过伪随机数指定每个作业的到达时间(0-30)和所需运行时间(1-8)。
二、 模拟程序的功能
1. 按照模拟数据的到达时间和所需运行时间,执行FCFS, SJF和HRRN调度算法,程序计算各作业的开始执行时间,各作业的完成时间,周转时间和带权周转时间(周转系数)。
2. 动态演示每调度一次,更新现在系统时刻,处于运行状态和等待各作业的相应信息(作业名、到达时间、所需的运行时间等)对于HRRN算法,能在每次调度时显示各作业的响应比R情况。
3. (**)允许用户在模拟过程中提交新作业。
4. (**)编写并调度一个多道程序系统的作业调度模拟程序。 只要求作业调度算法:采用基于先来先服务的调度算法。 对于多道程序系统,要假定系统中具有的各种资源及数量、调度作业时必须考虑到每个作业的资源要求。
三、 模拟数据结果分析
1. 对同一个模拟数据各算法的平均周转时间,周转系数比较。
2. (**)用曲线图或柱形图表示出以上数据,分析算法的优点和缺点。
四、 实验准备
序号 |
准备内容 |
完成情况 |
1 |
什么是作业? |
作业相当于一个程序。 任务相当于整个程序中的一段段可以并发执行的代码。 进程其实就是任务。从系统的角度看,作业则是一个比程序更广的概念。它由程序、数据和作业说明书组成。系统通过作业说明书控制文件形式的程序和数据,使之执行和操作。而且,在批处理系统中,作业是抢占内存的基本单位。也就是说,批处理系统以作业为单位把程序和数据调入内存以便执行。 |
2 |
一个作业具备什么信息? |
作业由三部分组成,即程序、数据和作业说明书。一个作业可以包含多个程序和多个数据集,但必须至少包含一个程序。否则将不成为作业。 |
3 |
为了方便模拟调度过程,作业使用什么方式的数据结构存放和表示? |
由作业说明书在系统中生成一个称为作业控制块(job control block,JCB)的表格。该表格登记该作业所要求的资源情况、预计执行时间和执行优先级等。从而,操作系统通过该表了解到作业要求,并分配资源和控制作业中程序和数据的编译、链接、装入和执行等。 |
4 |
操作系统中,常用的作业调度算法有哪些? |
先来先服务算法、最短作业优先算法、最短剩余时间优先算法、最高响应比优先算法、轮转调度算法、多级反馈队列调度算法、优先级法调度算法 |
5 |
如何编程实现作业调度算法? |
|
6 |
模拟程序的输入如何设计更方便、结果输出如何呈现更好? |
|
五、 其他要求
1. 完成报告书,内容完整,规格规范。
2. 实验须检查,回答实验相关问题。
注:带**号的条目表示选做内容。
实验原理及核心算法参考程序段
单道FCFS算法:
三、 实验方法、步骤及结果测试
1. 源程序名:源程序名 job2.c
可执行程序名:job2.exe
2. 原理分析及流程图
作业调度算法:
1) 采用先来先服务(FCFS)调度算法,即按作业到达的先后次序进行调度。总是首先调度在系统中等待时间最长的作业。
2) 短作业优先 (SJF) 调度算法,优先调度要求运行时间最短的作业。
3) 响应比高者优先(HRRN)调度算法,为每个作业设置一个优先权(响应比),调度之前先计算各作业的优先权,优先数高者优先调度。RP (响应比)= 作业周转时间 / 作业运行时间=1+作业等待时间/作业运行时间
每个作业由一个作业控制块JCB表示,JCB可以包含以下信息:作业名、提交(到达)时间、所需的运行时间、所需的资源、作业状态、链指针等等。
作业的状态可以是等待W(Wait)、运行R(Run)和完成F(Finish)三种之一。每个作业的最初状态都是等待W。
3. 主要程序段及其解释:
1 #include<stdio.h> 2 #include <stdlib.h> 3 #include <time.h> 4 #define MAX 24 5 typedef struct node 6 { 7 char name[10];//作业名 8 int arrivetime;//作业到达时间 9 int requesttime;//作业要求服务时间 10 int starttime; //开始时间 11 int finishtime; //结束时间 12 float Ttime;//周转时间 13 float p;//响应比 14 float Wtime;//带权周转时间 15 }JCB; 16 17 static int N=5; //系统默认作业数 18 static int flag=0; 19 JCB job[MAX]; 20 21 void FCFS();//先来先服务算法 22 void SJF();//最短作业优先算法 23 void HRRN();//最高响应比优先算法 24 void getValue();//给每个作业内的相关参数赋值 25 void input();//输入数据 26 void print();//打印输入的数据列表 27 void getp();//得到响应比 28 int ReadFile();//读取文件中的数据 29 void input1();//初始数据列表 30 31 //读取文件数据 32 int ReadFile() 33 { 34 int m=0; 35 char i=0; 36 FILE *fp; //定义文件指针 37 fp=fopen("3.txt","r"); //打开文件 38 if(fp==NULL) 39 { 40 printf("File open error !\n"); 41 exit(0); 42 } 43 printf("\n文件中的数据内容为:"); 44 while(!feof(fp)) 45 { 46 47 fscanf(fp,"\n%s%d%d",&job[i].name,&job[i].arrivetime,&job[i].requesttime); //fscanf()函数将数据读入 48 printf("\n%3d%12d%15d",job[i].name,job[i].arrivetime,job[i].requesttime); //输出到屏幕 49 i++; 50 }; 51 printf("\n"); 52 if(fclose(fp)) //关闭文件 53 { 54 printf("Can not close the file !\n"); 55 exit(0); 56 } 57 m=i-1; 58 return m; 59 60 } 61 62 //伪随机数产生器 63 int Pseudo_random_number() 64 { 65 int i,n; 66 srand((unsigned)time(0)); //参数seed是rand()的种子,用来初始化rand()的起始值。 67 //输入作业数 68 n=rand()%23+5; 69 for(i=0; i<=n; i++) 70 { 71 //作业到达时间 72 job[i].arrivetime=rand()%29+1; 73 //作业运行时间 74 job[i].requesttime=rand()%7+1; 75 } 76 return n; 77 78 } 79 80 void input1() 81 { 82 int i; 83 printf("\n--------输入的数据为:\n"); 84 printf(" 作业名 到达时间 要求服务时间\n"); 85 for(i=0; i<N; i++) 86 { 87 printf("第%d个作业",i+1); 88 printf(" %4s% 13d %14d\n",job[i].name,job[i].arrivetime,job[i].requesttime); 89 } 90 } 91 92 void input()//输入数据 93 { 94 int i, jobNum, choi; 95 char flag=0; 96 printf("_________________________________\n"); 97 printf("1.自选作业个数并输入\n"); 98 printf("2.伪随机数产生器\n"); 99 printf("3.读取文件输入数据\n"); 100 printf("_________________________________\n"); 101 printf("****你的选择是:"); 102 scanf("%d", &choi); 103 switch(choi) 104 { 105 case 1: 106 { 107 do{ 108 printf("****请输入作业个数(个数在2~24之间):"); 109 scanf("%d", &jobNum); //输入作业数 110 N=jobNum; 111 112 113 } 114 while(N<2 || N>24); 115 break; 116 } 117 case 2: 118 Pseudo_random_number();//产生随机数 119 //input1(); 120 break; 121 case 3: 122 ReadFile();//读取文件 123 //input1(); 124 break; 125 default: 126 printf("\n !!!!!输入错误,请重新选择!!!!!\n"); 127 input(); 128 129 } 130 for(i=0; i<jobNum; i++) 131 { 132 printf("\n第%d个作业名:",i+1); 133 scanf(" "); 134 gets(job[i].name); //输入作业名 135 printf("到达时间:"); 136 scanf(" %d",&job[i].arrivetime); //输入作业达到时间 137 printf("要求服务时间:"); 138 scanf(" %d",&job[i].requesttime); //输入作业要求服务时间 139 job[i].starttime=0; 140 141 } 142 input1(); 143 } 144 145 void print()//打印输入的数据列表 146 { 147 int i; 148 float TAvetime; 149 float WAvetime; 150 float TtimeSum=0; 151 float WtimeSum=0; 152 153 printf(" 作业名 到达时间 要求服务时间 开始时间 完成时间 周转时间 带权周转时间\n"); 154 for(i=0; i<N; i++) 155 { 156 TtimeSum+=job[i].Ttime; 157 WtimeSum+=job[i].Wtime; 158 printf("第%d个作业",i+1); 159 printf(" %4s% 13d %14d %9d %10d %10.2f %10.2f\n",job[i].name,job[i].arrivetime,job[i].requesttime,job[i].starttime,job[i].finishtime,job[i].Ttime,job[i].Wtime); 160 161 } 162 TAvetime=TtimeSum/N; 163 WAvetime=WtimeSum/N; 164 printf("平均周转时间为:%.2f",TAvetime); 165 printf("\n平均带权周转时间为:%.2f",WAvetime); 166 } 167 168 void choice()//选择调度算法 169 { 170 int mark; 171 printf("\n\n--------------------------------------------- "); 172 printf("\n 1.先来先服务(FCFS)调度算法;"); 173 printf("\n 2.最短作业优先(SJF)调度算法;"); 174 printf("\n 3.最高响应比优先(HRRF)调度算法; "); 175 printf("\n 4.退出; "); 176 printf("\n 5.返回主菜单 "); 177 printf("\n---------------------------------------------\n"); 178 printf("\n 请选择算法: "); 179 scanf("%d", &mark); 180 switch(mark) 181 { 182 case 1: 183 printf("\n********************先来先服务(FCFS)调度算法结果*****************\n\n"); 184 FCFS(); //先来先服务算法 185 choice(); 186 break; 187 case 2: 188 printf("\n********************最短作业优先(SJF)调度算法结果*****************\n\n"); 189 SJF(); //最短作业优先算法 190 choice(); 191 break; 192 case 3: 193 printf("\n********************最高响应比优先(HRRF)调度算法结果*****************\n\n"); 194 HRRN(); //最高响应比优先算法 195 choice(); 196 break; 197 case 4: 198 return; 199 case 5: 200 input(); 201 choice(); 202 break; 203 default: 204 printf("\n !!!!!!输入错误,请重新选择!!!!!!"); 205 choice(); 206 } 207 } 208 209 void getValue() //给每个作业内的相关参数赋值 210 { 211 int i; 212 213 for(i=0; i<N; i++) 214 { 215 if(i==0 || job[i].arrivetime>job[i-1].finishtime) 216 job[i].starttime=job[i].arrivetime; 217 else 218 job[i].starttime=job[i-1].finishtime; 219 job[i].finishtime=job[i].requesttime+job[i].starttime; 220 job[i].Ttime=(float)job[i].finishtime-(float)job[i].arrivetime; 221 job[i].Wtime=(float)job[i].Ttime/(float)job[i].requesttime; 222 223 } 224 } 225 226 void FCFS()//先来先服务算法 227 { 228 int i, j; 229 JCB mark; 230 for(i=0;i<N-1; i++) //通过作业到达时间整体排序 231 { 232 for(j=i+1; j<N; j++) 233 { 234 if(job[j].arrivetime<job[i].arrivetime)//冒泡排序 235 { 236 mark=job[j]; 237 job[j]=job[i]; 238 job[i]=mark; 239 } 240 } 241 } 242 getValue();//给每个作业内的相关参数赋值 243 print(); //打印出结果 244 } 245 246 void SJF()//最短作业优先算法 247 { 248 int i, j; 249 JCB mark; 250 for(i=1;i<N-1; i++) //通过作业所需运行时间整体排序 251 { 252 for(j=i+1; j<N; j++) 253 { 254 if(job[j].requesttime<job[i].requesttime)//冒泡排序 255 { 256 mark=job[j]; 257 job[j]=job[i]; 258 job[i]=mark; 259 } 260 } 261 } 262 263 getValue(); //给每个作业内的相关参数赋值 264 print(); //打印出结果 265 266 } 267 268 void HRRN()//最高响应比优先算法 269 { 270 int i, j; 271 JCB mark; 272 for(i=1;i<N-1; i++) //通过到达时间整体排序 273 { 274 for(j=i+1; j<N; j++) 275 { 276 if(job[j].arrivetime<job[i].arrivetime) 277 { 278 mark=job[j]; 279 job[j]=job[i]; 280 job[i]=mark; 281 } 282 } 283 } 284 job[0].starttime=job[0].arrivetime; 285 job[0].finishtime=job[0].requesttime+job[0].starttime;; 286 job[0].Ttime=job[0].finishtime-job[0].arrivetime; 287 job[0].Wtime=(float)job[0].Ttime/(float)job[0].requesttime; 288 289 flag=0; 290 getp(); // 得到响应比 291 print(); //打印出来 292 } 293 294 void getp()//得到响应比 295 { 296 int i, j; 297 JCB mark2; 298 do{ 299 for(i=flag+1; i<N; i++) 300 { 301 if(job[i].arrivetime>job[flag].finishtime) //后面的与第一个对比 302 job[i].starttime=job[i].arrivetime; 303 else 304 job[i].starttime=job[flag].finishtime; 305 job[i].finishtime=job[i].requesttime+job[i].starttime; 306 job[i].Ttime=job[i].finishtime-job[i].arrivetime; 307 job[i].Wtime=(float)job[i].Ttime/(float)job[i].requesttime; 308 } 309 for(i=flag+1;i<N-1; i++) //后面的元素 根据响应比整体排序 得到高响应比的元素 310 { 311 for(j=i+1; j<N; j++) 312 { 313 if(job[j].Wtime>job[i].Wtime) 314 { 315 mark2=job[j]; 316 job[j]=job[i]; 317 job[i]=mark2; 318 } 319 } 320 } 321 flag++; 322 }while(flag<N); 323 } 324 325 void main() 326 { 327 printf("\n*************************欢迎使用作业调度模拟程序*************************\n\n"); 328 input(); //输入 329 //print(); //打印输出 330 choice(); //选择调度算法 331 }
4. 运行结果及分析
四、 实验总结
这次的实验做的时间挺长的,主要实现了三种作业调度算法,还可以通过产生随机数来产生数据。一开始的代码都写在main函数里面,看起来不美观而且不方便,所以把代码都分开放到不同的方法里面,改起来会比较方便。在实现最短作业优先算法的时候一开始忽略了第一个作业是最先到达,而且只有一个作业在调度,不管其他的作业时间有多短都应该先运行作业一。在实现最高响应比优先算法的时候,虽然知道怎么比较计算响应比,可是不太会实现算法让他们进行作业调度,后来向同学求助还有上网参考一些代码实现。这过程有很多粗心的地方,比如计算公式错了,本来是整形,输出却打印浮点型的数,弄得一直是显示0。以后要多练习多注意细节问题。