操作系统实验指导_源码参考
华东交通大学
软件学院
操作系统实验报告
专业: 计算机科学与技术
姓名: 林庆达
学号: 3103005138
2005-6
试验一进程调度
一、实验目的:
编写和调试一个进程调度程序,以加深对进程的概念及进程调度算法的理解。
二、实验内容:以两种典型算法为例说明实现的算法
(一)、最高优先数优先的调度算法
1、实验原理
进程调度算法:采用最高优先数优先
的调度算法(即把处理机分配给优先数最
高的进程)和先来先服务算法。
每个进程有一个进程控制块(PCB)
表示。进程控制块可以包含如下信息:进
程名、优先数、到达时间、需要运行时间、
已用CPU时间、进程状态等等。
进程的优先数及需要的运行时间可以
事先人为地指定(也可以由随机数产生)。
进程的到达时间为进程输入的时间。
进程的运行时间以时间片为单位进
行计算。
每个进程的状态可以是就绪W
(Wait)、运行R(Run)、或完成F(Finish)
三种状态之一。
就绪进程获得CPU后都只能运行一
个时间片。用已占用CPU时间加1来表示。
如果运行一个时间片后,进程的已占
用CPU时间已达到所需要的运行时间,
则撤消该进程,如果运行一个时间片后进
程的已占用CPU时间还未达所需要的运
行时间,也就是进程还需要继续运行,此
时应将进程的优先数减1(即降低一级),
然后把它插入就绪队列等待CPU。
每进行一次调度程序都打印一次运
行进程、就绪队列、以及各个进程的PCB,
以便进行检查。
重复以上过程,直到所有进程都完成为止。
2、源代码:
#include "stdio.h"
#include
#include
#define getpch(type) (type*)malloc(sizeof(type))
#define NULL 0
struct pcb { /* 定义进程控制块PCB */
char name[10]; /*定义进程名称*/
char state; /*进程状态*/
int super; /*优先数*/
int ntime; /*需要运行的时间*/
int rtime; /*已占用的CPU时间*/
struct pcb* link;
}*ready=NULL,*p;
typedef struct pcb PCB; /*pcb表*/
sort() /* 建立对进程进行优先级排列函数*/
{ PCB *first, *second;
int insert=0;
if((ready==NULL)||((p->super)>(ready->super))) /*优先级最大者,插入队首*/ { p->link=ready;
ready=p;
}
else /* 进程比较优先级,插入适当的位置中*/
{ first=ready;
second=first->link;
while(second!=NULL)
{ if((p->super)>(second->super)) /*若插入进程比当前进程优先数大,*/ { /*插入到当前进程前面*/
p->link=second;
first->link=p;
second=NULL;
insert=1;
}
else /* 插入进程优先数最低,则插入到队尾*/
{ first=first->link;
second=second->link;
}
}
if(insert==0) first->link=p;
}
}
input() /* 建立进程控制块函数*/
{ i nt i,num;
clrscr(); /*清屏*/
printf("\n 请输入进程号?");
scanf("%d",&num);
for(i=0;i { printf("\n 进程号No.%d:\n",i); p=getpch(PCB); printf("\n 输入进程名:"); scanf("%s",p->name); printf("\n 输入进程优先数:"); scanf("%d",&p->super); printf("\n 输入进程运行时间:"); scanf("%d",&p->ntime); printf("\n"); p->rtime=0;p->state='w'; p->link=NULL; sort(); /* 调用sort函数*/ } } int space() { int l=0; PCB* pr=ready; while(pr!=NULL) { l++; pr=pr->link; } return(l); } disp(PCB * pr) /*建立进程显示函数,用于显示当前进程*/ { printf("\n qname \t state \t super \t ndtime \t runtime \n"); printf("|%s\t",pr->name); printf("|%c\t",pr->state); printf("|%d\t",pr->super); printf("|%d\t",pr->ntime); printf("|%d\t",pr->rtime); printf("\n"); } check() /* 建立进程查看函数,检查等待队列的进程是否进入就绪队列*/ { PCB* pr; printf("\n **** 当前正在运行的进程是:%s",p->name); /*显示当前运行进程*/ disp(p); pr=ready; printf("\n ****当前就绪队列状态为:\n"); /*显示就绪队列状态*/ while(pr!=NULL) { disp(pr); pr=pr->link; } } destroy() /*建立进程撤消函数(进程运行结束,撤消进程)*/ { printf("\n 进程[%s] 已完成.\n",p->name); free(p); } running() /* 建立进程就绪函数(进程运行时间到,置就绪状态*/ { (p->rtime)++; if(p->rtime==p->ntime) destroy(); /* 调用destroy函数*/ else { (p->super)--; p->state='w'; sort(); /*调用sort函数*/ } } main() /*主函数*/ { int len, h=0; char ch; input(); len=space(); while((len!=0)&&(ready!=NULL)) { ch=getchar(); h++; printf("\n The execute number:%d \n",h); p=ready; ready=p->link; p->link=NULL; p->state='R'; check(); running(); printf("\n 按任一键继续......"); ch=getchar(); } printf("\n\n 进程已经完成.\n"); ch=getchar(); } 3、运行结果: 请输入进程号?5 进程号No.0: 输入进程名:A 输入进程优先数:2 输入进程运行时间:1 进程号No.1: 输入进程名:B 输入进程优先数:3 输入进程运行时间:1 进程号No.2: 输入进程名:C 输入进程优先数:1 输入进程运行时间:1 进程号No.3: 输入进程名:D 输入进程优先数:4 输入进程运行时间:1 进程号No.4: 输入进程名:E 输入进程优先数:5 输入进程运行时间:1 The execute number:1 ****当前正在运行的进程是:E Qname state super ndtime runtime E R 5 1 0 ****当前就绪队列状态为: Qname state super ndtime runtime D w 4 1 0 B w 3 1 0 A w 2 1 0 C w 1 1 0 进程[E]已完成 按任一键继续…… The execute number:2 ****当前正在运行的进程是:D Qname state super ndtime runtime D R 4 1 0 ****当前就绪队列状态为: Qname state super ndtime runtime B w 3 1 0 A w 2 1 0 C w 1 1 0 进程[D]已完成 按任一键继续…… The execute number:3 ****当前正在运行的进程是:B Qname state super ndtime runtime B R 3 1 0 ****当前就绪队列状态为: Qname state super ndtime runtime A w 2 1 0 C w 1 1 0 进程[B]已完成 按任一键继续…… The execute number:4 ****当前正在运行的进程是:A Qname state super ndtime runtime A R 2 1 0 ****当前就绪队列状态为: Qname state super ndtime runtime C w 1 1 0 进程[A]已完成 按任一键继续…… The execute number:5 ****当前正在运行的进程是:c Qname state super ndtime runtime c R 1 1 0 ****当前就绪队列状态为: 进程[C]已完成 按任一键继续…… 进程已经完成 (二)、简单轮转法 1、实验原理 在分时系统中,都毫无例外采用时间片轮 转法。在一种简单的轮转法中,系统将所有就 绪进程按FIFO规则排成一个队列,把CPU分 配给队首进程,并规定它执行一给定的时间如 100ms,称此时间间隔为时间片。当时间片完 成时,系统产生一个时钟中断,剥夺该进程的 执行,将它送至就绪队列的末尾,并把处理机 分配给就绪队列的新队首进程,同样也让它执 行一个时间片。这样,就绪队列中的所有进程 均可获得一个时间片的处理机而运行。就绪队 列中的进程在依次执行时,可能发生以下三种 情况:(1)进程未用完一个时间片就结束,这时 系统应提前调度;(2)进程在执行过程中提出 I/O请求而阻塞,系统应将它放入相应的阻塞 队列并引起调度;(3)进程完成一个时间片后尚 未完成,系统应将它重新放到就绪队列的末 尾,等待下次执行。由于在分时系统中,键盘命令的执行时间较短,大多能在一个时间片内执行完毕,因此分时系统的实际响应时间将比Nq(N是同时性用户数,q是时间片大小)小。 2、源代码: #include /*定义一个pcb的结构体*/ struct pcb { char name; /*进程名*/ int time; /*进程执行时间*/ }; void main() { int n,i,j,flag=1; struct pcb a[100]; /*最多可以有100个进程*/ printf("输入进程个数:"); scanf("%d",&n); getchar();/*接收回车*/ for(i=0;i { printf("输入进程的名字:\n"); scanf("%c",&a[i].name); /*以字符接收进程名*/ getchar();/*接收回车*/ printf("输入占用的时间片:"); /*输入进程占用的时间片*/ scanf("%d",&a[i].time); getchar();/*接收回车*/ } i=0; while(flag && n>0) /*若进程数为空,结束程序*/ { if(a[i].time!=0) /*就绪队列是否为空*/ { printf("%c",a[i].name); /*进程执行一次,打印出该进程*/ a[i].time--; /*使该进程占用的时间片减1*/ } for(j=0;j if(a[j].time) /*若进程所占用的时间片不为0,仍执行下一进程*/ { flag=1; break; } else /*若进程所占用的时间片为0,说明已经完成,跳过执行下一进程*/ flag=0; i=(++i)%n; /*继续执行下一个进程,i+1*/ } printf("\n"); } 3、运行结果: 输入进程个数:5 输入进程的名字: A 输入占用的时间片:2 输入进程的名字: B 输入占用的时间片:3 输入进程的名字: C 输入占用的时间片:1 输入进程的名字: D 输入占用的时间片:4 输入进程的名字: E 输入占用的时间片:5 ABCDEABDEBDEDEE Press any key to continue 六、心得体会: 操作系统是计算机系统中必不可少的系统软件。它是计算机系统中各种资源的管理者和各种活动的组织者、指挥者。操作系统采用时间片法调度进程,使系统资源得到充分的利用,用户也可以花更少的时间完成更多的工作,通过这次进程调度实验,让我明白了系统时间片的调度方法,对操作系统理论的学习更加深一层.并且增强了用C语言的编程能力。在编程的过程中,遇到了种种困难,并且一一的克服了,这使我产生很大的成就感。 实验二作业调度 一、实验名称:进程调度 用高级语言编写和调试一个或多个作业调度的模拟程序,加深对作业调度算法的理解。 二、实验内容: 在单道批处理系统中,作业一投入运行,它就占有计算机的一切资源直到作业完成为止,因此调度作业时不必考虑它所需要的资源是否得到满足,它所占用的CPU时限等因素。 而在多道批处理系统中,作业首先存放在外存,当系统拥有的资源足够分配给一个作业,就将资源分配给此作业,并将此作业调进内存。当系统资源不足以分配给一个作业时,则等待已经分配资源的作业运行完成后释放资源增加系统资源。 (一)、为单道批处理系统设计一个作业调度程序 1、实验原理。 作业等待算法:分别采用先来先服务(FCFS),最短作业优先(SJF)、响应比高者优先(HRN)的调度算法。 (1)先来先服务(FCFS)算法 先来先服务作业调度算法是一种较简单的作业调度算法,即每次调度是从后备作业队列中选择一个最先进入该队列的作业,将它调入内存,分配资源、创建相应的进程,放入进程就绪队列准备运行。FCFS算法利于长作业,不利于短作业,而大多数的作业是I/O繁忙的短作业。以FCFS作为主调度算法是不常用的。 (2)短作业优先调度算法(SJF) 短作业优先调度算法是指操作系统在进行作业调度时以作业长短作为优先级进行调度。该调度算法可以照顾到实际上占作业总数绝大部分的短作业,使它们能比长作业优先调度执行。这时后备作业队列按作业优先级由高到低顺序排列,当作业进入后备队列时要按该作业优先级放置到后备队列相应的位置。实践证明,该调度算法的性能是最好的,单位时间的作业吞吐量也最大,但也存在缺点:对长作业极为不利。 (3)响应比高者优先(HRN)的调度算法 采用响应比高者优先调度算法,进行调度时必须计算出系统中的所有满足必要条件作业的响应比;从中选择响应比最高的一个作业装入主存储器、分配资源,由于是实验,所以就用将作业的作业控制块出队,并输出作业的作业名代替装入主存储器,同时修改系统的资源数量;用同样方法选择第二个、第三个……直到不再有满足必要条件的作业。 调度算法的流程图如下 : 2、源代码及运行结果: #include "stdio.h" #define getjcb(type) (type*)malloc(sizeof(type)) #define NULL 0 int n=0,time=0;float eti,ewi; struct jcb{ char name[10]; /* 作业名 */ char state; /* 作业状态 */ int ts; /* 提交时间 */ float super; /* 优先权 */ int tb; /* 开始运行时间 */ int tc; /* 完成时间 */ float ti; /* 周转时间 */ float wi; /* 带权周转时间 */ int ntime; /* 作业所需运行时间 */ struct jcb *link; /* 结构体指针 */ } *p,*q,*head=NULL; typedef struct jcb JCB; inital(){int i; printf("\n输入作业数:\n"); scanf("%d",&n); printf("输入:\n作业名\t到达时间\t服务时间\n"); for(i=0;i scanf("%s\t%d\t%d",&p->name,&p->ts,&p->ntime); if(head==NULL) head=q=p; else{ q->link=p; q=p; } }} void print(JCB *pr,int m){ JCB *p; printf("\ntime=%d",time); if(m==3){ printf("\n作业名\t状态\t到达时间\t服务时间\t优先权\t\t完成时间\t周转时间\t 带权周转时间\n"); printf("%s\t%c\t%d\t%d\t%4.2f\t%d\t%4.2f\t%4.2f\n", pr->name,pr->state,pr->ts,pr->ntime,pr->super,pr->tc,pr->ti,pr->wi); } else { printf("\n作业名状态到达时间服务时间完成时间周转时间带权周转时间\n"); printf("%s\t%c\t%d\t%d\t%d\t%4.2f\t%4.2f\n", pr->name,pr->state,pr->ts,pr->ntime,pr->tc,pr->ti,pr->wi); } p=head; do{ if(p->state=='W') if(m==3){ printf("%s\t%c\t%d\t%d\t%4.2f\n", p->name,p->state,p->ts,p->ntime,p->super); } else{ printf("%s\t%c\t%d\t%d\n", p->name,p->state,p->ts,p->ntime); } p=p->link; }while(p!=NULL); p=head; do{ if(p->state=='F') if(m==3){ printf("%s\t%c\t%d\t%d\t%4.2f\t%d\t%4.2f\t%4.2f\n", p->name,p->state,p->ts,p->ntime,p->super,p->tc,p->ti,p->wi); } else{printf("%s\t%c\t%d\t%d\t%d\t%4.2f\t%4.2f\n", p->name,p->state,p->ts,p->ntime,p->tc,p->ti,p->wi); } p=p->link; }while(p!=NULL); } void last(){eti/=n;ewi/=n; printf("\n平均周转时间=%7.3f\n平均带权周转时间=%7.3f\n",eti,ewi); } super(){JCB *padv; padv=head; do{ if(padv->state=='W'&&padv->ts<=time) padv->super=(float)(time-padv->ts+padv->ntime)/padv->ntime; padv=padv->link; }while(padv!=NULL); } void hrn(m){JCB *min; int i,iden; for(i=0;i super(); do{if(p->state=='W'&&p->ts<=time) if(iden){ min=p;iden=0;} else if(p->super>min->super) min=p; if(iden) {i--;time++;printf("\ntime=%d",time); if(time>1000){printf("\nruntime is too long...error...");getch();} } else{ running(min,m); } }} void sjf(int m){ JCB *min; int i,iden; for(i=0;i do{if(p->state=='W'&&p->ts<=time) if(iden){ min=p;iden=0; } else if(p->ntime p=p->link; }while(p!=NULL) ; if(iden) {i--;printf("\ntime=%d",time);time++; if(time>100){printf("\nruntime is too long...error");getch();} } else{running(min,m);} }} fcfs(int m){ int i,iden; for(i=0;i do{if(p->state=='W'&&p->ts<=time) iden=0; if(iden)p=p->link; }while(p!=NULL&&iden) ; if(iden) { i--;printf("\ntime=%d",time);time++; if(time>100){printf("\nruntime is too long...error");getch();} } else{ running(p,m); } }} running(JCB *p,int m){ p->tb=time;p->state='R'; p->tc=p->tb+p->ntime; p->ti=(float)(p->tc-p->ts); p->wi=(float)(p->ti/p->ntime); eti+=p->ti; ewi+=p->wi; print(p,m); time+=p->ntime; p->state='F'; printf("\n作业%s已经完成!\npress any key to continue...\n",p->name); getch(); } void runjcb(int m){ printf("\n\n作业开始运行"); switch(m){case 1:fcfs(m);break; case 2:sjf(m);break; case 3:hrn(m);break; default:printf("\n运行错误!\n");exit(); }} start(){ int m; char str[100]="\n选择调度算法:\n1.先来先服务FCFS\n2.最短作业优先SJF\n3.响应比高者优先HRN\n" ; printf("%s",str); m=getch()-48; inital(); if(1<=m&&m<=3) runjcb(m); else { printf("\n选择错误,请重新选择!\n"); } last(); } main(){start(); printf("\n所有作业完成!"); getch(); } 运行结果: 1、选择先来先服务FCFS 选择调度算法: 1.先来先服务FCFS 2.最短作业优先SJF 3.响应比高者优先HRN 输入作业数: 5 输入: 作业名到达时间服务时间 A 0 4 B 1 3 C 2 5 D 3 2 E 4 4 作业开始运行 Time=0 作业名状态到达时间服务时间完成时间周转时间带权周转时间 A R 0 4 4 4.00 1.00 B W 1 3 C W 2 5 D W 3 2 E W 4 4 作业A已经完成 Press any key to continue… Time=4 作业名状态到达时间服务时间完成时间周转时间带权周转时间 B R 1 3 7 6.00 2.00 C W 2 5 D W 3 2 E W 4 4 A F 0 4 4 4.00 1.00 作业B已经完成 Press any key to continue… Time=7 作业名状态到达时间服务时间完成时间周转时间带权周转时间 C R 2 5 12 10.00 2.00 D W 3 2 E W 4 4 A F 0 4 4 4.00 1.00 B F 1 3 7 6.00 2.00 作业C已经完成 Press any key to continue… Time=12 作业名状态到达时间服务时间完成时间周转时间带权周转时间 D R 3 2 14 11.00 5.50 E W 4 4 A F 0 4 4 4.00 1.00 B F 1 3 7 6.00 2.00 C F 2 5 12 10.00 2.00 作业D已经完成 Press any key to continue… Time=14 作业名状态到达时间服务时间完成时间周转时间带权周转时间 E R 4 4 18 14.00 3.50 A F 0 4 4 4.00 1.00 B F 1 3 7 6.00 2.00 C F 2 5 12 10.00 2.00 D F 3 2 14 11.00 5.50 作业E已经完成 Press any key to continue… 平均周转时间=9.000 平均带权周转时间=2.800 所有作业完成! 2、选择最短作业优先SJF(简要过程) …… 作业开始运行 Time=0 作业名状态到达时间服务时间完成时间周转时间带权周转时间 A R 0 4 4 4.00 1.00 B W 1 3 C W 2 5 D W 3 2 E W 4 4 作业A已经完成 Press any key to continue… Time=4 作业名状态到达时间服务时间完成时间周转时间带权周转时间 D R 3 2 6 3.00 1.50 B W 1 3 C W 2 5 E W 4 4 A F 0 4 4 4.00 1.00 作业D已经完成 Press any key to continue… Time=6 作业名状态到达时间服务时间完成时间周转时间带权周转时间 B r 1 3 9 8.00 2.67 C W 2 5 E W 4 4 A F 0 4 4 4.00 1.00 D F 3 2 6 3.00 1.50 作业B已经完成 Press any key to continue… Time=9 作业名状态到达时间服务时间完成时间周转时间带权周转时间 E R 4 4 13 9.00 2.25 C W 2 5 A F 0 4 4 4.00 1.00 B F 1 3 9 8.00 2.67 D F 3 2 6 3.00 1.50 作业E已经完成 Press any key to continue… Time=13 作业名状态到达时间服务时间完成时间周转时间带权周转时间 C R 2 5 18 16.00 3.20 A F 0 4 4 4.00 1.00 B F 1 3 9 8.00 2.67 D F 3 2 6 3.00 1.50 E F 4 4 13 9.00 2.25 作业C已经完成 Press any key to continue… 平均周转时间=8.000 平均带权周转时间=2.123 所有作业完成! 3、响应比高者优先HRN(简要过程) …… 作业开始运行 Time=0 作业名状态到达时间服务时间优先权完成时间周转时间带权周转时间 A R 0 4 1.00 4 4.00 1.00 B W 1 3 -0.00 C W 2 5 D W 3 2 E W 4 4 作业A已经完成 Press any key to continue… Time=4 作业名状态到达时间服务时间优先权完成时间周转时间带权周转时间 B R 1 3 2.00 7 6.00 2.00 C W 2 5 D W 3 2 E W 4 4 A F 0 4 1.00 4 4.00 1.00 作业B已经完成 Press any key to continue… Time=7 作业名状态到达时间服务时间优先权完成时间周转时间带权周转时间 D R 3 2 3.00 9 6.00 3.00 C W 2 5 E W 4 4 A F 0 4 1.00 4 4.00 1.00 B F 1 3 2.00 7 6.00 2.00 作业D已经完成 Press any key to continue… Time=9 作业名状态到达时间服务时间优先权完成时间周转时间带权周转时间 C R 2 5 2.40 14 12.00 2.40 E W 4 4 2.25 A F 0 4 1.00 4 4.00 1.00 B F 1 3 2.00 7 6.00 2.00 D F 3 2 3.00 9 6.00 3.00 作业C已经完成 Press any key to continue… Time=14 作业名状态到达时间服务时间优先权完成时间周转时间带权周转时间 E R 4 4 3.25 18 14.00 3.50 A F 0 4 1.00 4 4.00 1.00 B F 1 3 2.00 7 6.00 2.00 C F 2 5 2.40 14 12.00 2.40 D F 3 2 3.00 9 6.00 3.00 作业E已经完成 Press any key to continue… 平均周转时间=8.400 平均带权周转时间=2.380 所有作业完成! (二)、编写并调度一个多道程序系统的作业调度模拟程序。 作业调度算法:采用基于先来先服务的调度算法。可以参考课本中的方法进行设计。 对于多道程序系统,要假定系统中具有的各种资源及数量、调度作业时必须考虑到每个作业的资源要求。 在单道批处理系统中,作业一投入运行,它就占有计算机的一切资源直到作业完成为止,因此调度作业时不必考虑它所需要的资源是否得到满足,它所占用的CPU时限等因素。 而在多道批处理系统中,作业首先存放在外存,当系统拥有的资源足够分配给一个作业,就将资源分配给此作业,并将此作业调进内存。当系统资源不足以分配给一个作业时,则等待已经分配资源的作业运行完成后释放资源增加系统资源。 程序及运行结果如下: #include #include #define getb(type) (type *)malloc(sizeof(type)) #define NULL 0 typedef struct JCB{//定义作业控制块JCB char name[10];//作业名 int stime;//开始运行时刻 int rtime;//需要运行时间,即提供服务的时间 char state;//作业状态 JCB *next;//链指针 }JCB; JCB *ready=NULL,*p; int T;//时间量 int ttime;//总周转时间 float trtime;//总的带权周转时间 void sort()//构造链表存放作业 {JCB *fir,*sec; if(ready==NULL){ready=p;} else{ fir=ready->next; if(fir==NULL){sec=ready;} else{ while(fir!=NULL){ sec=fir;fir=fir->next; } } sec->next=p; }} void init()//输入作业参数 {int i,num; printf("输入作业数:"); scanf("%d",&num);//输入作业数 for(i=0;i p=getb(JCB); printf("作业名:"); scanf("%s",p->name); printf("开始运行时刻:"); scanf("%d",&p->stime); printf("需要运行时间:"); scanf("%d",&p->rtime); p->state='w';//每个作业的初始状态总是等待W sort(); } T=0;//时间量 ttime=0;//总周转时间 trtime=0;//总的带权周转时间 getchar();//接收字符 } int length()//链表长 {int i=0; JCB *q; q=ready; while(q!=NULL){i++;q=q->next;} return i; } void destroy(int end)//完成作业 { int i=end; float W; printf("\n作业完成时间:%d",i); printf("\n周转时间:%d",i-(p->stime)); W=(float)(i-(p->stime))/(float)(p->rtime);//带权周转时间=周转时间/提供服务的时间printf("\n带权周转时间:%2.2f",W); } void run()//运行作业 { int start,end; start=T;//初始值为0 end=(p->rtime)+start;//作业完成时间=运行时间+开始运行时刻 ttime+=end-p->stime;//总周转时间=完成时间-开始运行时刻 trtime+=(float)(end-(p->stime))/(float)(p->rtime);//总的带权周转时间 T+=p->rtime; destroy(end); } void main()//主函数 { int len,count; count=0; printf("\t\tcopyright:林庆达计算机03(7)班"); printf("\n\t ******作业调度算法:先来先服务(FCFS)******\n"); init();//初始化数据 len=length();//就绪作业的长度 printf("\npress any key to continue ..."); getchar(); while((len!=0)&&(ready!=NULL)){//若就绪队列不为空 count++; p=ready; printf("\n正在执行的作业是: %s.",p->name); ready=ready->next; p->next=NULL; p->state='r'; run(); printf("\npress any key to continue ..."); getchar(); } printf("\n所有作业全部完成运行!\n"); printf("平均周转时间为:%3.2f\n",(float)ttime/(float)count);//总周转时间/作业数printf("平均带权周转时间为:%3.2f\n",trtime/(float)count);//总的带权周转时间/作业数getchar(); } 运行结果:Copyright:林庆达计算机03(7)班 ******作业调度算法:先来先服务(FCFS)****** 输入作业数:5 输入第1个作业的信息: 作业名:A 开始运行时刻:0 需要运行时间:4 输入第2个作业的信息: 作业名:B 开始运行时刻:1 需要运行时间:3 输入第3个作业的信息: 作业名:C 开始运行时刻:2 需要运行时间:5 输入第4个作业的信息: 作业名:D 开始运行时刻:3 需要运行时间:2 输入第5个作业的信息: 作业名:E 开始运行时刻:4 需要运行时间:4 Press any key to continue…… 正在执行的作业是:A 作业完成时间:4 周转时间:4 带权周转时间:1.00 Press any key to continue…… 正在执行的作业是:B 作业完成时间:7 周转时间:6 带权周转时间:2.00 Press any key to continue…… 正在执行的作业是:C 作业完成时间:12 周转时间:10 带权周转时间:2.00 Press any key to continue…… 正在执行的作业是:D 作业完成时间:14 周转时间:11 带权周转时间:5.50 Press any key to continue…… 正在执行的作业是:E 作业完成时间:18 周转时间:14 带权周转时间:3.50 Press any key to continue…… 所有作业全部完成运行! 平均周转时间为:9.00 平均带权周转时间:2.80 Press any key to continue…… 五、心得体会: 通过实验和课程设计,还进一步锻炼了自己的编程能力,增强了实践和动手能力,使自己的编程能力和逻辑思考能力有了较大的进步。 实验三存储管理 一.实验目的: 存储管理的主要功能之一是合理分配空间,请求页式管理是一种常用的虚拟存储管理技术。本实验的目的是通过请求页式管理中的页面置换算法设计,了解虚拟存储技术的特点,掌握请求页式管理的页面置换算法。 二.实验内容: 1、分区管理的原理:将存储器划分成若干段大小固定的区域,一个区域里只能运行一个程序,程序只能在其自身所在的分区中活动。 2、固定式分区管理的原理:区域大小及起始地址是固定的。一个分区只能存放一个程序。需要设置一个分区说明表来标明内存的使用状态。根据分区说明表来给程序分配相应的区域。由于程序不可能刚刚占有一个分区的大小,这样就会在一个分区之中留下零头,造成了极大的浪费。 3、可变式分区管理的原理:区域的大小及起始地址是可变的,根据程序装入时的大小动态地分配一个区域。保证每个区域之中刚 好放一个程序。这样可以充分地利用存储 空间,提高内存的使用效率。如果一个程 序运行完毕,就要释放出它所占有的分区, 使之变成空闲区。这样就会出现空闲区与 占用区相互交错的情况。这样就需要P表, F表来分别表示内存的占用区状态与空闲 区的状态。 (一)、设计一个固定式分区分 配的存储管理方案,并模拟实 现分区的分配和回收过程。 1.通过随机数产生一个程序指令序列,使 得50%的指令是顺序执行的。25%的指令 是均匀分布在前地址部分,25%的指令是 均匀分布在后地址部分。 2.FIFO算法总是选择在内存驻留时间最长 的一页将其淘汰。FIFO算法认为先调入内 存的页不再被访问的可能性要比其他页大, 因而选择最先调入内存的页换出。实现FIFO 算法需要把各个已分配页面按分配时间顺 序记录在一个数组中,每次淘汰最早进入数组的页。 3、程序代码如下: #include #include #define maxsize 32 #include #define vpf 200 void FIFO(int a[]); int count[maxsize]; int a[vpf]; void main() // 定义主函数 {for(int i=0;i<200;i++) // 用随机数产生页地址流 a[i]=rand()%32; FIFO(a); } void FIFO(int a[]) // FIFO算法 { for(int n=4;n<33;n++) //不同的页面数计算命中率 { int num; int max; int maxpage=0; int dis=0; int i=0; int k=0; int sum=n; int b[maxsize]; for (k=0;k { b[k]=-1; count[k]=0;} for (i=0;i { num=0; for (k=0;k { if(a[i]==b[k]) num++; } if(num==0) //未命中 { dis++; for(k=0;k count[k]++; if(sum==0) //没空白页面时 { max=0; for(k=0;k { if(max {max=count[k]; maxpage=k; } } b[maxpage]=a[i]; count[maxpage]=0; //被替换页面计数器清零 } else {b[n-sum]=a[i]; count[n-sum]=0; //有空白页面时,将所缺页放入空白页面, sum--; // 并将该页面计数器清零 }}} printf("%d",n); printf(" page frames FIFO:%3d",dis); printf(" FIFO:%6.4f\n",1-(float)dis/32); }} 运行结果 (二)、编写并调试一个断式存储管理的地址转换的模拟程序。――― 最佳适应算法 #include #include struct freeM{int Sadd; int length; }; struct busyMEM{int Sadd; int Eadd; char fill; busyMEM *next; }; class Assign{ public: void initMEM(); void pai(); void printList(); void resetfree(); void insert(); void Delete(); private: freeM freeMEM[20]; busyMEM *p; }; void Assign::initMEM() { p=(busyMEM*)malloc(sizeof(busyMEM)); busyMEM *L; L=p; L->fill='O'; L->Eadd=19;