实验报告
-----作业调度
计算机科学与技术04级一班
022号 剪晓光
20##.12.6
实验(二):作业调度
本组成员:剪晓光 王鹏 张文艺 余忠福
一、 实验目的:
(1)理解什么是作业:每个用户请求计算机的一个计算任务叫做一个作业。
(2)作业的执行有几个步骤:一个作业从开始执行到得出结果要经历若干步。
(3)什么是作业控制方式:用户向系统提出作业加工的方式称作业控制方式。
(4)作业控制方式有那几种:终端控制方式(又称直接控制方式或联机控制方式)和批处理控制方式(又称自动控制方式或脱机控制方式)。
(5)作业调度的作用:通过模拟作业调度的实现,了解作业调度在操作系统中的作用。
二、 实验内容:
(1):设计一个小系统(能够通过小系统中作业的调度了解多道操作系统中作业执行)。
(2):通过小系统的模拟,分析多道系统的作业执行。
(3):提出系统中作业的调度的改进措施,以提高作业的执行效率,提高多道操作系统的处理能力。
三. 流程图如下:
三、 源程序如下:
#include "stdio.h"
#include "stdlib.h"
#include "time.h"
#define Max 100 //最大作业数
#define MEMLENGTH 180
#define RECORDERNUM 16
typedef struct JCB //作业控制块
{
int UserID; //用户名
int JobID; //作业名
char status; //状态
float RunTime; //运行时间
int ApplyMem; //申请主存大小
int ApplyRecorder;//申请磁带数
struct JCB * next;
}JCB;
void JTinit(JCB * p)//构造一个空的
{
p->next=(JCB *)malloc(sizeof(JCB));
p->next->next=NULL;
p->UserID=p->JobID=NULL;
}
void JTinsert(JCB * jt,JCB * j) //插入
{
JCB * p;
for(p=jt;p->next!=NULL;p=p->next);
p->next=j;
j->next=NULL;
}
int JTdel(JCB * jt,JCB * j) //删除
{
JCB * p;
if(j==NULL)return 0;
p=jt->next;
if(p==NULL)return 0;
for(;p->next!=NULL&&p->next!=j;p=p->next);
if(p->next==NULL)return 0;
p->next=j->next;
return 1;
}
JCB * JTfind(JCB * jcb,char status) //查找
{
JCB * p;
if(jcb==NULL) return NULL;//若作业控制块为空,返回NULL
for(p=jcb->next;p!=NULL&&p->status!=status;p=p->next);
return p;
}
void JTrelease(JCB * jt) //释放
{
JCB * p;
JCB * q;
p=jt->next;
if(p==NULL)return;
for(q=p->next;q!=NULL;p=q,q=q->next)
free(p);
}
JCB jt;
int memory=MEMLENGTH;
int recorder=RECORDERNUM;
int num,num1;
int m;
int e=0;
int runnum=0;
void stop(int n)//运行该函数大概需要n/100秒,用来模拟作业执行时间
{
int i=0,j,m;
for(;i<=2650;i++)
{
for(j=0;j<n;j++)
{
m=1000;
while(m){m--;}
}
}
}
void run()
{
JCB * ep,* pd;
void recover();//函数声明
if(num>0)//若作业表中有尚未选中的作业
{
ep=JTfind(&jt,'s');
pd=ep;
if(m==2)
{
while((pd=JTfind(pd,'s'))!=NULL)
if(ep->RunTime>=pd->RunTime)
ep=pd;
}
while(num>0&&ep&&memory>=ep->ApplyMem&&recorder>=ep->ApplyRecorder)
{
num--;
ep->status='e';
memory-=ep->ApplyMem;
recorder-=ep->ApplyRecorder;
e++;
printf("选中第%d个占有处理机执行的作业:\n",e);
printf("作业名:zy%d\t用户名:User%d\t运行时间:%1.2f秒\n",ep->JobID,ep->UserID,ep->RunTime);
printf("申请主存量:%dK\t申请磁带数:%d\n",ep->ApplyMem,ep->ApplyRecorder);
printf("剩余主存量:%dK\t剩余磁带数:%d\n\n",memory,recorder);
ep=JTfind(&jt,'s');
pd=ep;
if(m==2)
{
while((pd=JTfind(pd,'s'))!=NULL)
if(ep->RunTime>=pd->RunTime)
ep=pd;
}
if(ep==NULL)
{
printf("**************主存中已无收容态的作业!**************\n\n");
recover();
}
else if(recorder<ep->ApplyRecorder)
{
printf("**************磁带数不足**************\n\n");
recover();
}
else if(memory<ep->ApplyMem)
{
printf("**************主存量不足**************\n\n");
recover();
}
}
}
}
void recover()
{
JCB * ep,* pd;
ep=JTfind(&jt,'e');
pd=ep;
if(m==2)
{
while((pd=JTfind(pd,'e'))!=NULL)
if(ep->RunTime>=pd->RunTime)
ep=pd;
}
while(num1>0&&ep)
{
int time=int(100*ep->RunTime);
stop(time);
runnum++;
num1--;
ep->status='f';
memory+=ep->ApplyMem;
recorder+=ep->ApplyRecorder;
printf("第%d个作业执行结束:\n",runnum);
printf("作业名:zy%d\t用户名:User%d\t运行时间:%1.2f秒\n",ep->JobID,ep->UserID,ep->RunTime);
printf("申请主存量:%dK\t申请磁带数:%d\n",ep->ApplyMem,ep->ApplyRecorder);
printf("剩余主存量:%dK\t剩余磁带数:%d\n\n\n",memory,recorder);
ep=JTfind(&jt,'e');
pd=ep;
if(m==2)
{
while((pd=JTfind(pd,'e'))!=NULL)
if(ep->RunTime>=pd->RunTime)
ep=pd;
}
if(num1>=0&&ep==NULL)printf("****************作业全部执行结束****************\n\n");
else if(JTfind(&jt,'s'))
{
if(memory>=ep->ApplyMem&&recorder>=ep->ApplyRecorder)
{
run();
}
}
}
}
void init(int n)
{
JCB *p;
JTinit(&jt);
//产生随机运行时间数组Tr[Max]
int i=0,t[Max];
float tt[Max],Rt[Max];
srand((unsigned)time(NULL));
for(i=0;i<n;i++)
{
t[i]=rand()*1l*rand()%101;
while(t[i]==0)//控制产生不为0的数
{t[i]=rand()*1l*rand()%101;}
tt[i]=float(t[i]);
Rt[i]=tt[i]/40;
}
//产生随机申请主存量数组Am[Max]
int Am[Max];
for(int j=0;j<n;j++)
{
Am[j]=rand()*1l*rand()%61;
while(Am[j]<=4)//控制产生不为0的数
{Am[i]=rand()*1l*rand()%61;}
}
//产生随机申请磁带数数组Ar[Max]
int r=0,Ar[Max];
for(r=0;r<n;r++)
{
Ar[r]=rand()*1l*rand()%5;
while(Ar[r]==0)
{Ar[r]=rand()*1l*rand()%5;}
} //初始化
for(int k=0;k<n;k++)
{
p=(JCB*)malloc(sizeof(JCB));
p->UserID=p->JobID=k+1;
p->status='s';
p->RunTime=Rt[k];
p->ApplyMem=Am[k];
p->ApplyRecorder=Ar[k];
JTinsert(&jt,p);
}
printf("初始化成功!\n");
}
void main()
{
printf("输入你要创建的作业数【 n<=%d 】:",Max);
scanf("%d",&num);
num1=num;
init(num1);//初始化
printf("选择调度算法: 1.先来先服务法 2.最短作业优先法\n");
scanf("%d",&m);
run();
JTrelease(&jt);//释放资源
printf("\n\n****************调 度 完 成****************\n\n");
}
(四)程序的使用:调试后好运行程序,出现如下界面,显示的是输入所需要的作业数:
这时我们可以输入任何小于100的数字。例如现在我们输入12,显示的是:请求选择算法,1、先来先服务法(FCFS) ;2、最短作业优先法(SJF);
出现如下界面:
假如输入1 将输出如下:
假如输入2 将输出如下:
(五)关于模拟系统的演示:
(名称:作业调度演示系统)
运行 作业调度演示.swf后
可以看到用户界面如图所示:
点击“点击进入”即可以进入作业调度模拟系统:
看到以下用户界面:
点击“播放”作业调度演示将开始进行:
在执行的过程中,绿色的高亮显示将根据正确的顺序依次进行。而且界面右下角有:,通过这个“暂停”,可以实现在任何地方停止,然后点击“播放”演示又将继续执行。
还有 “返回主界面”按纽,可以回到进入演示系统的初始界面。
六、实验总结:
通过这次的操作系统的分组实验,我学到了很多东西:
(1)我学会了用小系统模拟大系统的方法来模拟大系统的实现过程。
(2)在实验过程中我还学习了一些能够表达实验动态演示的方法。例如:flash, VB. 等等。
(3)此次实验还增强了我的动手能力,可以将所学的理论知识转化为能够真正用到的实际能力。
(4)通过和同组的其他的同学的配合,我知道了团队合作的重要性,在以后的学习和工作中,一定会受益非浅。
(5)通过此次实验我也看到了自己很多不足的地方,比如对程序的认识,可能我们的程序写的还不是特别的好。可能走了一些弯路,还有就是我们的演示可能不是很有特点,总之,我了解另外自己的能力,们现在开始要抓紧时间学习,学习更多的东西。
完(共16页)
本科生实验报告
实验课程 操作系统原理
学院名称
专业名称
学生姓名
学生学号
指导教师
实验地点
实验成绩
二〇##年九月 二〇##年十二月
、
实验1-2:作业调度
一、实验内容
模拟批处理多道操作系统的作业调度。
二、实验目的
每个用户请求计算机计算的一个计算任务叫做一个作业。一个作业从输入初始数据到得到计算结果,要经过若干个步骤的相继执行。例如,编辑、编译、运行等,其中每一个步骤称作一个作业步。用户向系统提出作业加工步骤的方式称作业控制方式,作业控制方式有两种:终端控制方式(又称直接控制方式或联机控制方式)和批处理控制方式(又称自动控制方式或脱机控制方式)。
在批处理控制方式下,用户采用系统提供的作业控制语言(JCL)写好作业说明书,说明作业加工的步骤。操作员把一批作业组织成输入流,通过“预输入”手段使每个作业的信息(包括作业说明书、源程序、初始数据等)暂存在辅助存储器的“输入井”中。
批处理多道操作系统的作业管理有两个任务:作业调度和作业控制。采用多道程序设计方法的操作系统,在系统中要经常保留多个运行的作业,以提高系统效率。作业调度从系统已接纳的暂存在输入井中的一批作业中挑选出若干个可运行的作业,并为这些被选中的作业分配所需的系统资源。对被选中运行的作业必须按照它们各自的作业说明书规定的步骤进行控制。
本实验要求模拟作业调度的实现,了解作业调度在操作系统中的作用。
三、实验题目
采用先来先服务算法和运行时间最短者优先算法模拟设计作业调度程序。
[提示]:
(1) 作业调度程序负责从输入井选择若干个作业进入主存,为它们分配必要的资源,当它们能够被进程调度选中时,就可占用处理器运行。作业调度选择一个作业的必要条件是系统中现有的尚未分配的资源可满足该作业的资源要求。但有时系统中现有的尚未分配的资源既可满足某个作业的要求也可满足其它一些作业的要求,那么,作业调度必须按一定的算法在这些作业中作出选择。先来先服务算法是按照作业进入输入井的先后次序来挑选作业,先进入输入井的作业优先被挑选,当系统中现有的尚未分配的资源不能满足先进入输入井的作业时,那么顺序挑选后面的作业。运行时间最短者优先算法总是按作业要求运行的时间来选择作业,每次挑选要求运行时间短且资源要求能满足的作业先进入主存执行。
(2) 为了表示暂存在输入井中的各个作业的情况(作业信息在输入井中的位置、作业的资源要求等),常常采用二级目录结构:作业表和预输入表。例如:
“预输入”程序为每个作业在作业表中占一登记栏,且把作业信息存放到输入井中并按文件(源程序文件、数据文件等)登记在预输入表中。“预输入”程序工作时还把作业控制语句集中,作为作业说明书文件存放在输入井并登记在预输入表的第一栏中,同时把用户在作业说明书中提出的资源要求登记在作业表中。
本实验模拟作业调度,所以可不考虑有关“预输入”程序的工作。假定“预输入”程序已经把一批作业的信息存放在输入井了,并为它们建立了如下的作业表:
其中状态分三种:
收容状态——作业已在输入井,但尚未被选中执行;----READY
执行状态——作业被选中,正在执行;----RUNNING
完成状态——作业执行结束。--END
(3) 假定主存中可容纳多道作业同时执行,那么作业调度按调度算法和资源分配情况查作业表,从中选择若干作业,对每个被选中的作业创建一个作业控制进程且使它们处于就绪状态,同时把选中作业的作业说明书读入主存。
处理器调度按调度策略选择作业调度进程或作业控制进程轮流占有处理器(处理器调度参见实验一)。作业控制进程按作业说明书控制作业执行,当一个作业执行结束后,作业调度再从输入井中选择一个作业进入主存,直到输入井中的作业都执行结束,通知操作员再预输入一批作业。
本实验主要模拟作业调度,所以对处理器调度、作业控制过程简化。用输入随机数模拟处理器调度,用输入“用户名、作业名”模拟一个作业已经执行结束。于是,本实验的模拟流程可参考图2-1。
(4) 假定某系统可供用户使用的主存空间共1M,并有5台磁带机。主存分配采用可变分区分配方式且主存中信息不允许移动,对磁带机采用静态分配策略,主存中可同时执行的作业限定为两道,作业调度分别采用先来先服务算法和运行时间最短者优先算法,参考图2-1设计模拟作业调度的程序。假定作业表的初值如提示(2),分别在两种算法控制下运行设计的程序,依次显示被选中作业的用户名和作业名。比较两种作业调度算法选择作业的次序。
在模拟作业执行结束输入被撤离作业的用户名、作业名时,应根据已在主存中的作业需运行的时间来决定撤离的先后次序。
四:实验报告
(1)实验题目:作业调度
(2)程序所用的数据结构及其说明
#define MEMLENGTH 1024//主存大小
#define RECORDERNUM 2 5//磁带数量
typedef struct JCB
{
char*UserID
char*JobID;
char*status;//-1被选中,0完成,1执行,2收容
float RunTime;
int ApplyMem; //所需内存资源
int ApplyRecorder;
int MemoryNum; //所需磁带资源
} JCB;
typedef struct PCB//PCB类型的结构体
{
JCB *next;
char state;//状态R-就绪E-结束,W-等待
int order;
}PCB;//0资源不满足1主存满足条件2磁带满足条件3两种均满足条件
(3)流程图
(4)源程序代码
#include "stdio.h"
#include "stdlib.h"
#define MEMLENGTH 1024
#define RECORDERNUM 25
typedef struct JCB
{
char*UserID;
char*JobID;
char status;
float RunTime;
int ApplyMem;
int MemoryNum;
int ApplyRecorder;
struct JCB*next;
}JCB;
JCB*JTfind(JCB*jcb,char status)
{
JCB*p;
if(jcb==NULL) return NULL;
for(p=jcb->next;p!=NULL&&p->status!=status;p=p->next);
return p;
}
void JTinit(JCB*p)
{
p->next=(JCB*)malloc(sizeof(JCB));
p->next->next=NULL;
p->UserID=p->JobID=NULL;
}
void JTinsert(JCB*jt,JCB*j)
{
JCB*p;
for(p=jt;p->next!=NULL;p=p->next);
p->next=j;
j->next=NULL;
}
int JTdel(JCB*jt,JCB*j)
{
JCB*p;
if(j==NULL)return 0;
p=jt->next;
if(p==NULL)return 0;
for(;p->next!=NULL&&p->next!-j;p=p->next);
if(p->next==NULL)return 0;
p->next-j->next;
return 1;
}
void JTrelease(JCB*jt)
{
JCB*p;
JCB*q;
p=jt->next;
if(p==NULL)return;
for(q=p->next;q!=NULL;p=q,q=q->next)
free(p);
}
JCB jt;
int memory=MEMLENGTH;
int recorder=RECORDERNUM;
int count=0;
int num=5;
void large()
{
JCB*ep,*pd;
int i;
ep=JTfind(&jt,'s');
if(ep!=NULL)
{
pd=ep;
while((pd=JTfind(pd,'s'))!=NULL)
if(ep->RunTime>pd->RunTime)
ep=pd;
if(count<2)
{
if(memory>ep->ApplyMem)
{
if(recorder>=ep->ApplyRecorder)
{
ep->status='e';
JTdel(&jt,ep);
JTinsert(&jt,ep);
memory-=ep->ApplyRecorder;
count++;
printf("The selected job's name is %s\n",ep->JobID);
printf("The selected user is %s\n",ep->UserID);
}
else printf("The recorder is not adequate \n");
}
else printf("The main memory is not adequate \n");
}
else printf("The system can not excute any more jobs!\n");
}
else printf("The saved queue is empty!\n");
}
void small()
{
char*str1,str2;
char i;
JCB *ep;
ep=JTfind(&jt,'e');
if(ep==NULL)
{
printf("主存中无作业!\n");
return;
}
/*先来先服务*/
else
{
printf("Be executiving custmoer %s\n",ep->JobID);
/*printf("输入用户名字,作业名字A,B,C,D,E!\n");*/
printf("The user and job are:%s,%s\n",ep->UserID,ep->JobID);
count--;
num--;
memory+=ep->ApplyMem;
recorder+=ep->ApplyRecorder;
JTdel(&jt,ep);
}
return;
}
void init()
{
JCB*p;
JTinit(&jt);
p=(JCB*)malloc(sizeof(JCB));
p->UserID=(char*)malloc(10*sizeof(char));
p->UserID="A";
p->JobID=(char*)malloc(10*sizeof(char));
p->JobID="ZYA";
p->status='s';
p->RunTime=0.3;
p->ApplyMem=15;
p->ApplyRecorder=2;
JTinsert(&jt,p);
p=(JCB*)malloc(sizeof(JCB));
p->UserID=(char*)malloc(10*sizeof(char));
p->UserID="B";
p->JobID=(char*)malloc(10*sizeof(char));
p->JobID="ZYB";
p->status='s';
p->RunTime=0.5;
p->ApplyMem=60;
p->ApplyRecorder=1;
JTinsert(&jt,p);
p=(JCB*)malloc(sizeof(JCB));
p->UserID=(char*)malloc(10*sizeof(char));
p->UserID="C";
p->JobID=(char*)malloc(10*sizeof(char));
p->JobID="ZYC";
p->status='s';
p->RunTime=0.1;
p->ApplyMem=50;
p->ApplyRecorder=3;
JTinsert(&jt,p);
p=(JCB*)malloc(sizeof(JCB));
p->UserID=(char*)malloc(10*sizeof(char));
p->UserID="D";
p->JobID=(char*)malloc(10*sizeof(char));
p->JobID="ZYD";
p->status='s';
p->RunTime=0.4;
p->ApplyMem=10;
p->ApplyRecorder=2;
JTinsert(&jt,p);
p=(JCB*)malloc(sizeof(JCB));
p->UserID=(char*)malloc(10*sizeof(char));
p->UserID="E";
p->JobID=(char*)malloc(10*sizeof(char));
p->JobID="ZYE";
p->status='s';
p->RunTime=0.1;
p->ApplyMem=30;
p->ApplyRecorder=3;
JTinsert(&jt,p);
}
void main()
{
int operation;
init();
for(;num!=0;)
{
printf("\n\nPlease input a random integer in the range of(0~~9)\n");
scanf("%d",&operation);
if((operation>9)||(operation<0))continue;
if(operation>5)
large();
else
small();
}
JTrelease(&jt);
printf("Please the system operation input jobs.\n");
}
(5)运行截图
操作系统进程调度实验报告一实验目的用高级语言编写和调试一个进程调度程序以加深对进程的概念及进程调度算法的解进程调度时进程管理的主要…
操作系统实验题设计一若干并发进程的进程调度程序一实验目的无论是批处理系统分时系统还是实时系统用户进程数一般都大于处理机数这将导致用…
实验一进程调度实验专业XXXXX学号XXXXX姓名XXX实验日期20XX年XX月XX日一实验目的通过对进程调度算法的模拟加深对进程…
实验二进程调度实验内容进程调度模拟实验实验目的通过模拟进程调度算法了解进程调度的过程并比较不同的调度算法的区别实验题目设计一段程序…
目录1课程设计目的32课程设计要求33相关知识34需求分析45概要设计56详细设计67测试修改及运行结果138参考文献159结束语…
实验报告课程名称实验名称班学姓级号名指导教师基础实验一时间表调度实验1实验目的驱动交换网络实验用来考查学生对时间表调度原理的掌握情…
实验报告课程名称实验名称班学姓级号名指导教师基础实验一时间表调度实验1实验目的驱动交换网络实验用来考查学生对时间表调度原理的掌握情…
操作系统实验题设计一若干并发进程的进程调度程序一实验目的无论是批处理系统分时系统还是实时系统用户进程数一般都大于处理机数这将导致用…
沈阳理工大学课程设计任务书1沈阳理工大学目录1课程设计目的32课程设计要求33相关知识34需求分析45概要设计56详细设计67测试…