执行第三个作业:
完成:
六、思考题
1、 写出每种算法的调度策略,最后比较各种算法的优缺点。
答:先来先服务算法是根据作业的进入时间来排序,到达时间短的先运行,优点是实现简单,缺点是运行时间慢。
短作业优先算法是根椐作业的估计运行时间来排序,估计运行时间短的先运行,优点是运行时间快,缺点是实现起来比较复杂。
2、 选择调度算法的依据是什么?
答:如果作业要求的速度不高,而且作业比较小型,那就最好用先来先服务算法。
如果作业要求的速度高,作业流程复杂,那就最好用短作业优先算法。 七、源代码
#include \#include
#define getpch(type) (type*)malloc(sizeof(type)) #define NULL 0
struct worktime{
float Tb; //作业运行时刻 float Tc; //作业完成时刻 float Ti; //周转时间 float Wi; //带权周转时间 };
struct jcb { /*定义作业控制块JCB */ char name[10]; //作业名
float subtime; //作业提交时间
float runtime; //作业所需的运行时间 char resource; //所需资源
float Rp; //后备作业响应比 char state; //作业状态 struct worktime wt;
struct jcb* link; //链指针 }*jcb_ready=NULL,*j;
typedef struct jcb JCB;
float T=0;
void sort() /* 建立对作业进行提交时间排列函数*/ {
JCB *first, *second; int insert=0;
if((jcb_ready==NULL)||((j->subtime)<(jcb_ready->subtime))) /*作业提交时间最短的,插入队首*/ {
j->link=jcb_ready; jcb_ready=j; T=j->subtime; j->Rp=1; }
else /* 作业比较提交时间,插入适当的位置中*/ {
first=jcb_ready; second=first->link; while(second!=NULL) {
if((j->subtime)<(second->subtime)) /*若插入作业比当前作业提交时间短,*/ { /*插入到当前作业前面*/ j->link=second; first->link=j; second=NULL; insert=1; }
else /* 插入作业优先数最低,则插入到队尾*/ {
first=first->link; second=second->link; } }
if (insert==0) first->link=j; } }
void HRNget()/* 获取队列中的最高响应作业 */ {
JCB *front,*mintime,*rear; int ipmove=0;
mintime=jcb_ready; rear=mintime->link; while(rear!=NULL)
if ((rear!=NULL)&&(T>=rear->subtime)&&(mintime->Rp)<(rear->Rp)) {
front=mintime; mintime=rear; rear=rear->link; ipmove=1; } else
rear=rear->link; if (ipmove==1){
front->link=mintime->link; mintime->link=jcb_ready; }
jcb_ready=mintime;
}
void input() /* 建立作业控制块函数*/ {
int i,num;
printf(\请输入作业数:\ scanf(\ for(i=0;i printf(\作业号No.%d:\ j=getpch(JCB); printf(\输入作业名:\ scanf(\ printf(\输入作业提交时刻:\ scanf(\ printf(\输入作业运行时间:\ scanf(\ printf(\ j->state='w'; j->link=NULL; sort(); /* 调用sort函数*/ } } int space() { int l=0; JCB* jr=jcb_ready; while(jr!=NULL) { l++; jr=jr->link; } return(l); } void disp(JCB* jr,int select) /*建立作业显示函数,用于显示当前作业*/ { if (select==3) printf(\作业 服务时间 响应比 运行时刻 完成时刻 周转时间 带权周转时间 \\n\ else printf(\作业 服务时间 运行时刻 完成时刻 周转时间 带权周转时间 \\n\ printf(\ printf(\ if (select==3) printf(\ if (j==jr){ printf(\ printf(\ printf(\ printf(\ } printf(\} int destroy() /*建立作业撤消函数(作业运行结束,撤消作业)*/ { printf(\作业 [%s] 已完成.\\n\ free(j); return(1); } void check(int select) /* 建立作业查看函数 */ { JCB* jr; printf(\当前正在运行的作业是:%s\显示当前运行作业*/ disp(j,select); jr=jcb_ready; printf(\当前就绪队列状态为:\\n\显示就绪队列状态*/ while(jr!=NULL) { jr->Rp=(T-jr->subtime)/jr->runtime; disp(jr,select); jr=jr->link; } destroy(); } void running(JCB* jr) /* 建立作业就绪函数(作业运行时间到,置就绪状态*/ { if (T>=jr->subtime) jr->wt.Tb=T; else jr->wt.Tb=jr->subtime; jr->wt.Tc=jr->wt.Tb+jr->runtime; jr->wt.Ti=jr->wt.Tc-jr->subtime; jr->wt.Wi=jr->wt.Ti/jr->runtime; T=jr->wt.Tc; } int main() /*主函数*/ { int select=0,len,h=0; float sumTi=0,sumWi=0; input(); len=space(); printf(\请选择作业调度算法:\ scanf(\ while((len!=0)&&(jcb_ready!=NULL)) { h++; printf(\执行第%d个作业 \\n\ j=jcb_ready; jcb_ready=j->link; j->link=NULL; j->state='R'; running(j); sumTi+=j->wt.Ti; sumWi+=j->wt.Wi; check(select); if (select==3&&h printf(\作业已经完成.\\n\ printf(\此组作业的平均周转时间:%.2f\\n\ printf(\此组作业的带权平均周转时间:%.2f\\n\ getchar(); } 实验三:主存空间的分配和回收 一、实验目的 熟悉主存的分配与回收。理解在不同的存储管理方式下,如何实现主存空间的分配与回收。掌握动态分区分配方式中的数据结构和分配算法及动态分区存储管理方式及其实现过程。 二、实验内容和要求 主存的分配和回收的实现是与主存储器的管理方式有关的。所谓分配,就是解决多道作业或多进程如何共享主存空间的问题。所谓回收,就是当作业运行完成时将作业或进程所占的主存空间归还给系统。 可变分区管理是指在处理作业过程中建立分区,使分区大小正好适合作业的需求,并且分区个数是可以调整的。当要装入一个作业时,根据作业需要的主存量查看是否有足够的空闲空间,若有,则按需要量分割一个分区分配给该作业;若无,则作业不能装入,作业等待。随着作业的装入、完成,主存空间被分成许多大大小小的分区,有的分区被作业占用,而有的分区是空闲的。 实验要求使用可变分区存储管理方式,分区分配中所用的数据结构采用空闲分区表和空闲分区链来进行,分区分配中所用的算法采用首次适应算法、循环首次适应算法、最佳适应算法三种算法来实现主存的分配与回收。同时,要求设计一个实用友好的用户界面,并显示分配与回收的过程。 三、实验主要仪器设备和材料 硬件环境:IBM-PC或兼容机 软件环境:VC++ 6.0 四、实验原理及设计方案 1、循环首次适应算法 在该算法中,把主存中所有空闲区按其物理地址递增的次序排列。在为作业分配存储空间时,从上次找到的空闲分区的下一个空闲分区开始查找,直到找到第一个能满足要求的空闲区,从中划出与请求的大小相等的存储空间分配给作业,余下的空闲区仍留在空闲区表或链中。 2、 实验步骤 (1)初始化空闲分区; (2)反复对现有的空闲分区进行进程创建和撤消,即内存分配和回收; (3)退出。 3、流程图