一、目的和要求
1. 实验目的
(1)加深对作业调度算法的理解;
(2)进行程序设计的训练。
2.实验要求
用高级语言编写一个或多个作业调度的模拟程序。
单道批处理系统的作业调度程序。作业一投入运行,它就占有计算机的一切资源直到作业完成为止,因此调度作业时不必考虑它所需要的资源是否得到满足,它所运行的时间等因素。
作业调度算法:
1) 采用先来先服务(FCFS)调度算法,即按作业到达的先后次序进行调度。总是首先调度在系统中等待时间最长的作业。
2) 短作业优先 (SJF) 调度算法,优先调度要求运行时间最短的作业。
3) 响应比高者优先(HRRN)调度算法,为每个作业设置一个优先权(响应比),调度之前先计算各作业的优先权,优先数高者优先调度。RP (响应比)= 作业周转时间 / 作业运行时间=1+作业等待时间/作业运行时间
每个作业由一个作业控制块JCB表示,JCB可以包含以下信息:作业名、提交(到达)时间、所需的运行时间、所需的资源、作业状态、链指针等等。
作业的状态可以是等待W(Wait)、运行R(Run)和完成F(Finish)三种之一。每个作业的最初状态都是等待W。
一、 模拟数据的生成
1. 允许用户指定作业的个数(2-24),默认值为5。
2. 允许用户选择输入每个作业的到达时间和所需运行时间。
3. (**)从文件中读入以上数据。
4. (**)也允许用户选择通过伪随机数指定每个作业的到达时间(0-30)和所需运行时间(1-8)。
二、 模拟程序的功能
1. 按照模拟数据的到达时间和所需运行时间,执行FCFS, SJF和HRRN调度算法,程序计算各作业的开始执行时间,各作业的完成时间,周转时间和带权周转时间(周转系数)。
2. 动态演示每调度一次,更新现在系统时刻,处于运行状态和等待各作业的相应信息(作业名、到达时间、所需的运行时间等)对于HRRN算法,能在每次调度时显示各作业的响应比R情况。
3. (**)允许用户在模拟过程中提交新作业。
4. (**)编写并调度一个多道程序系统的作业调度模拟程序。 只要求作业调度算法:采用基于先来先服务的调度算法。 对于多道程序系统,要假定系统中具有的各种资源及数量、调度作业时必须考虑到每个作业的资源要求。
三、 模拟数据结果分析
1. 对同一个模拟数据各算法的平均周转时间,周转系数比较。
2. (**)用曲线图或柱形图表示出以上数据,分析算法的优点和缺点。
四、 其他要求
1. 完成报告书,内容完整,规格规范。
2. 实验须检查,回答实验相关问题。
注:带**号的条目表示选做内容。
二、实验内容
根据指定的实验课题,完成设计、编码和调试工作,完成实验报告。
三、实验环境
可以采用TC,也可以选用Windows下的利用各种控件较为方便的VB,VC等可视化环境。也可以自主选择其他实验环境。
四、实验原理及核心算法参考程序段
#include<stdio.h> #include<stdlib.h> typedef struct JCB{ //定义进程控制块 char name[10]; char state; int tt; //提交时间 int kt; //开始时间 int jt; //结束时间 int nt; //运行需要时间 int st; //运行了一段时间后被抢占资源,还需要的时间 int priority; //优先级 float yt; //实际运行时间 float jqyt; //加权运行时间 char depend[10]; //完成的前提作业 struct JCB *next; //指向下个作业 }jcb; int time=10000,n,flag; //计时器 //flag标志当前作业剩余量 char k; jcb *head=NULL,*p,*q; run_fcfo(jcb *p1) { time=p1->tt<time?p1->tt:time; printf(" 现在时间是%d,开始运行作业%s! ",time,p1->name); printf(" name tt nt jt prt depend yt jqyt "); time+=p1->nt; p1->yt=time-p1->tt; p1->jqyt=p1->yt/p1->nt; p1->state='F'; p1->jt=time; printf("%s %d %d %d %d %s %.1f %.1f ",p1->name,p1->tt,p1->nt,p1->jt,p1->priority,p1->depend,p1->yt,p1->jqyt); printf(" 作业%s已经运行结束!共费时%0.1f! ",p1->name,p1->yt); } sata() //统计数据 { int i; float sum=0,jqsum=0; //分别存放总运行时间和加权时间 p=head; for(i=0;i<n;i++) { sum+=p->yt; jqsum+=p->jqyt; p=p->next; } printf(" 所有作业全部运行完毕! "); printf(" 平均周转时间为:%0.2f 平均加权周转时间为:%0.2f ",sum/n,jqsum/n); } fcfo() { int i,j,t; //t作为当前提交时间的存储值 for(j=0;j<n;j++) { p=head; t=10000; for(i=0;i<n;i++) //找到当前未完成的作业 { if(p->tt<t&&p->state=='W') { t=p->tt; q=p; //标记当前未完成的作业 } p=p->next; } run_fcfo(q); } //下面统计数据 sata(); } run_sjf(jcb *p1) { //p1-<yt=time-p1-<tt+1; if(p1->st==p1->nt) { p1->kt=time; //如果尚未运行过,确定运行开始时间 } if(p1->st-1==0) { p1->jt=time+1; //如果运行后可以结束,记录下当前的结束时间 } p1->st--; printf(" 时刻:%d",time); printf(" name tt nt st prt "); printf("%s %d %d %d %d ",p1->name,p1->tt,p1->nt,p1->st,p1->priority); if(p1->st==0) //如果某个作业运行结束 { p1->yt=p1->jt-p1->tt; printf(" ----------------------------------------------------- "); printf("----------------------------------------------------- "); p1->state='F'; printf(" 作业%s已经完成,作业参数如下: ",p1->name); printf(" name tt nt jt prt depend yt jqyt "); p1->jqyt=p1->yt/p1->nt; printf("%s %d %d %d %d %s %.1f %.1f ",p1->name,p1->tt,p1->nt,p1->jt,p1->priority,p1->depend,p1->yt,p1->jqyt); printf("----------------------------------------------------- "); printf("----------------------------------------------------- "); flag--; } } sjf() { int i; jcb *now=head; //指向当前运行的作业 flag=n; while(flag) { p=head,q=head; //每次循环前将p置于指向作业头 for(i=0;i<n;i++) { if(p->state=='W'&&p->tt<=time) { if(q->state=='W') q=q->nt<p->nt?q:p; //执行短进程优先策略 else q=p; } p=p->next; } if(q->state!='F') { run_sjf(q); } else { printf(" 时刻:%d",time); printf(" 无作业可以运行,等待作业进入! "); } time++; } //下面统计数据 sata(); } run_prtf(jcb *p1) { //p1-<yt=time-p1-<tt+1; if(p1->st==p1->nt) { p1->kt=time; //如果尚未运行过,确定运行开始时间 } if(p1->st-1==0) { p1->jt=time+1; //如果运行后可以结束,记录下当前的结束时间 } p1->st--; printf(" 时刻:%d",time); printf(" name tt nt st prt "); printf("%s %d %d %d %d ",p1->name,p1->tt,p1->nt,p1->st,p1->priority); if(p1->st==0) //如果某个作业运行结束 { p1->yt=p1->jt-p1->tt; printf(" ----------------------------------------------------- "); printf("----------------------------------------------------- "); p1->state='F'; printf(" 作业%s已经完成,作业参数如下: ",p1->name); printf(" name tt nt jt prt depend yt jqyt "); p1->jqyt=p1->yt/p1->nt; printf("%s %d %d %d %d %s %.1f %.1f ",p1->name,p1->tt,p1->nt,p1->jt,p1->priority,p1->depend,p1->yt,p1->jqyt); printf("----------------------------------------------------- "); printf("----------------------------------------------------- "); flag--; } } prtf() { int i; jcb *now=head; //指向当前运行的作业 flag=n; while(flag) { p=head,q=head; //每次循环前将p置于指向作业头 for(i=0;i<n;i++) { if(p->state=='W'&&p->tt<=time) { if(q->state=='W') q=q->priority<p->priority?q:p; //执行优先级优先策略 else q=p; } p=p->next; } if(q->state!='F') { run_prtf(q); } else { printf(" 时刻:%d",time); printf(" 无作业可以运行,等待作业进入! "); } time++; } //下面统计数据 sata(); } run(int i) //选择相应的模块开始运行 { printf(" 虚拟机开始运行: "); switch(i) { case 1: fcfo();break; case 2: sjf();break; case 3: prtf();break; default: printf(" 运行错误!请检查错误! "); } } getit() //得到进程的相关信息 { int num; printf(" 总共有多少个作业?"); scanf("%d",&n); printf(" 现在请输入各进程的详细信息: 各项之间用tab键分隔! "); printf(" name tt nt prt depend "); for(num=0;num<n;num++) { p=(jcb *)malloc(sizeof(jcb)); if(head==NULL) {head=p;q=p;} scanf("%s %d %d %d %s",&p->name,&p->tt,&p->nt,&p->priority,&p->depend); if(p->tt<time) time=p->tt; q->next=p; p->state='W'; p->st=p->nt; p->yt=0; p->next=NULL; q=p; //记录当前P的位置,为下一步定义准备 } printf("输入完毕; "); } startup() //运行的主程序 { int i; printf("操作系统作业模拟调度程序: 1,先进先出调度; 2,短进程优先调度; 3,按优先级调度; "); printf("请选择: "); scanf("%d",&i); if(i<3) { printf(" 输入错误,请输入1-3之间的数! 重新开始: "); startup(); } getit(); run(i); } main() { printf(" ---------------------生活很美好,奋斗仍继续!(翠连座右铭)---------------------- "); startup(); printf(" 模拟运行已经完成! "); }