1. 目的和要求
1.1. 实验目的
用高级语言完成一个主存空间的分配和回收程序,以加深对动态分区分配方式及其算法的理解。
1.2. 实验要求
采用连续分配方式之动态分区分配存储管理,使用首次适应算法、循环首次适应算法、最佳适应算法和最坏适应算法4种算法完成设计(任选两种算法)。
(1)**设计一个作业申请队列以及作业完成后的释放顺序,实现主存的分配和回收。采用分区说明表进行。
(2)或在程序运行过程,由用户指定申请与释放。
(3)设计一个空闲区说明表,以保存某时刻主存空间占用情况。把空闲区说明表的变化情况以及各作业的申请、释放情况显示。
2. 实验内容
根据指定的实验课题,完成设计、编码和调试工作,完成实验报告。
3. 实验环境
可以选用Turbo C作为开发环境。也可以选用Windows下的VB,CB或其他可视化环境,利用各种控件较为方便。自主选择实验环境。
4. 代码如下
#include "stdio.h" #include <stdlib.h> #include<string.h> #include <conio.h> #include "iostream.h" #define getjcb(type) (type*)malloc(sizeof(type)) #define getsub(type) (type*)malloc(sizeof(type)) #define NULL 0 int num,num2; //要调度的作业数和要回收的区域数 int m=0; //已分配作业数 int flag; //分配成功标志 int isup,isdown; //回收区域存在上邻和下邻的标志 int is=0; struct jcb{ char name[10]; char state; int ntime; //所需时间 int size; //所需空间大小 int addr; //所分配分区的首地址 struct jcb *link; } *ready =NULL, *p,*q,*as=NULL; //作业队列ready,已分配作业队列as typedef struct jcb JCB; struct subarea{ //分区块 char name[10]; int addr; //分区首地址 int size; //分区大小 char state; struct subarea *link; } *sub=NULL,*r,*s,*cur; //空闲分区队列sub,当前分区指针cur typedef struct subarea SUB; void sort_sub() /*对空闲分区按从小到大排序*/ { SUB *first,*second; int insert=0; if((sub==NULL)||((s->size)<(sub->size))) /*插在队列之首*/ {s->link=sub; sub=s; } else{first=sub; /*寻找适当的位置插入*/ second=first->link; while(second!=NULL) { if((s->size)<(second->size)) { s->link=second; first->link=s; second=NULL; insert=1; } else { first=first->link; second=second->link; } } if(insert==0)first->link=s; /*插在队尾*/ } } void firstsort() //对空闲分区按从小到大排序sort { JCB *first; if(ready==NULL) ready=p; else{ first=ready; while(first->link!=NULL) first=first->link; first->link=p; p->link=NULL; } } void lastsort() //建立对已分配作业队列的排列函数,直接插在队列之尾sort3 { JCB *fir; if(as==NULL) as=q; else{ fir=as; while(fir->link!=NULL) fir=fir->link; fir->link=q; q->link=NULL; } m++; } void input() /* 建立作业控制块函数*/ { int i; printf("\n请输入要调度的总作业数:"); scanf("%d",&num); for(i=0;i<num;i++) { printf("\n作业号No.%d:\n",i); p=getjcb(JCB); printf("\n输入作业名:"); scanf("%s",&p->name); printf("\n输入作业的大小:"); scanf("%d",&p->size); printf("\n输入作业所需运行时间:"); scanf("%d",&p->ntime); p->state='w'; p->link=NULL; firstsort(); /* 调用sort函数*/ } printf("\n 按任一键继续......\n"); getch(); } void input2() /*建立要回收区域的函数*/ { JCB *k; int has; q=getjcb(JCB); printf("\n输入区域名(作业名):"); scanf("%s",&q->name); p=as; while(p!=NULL) { if(strcmp(p->name,q->name)==0) /*在已分配作业队列中寻找*/ { q->addr=p->addr; q->size=p->size; has=1; /*输入作业名存在标志位*/ if(p==as) as=p->link; /*在已分配作业队列中删除该作业*/ else {k=as; while(k->link!=p) k=k->link; k->link=k->link->link; /*删除*/ } printf("输出该作业首地址:%d\n",q->addr); printf("输出该作业大小:%d\n\n",q->size); q->link=NULL; break; } else {p=p->link; has=0;} /*输入作业名不存在标志*/ } if(has==0) {printf("\n输入作业名错误!请重新输入!\n"); input2(); } } void init_sub() /*初始化空闲分区表*/ { r=getsub(SUB); strcpy(r->name,"one"); r->addr=5; r->size=10; r->state='n'; sub=r; s=getsub(SUB); strcpy(s->name,"two"); s->addr=20; s->size=120; s->state='n'; sub->link=s;r=s; s=getsub(SUB); strcpy(s->name,"three"); s->addr=160; s->size=40; s->state='n'; r->link=s;r=s; s=getsub(SUB); strcpy(s->name,"four"); s->addr=220; s->size=10; s->state='n'; r->link=s;r=s; s=getsub(SUB); strcpy(s->name,"five"); s->addr=250; s->size=20; s->state='n'; r->link=s; } void disp() /*空闲分区表的显示函数*/ { printf("\t\t 分区 首地址 长度 状态 \n"); r=sub; while(r!=NULL) { printf("\t\t %s\t\t%d\t\t%d\t\t%c\n",r->name,r->addr,r->size,r->state); r=r->link; } printf("\n"); } void disp2() /*显示已分配内存的作业表函数*/ { printf("\t\t 作业名 首地址 长度 状态 \n"); p=as; while(p!=NULL) { printf("\t\t %s\t\t%d\t\t%d\t\t%c\n",p->name,p->addr,p->size,p->state); p=p->link; } printf("\n\n"); } void perfit(JCB *pr) /*最佳适应作业分区assign*/ { SUB *k; r=sub; while(r!=NULL) { if(((r->size)>(pr->size))&&(r->state=='n')) /*有空闲分区大于作业大小的情况*/ { pr->addr=r->addr; r->size-=pr->size; r->addr+=pr->size; if(r==sub) sub=r->link; /*删除空闲分区*/ else {s=sub; while(s->link!=r) s=s->link; s->link=s->link->link; /*删除空闲分区*/ } flag=1; /*分配成功标志位置1*/ q=pr; lastsort(); /*插入已分配作业队列*/ //重新插入剩余空闲分区,插在合适位置 if(r->size<sub->size) /*插入队首*/ { r->link=sub; sub=r; } else /*插在适当的位置*/ { s=sub; while((s->size)<=(r->size)) s=s->link; k=sub; if(k==s) {r->link=sub->link; sub=r;} /*插在队首的后一个位置*/ else /*第二个以后的位置*/ { while(k->link!=s) k=k->link; r->link=s; k->link=r; } } printf("作业%s的分区为[%s],首地址为%d.\n",p->name,r->name,pr->addr); break; } else if(((r->size)==(pr->size))&&(r->state=='n')) /*有空闲分区等于作业大小的情况*/ { pr->addr=r->addr; flag=1; /*分配成功标志位置1*/ q=pr; lastsort(); /*插入已分配作业队列*/ s=sub; /*空闲分区已完成分配,应删除*/ while(s->link!=r) s=s->link; s->link=s->link->link; /*删除空闲分区*/ printf("作业%s的分区为[%s],首地址为%d.\n",p->name,r->name,pr->addr); break; } else {r=r->link; flag=0;} } if(flag==0) /*作业过大的情况*/ { printf("作业%s长度过大,内存不足,分区分配出错!\n",p->name); is=1; } } void firstfit(JCB *pr) /*首次适应作业分区*/ { SUB *k; r=sub; /*从空闲表头开始寻找*/ while(r!=NULL) { if(((r->size)>(pr->size))&&(r->state=='n')) /*有空闲分区大于作业大小的情况*/ { pr->addr=r->addr; r->size-=pr->size; r->addr+=pr->size; flag=1; /*分配成功标志位置1*/ q=pr; q->state='r'; lastsort(); /*插入已分配作业队列*/ printf("作业%s的分区为[%s],首地址为%d.\n",p->name,r->name,pr->addr); break; } else if(((r->size)==(pr->size))&&(r->state=='n')) /*有空闲分区等于作业大小的情况*/ { pr->addr=r->addr; flag=1; /*分配成功标志位置1*/ q=pr; lastsort(); /*插入已分配作业队列*/ s=sub; /*空闲分区已完成分配,应删除*/ while(s->link!=r) s=s->link; s->link=s->link->link; /*删除空闲分区*/ printf("作业%s的分区为[%s],首地址为%d.\n",p->name,r->name,pr->addr); break; } else {r=r->link; flag=0;} } if(flag==0) /*作业过大的情况*/ { printf("作业%s长度过大,内存不足,分区分配出错!\n",p->name); is=1; } } void cyclefit(JCB *pr) /*循环首次适应作业分区*/ { SUB *k; r=cur; /*从当前指针开始寻找*/ while(r!=NULL) { if(((r->size)>(pr->size))&&(r->state=='n')) /*有空闲分区大于作业大小的情况*/ { pr->addr=r->addr; r->size-=pr->size; r->addr+=pr->size; flag=1; /*分配成功标志位置1*/ cur=r; /*更新当前指针*/ q=pr; q->state='r'; lastsort(); /*插入已分配作业队列*/ printf("作业%s的分区为[%s],首地址为%d.\n",p->name,r->name,pr->addr); break; } else if(((r->size)==(pr->size))&&(r->state=='n')) /*有空闲分区等于作业大小的情况*/ { pr->addr=r->addr; flag=1; /*分配成功标志位置1*/ cur=r; q=pr; lastsort(); /*插入已分配作业队列*/ s=sub; /*空闲分区已完成分配,应删除*/ while(s->link!=r) s=s->link; s->link=s->link->link; /*删除空闲分区*/ printf("作业%s的分区为[%s],首地址为%d.\n",p->name,r->name,pr->addr); break; } else { r=r->link; if(r==NULL) /*当前指针为空时,重新由空闲区队列之首寻找*/ { k=cur; /*作保存当前指针用*/ cur=sub; r=cur; } if(k==r) /*又回到开始的指针时,确定为没有空间满足要求*/ { cur=k; break; } flag=0; /*分配不成功标志*/ } } if(flag==0) /*作业过大的情况*/ { printf("作业%s长度过大,内存不足,分区分配出错!\n",p->name); is=1; } } void less_to_more() /*把分区按大小从小到大排序*/ { r=sub; sub=NULL; while(r!=NULL) { s=r; r=s->link; s->link=NULL; sort_sub(); /*调用排序函数*/ } } void reclperfit(JCB *pr) /*最佳适应回收区域,按分区大小排列*/ { SUB *k; r=sub; while(r!=NULL) { if(r->addr==((pr->addr)+(pr->size))) /*回收区域有下邻*/ { pr->size+=r->size; s=sub; isdown=1; /*下邻标志位置1*/ while(s!=NULL) { if(((s->addr)+(s->size))==(pr->addr)) /*有下邻又有上邻*/ { s->size+=pr->size; k=sub; while(k->link!=r) k=k->link; k->link=k->link->link; isup=1; /*上邻标志位置1*/ break; } else {s=s->link; isup=0;} /*上邻标志位置0*/ } if(isup==0) /*有下邻无上邻*/ { r->addr=pr->addr; r->size=pr->size; } break; } else {r=r->link; isdown=0;} /*下邻标志位置0*/ } if(isdown==0) /*区域无下邻*/ { s=sub; while(s!=NULL) { if(((s->addr)+(s->size))==(pr->addr)) /*无下邻但有上邻*/ { s->size+=pr->size; isup=1; /*上邻标志位置1*/ break; } else { s=s->link; isup=0;} /*上邻标志位置0*/ } if(isup==0) /*无下邻且无上邻*/ { k=getsub(SUB); /*重新生成一个新的分区结点*/ strcpy(k->name,pr->name); k->addr=pr->addr; k->size=pr->size; k->state='n'; r=sub; while(r!=NULL) { if((r->size)>(k->size)) /*按分区大小排列,回收区域插在合适的位置*/ { if(r==sub) /*第一个空闲分区大于回收区域的情况*/ { k->link=r; sub->link=k; } else { s=sub; while(s->link!=r) s=s->link; k->link=r; s->link=k; } break; } else r=r->link; } if(r==NULL) /*所有空闲分区都大于回收区域的情况*/ { s=sub; while(s->link!=NULL) s=s->link; s->link=k; k->link=NULL; } } } printf("\n区域%s己回收.",pr->name); } void reclfirst(JCB *pr) /*首次适应与循环首次适应区域回收*/ { SUB *k; r=sub; while(r!=NULL) { if(r->addr==((pr->addr)+(pr->size))) /*回收区域有下邻*/ { pr->size+=r->size; s=sub; isdown=1; /*下邻标志位置1*/ while(s!=NULL) { if(((s->addr)+(s->size))==(pr->addr)) /*有下邻又有上邻*/ { s->size+=pr->size; k=sub; while(k->link!=r) k=k->link; k->link=k->link->link; isup=1; /*上邻标志位置1*/ break; } else {s=s->link; isup=0;} /*上邻标志位置0*/ } if(isup==0) /*有下邻无上邻*/ { r->addr=pr->addr; r->size=pr->size; } break; } else {r=r->link; isdown=0;} /*下邻标志位置0*/ } if(isdown==0) /*区域无下邻*/ { s=sub; while(s!=NULL) { if(((s->addr)+(s->size))==(pr->addr)) /*无下邻但有上邻*/ { s->size+=pr->size; isup=1; /*上邻标志位置1*/ break; } else { s=s->link; isup=0;} /*上邻标志位置0*/ } if(isup==0) /*无下邻且无上邻*/ { k=getsub(SUB); /*重新生成一个新的分区结点*/ strcpy(k->name,pr->name); k->addr=pr->addr; k->size=pr->size; k->state='n'; r=sub; while(r!=NULL) { if((r->addr)>(k->addr)) /*按分区首地址排列,回收区域插在合适的位置*/ { if(r==sub) /*第一个空闲分区首址大于回收区域的情况*/ { k->link=r; sub->link=k; } else { s=sub; while(s->link!=r) s=s->link; k->link=r; s->link=k; } break; } else r=r->link; } if(r==NULL) /*所有空闲分区的首址都大于回收区域首址的情况*/ { s=sub; while(s->link!=NULL) s=s->link; s->link=k; k->link=NULL; } } } printf("\n区域%s己回收.",pr->name); } void print() //初始化界面 {printf("\n\n\n\n"); printf("\t\t**************************************\n"); printf("\t\t\t主存空间的分配与回收演示\n"); printf("\t\t**************************************\n\n\n"); printf("\t\t\t\t张文雅\n"); printf("\t\t\t\t华南师范大学增城学院\n"); printf("\t\t\t\t网络工程\n"); printf("\t\t\t\t201306114136\n"); printf("\t\t\t\t2015年6月\n"); printf("\n\n\n"); printf("\t\t\t按任意键进入演示"); getch(); system("cls"); } void init() { printf("\n\n\n\n\t\t\t 1. 显示空闲分区 \n"); printf("\t\t\t 2. 分配作业 \n"); printf("\t\t\t 3. 回收作业 \n"); printf("\t\t\t 0. 返回菜单 \n"); printf("\t\t\t请选择你要的操作:"); } firstfitf() //首次适应算法 { init(); switch(getchar()) { case '1': system("cls"); disp(); getch(); system("cls"); firstfitf(); break; case '2': system("cls"); system("cls"); input(); printf("\n"); while(num!=0) { p=ready; ready=p->link; p->link=NULL; firstfit(p); num--; } getch(); printf("\n\t\t 完成分配后的空闲分区表 \n"); disp(); printf("\n\t\t 已分配作业表 \n"); disp2(); if(is==0) printf("\n 全部作业已经被分配内存."); else printf("\n 作业没有全部被分配内存.\n"); getch(); system("cls"); firstfitf(); break; case '3': system("cls"); disp2(); printf("\n\n按任意键进行区域回收."); printf("\n"); while(as!=NULL) {getch(); input2(); printf("按任意键继续..."); getch(); printf("\n"); reclfirst(q); getch(); printf("\n\t\t 回收后的空闲分区表 \n"); disp(); printf("\n\t\t 已分配作业表 \n"); disp2(); printf("\n继续回收...(Enter)"); } printf("\n所有已分配作业已完成!"); printf("\nPress any key to return..."); getch(); system("cls"); firstfitf(); break; case '0': break; default: getch(); system("cls"); firstfitf(); break; } } cyclefirstf() //循环首次适应算法 { init(); switch(getchar()) { case '1': system("cls"); disp(); getch(); system("cls"); cyclefirstf(); break; case '2': system("cls"); cur=sub; input(); printf("\n"); while(num!=0) { p=ready; ready=p->link; p->link=NULL; cyclefit(p); num--; } getch(); printf("\n\t\t 完成分配后的空闲分区表 \n"); disp(); printf("\n\t\t 已分配作业表 \n"); disp2(); if(is==0) printf("\n 全部作业已经被分配内存."); else printf("\n 作业没有全部被分配内存.\n"); getch(); system("cls"); cyclefirstf(); break; case '3': system("cls"); disp2(); printf("\n\n按任意键进行区域回收."); while(as!=NULL) {getch(); printf("\n"); input2(); printf("按任意键继续..."); getch(); printf("\n"); reclfirst(q); getch(); printf("\n\t\t 回收后的空闲分区表 \n"); disp(); printf("\n\t\t 已分配作业表 \n"); disp2(); printf("\n继续回收...(Enter)"); } printf("\n所有已分配作业已完成!"); getch(); system("cls"); cyclefirstf(); break; case '0': break; default: getch(); system("cls"); cyclefirstf(); break; } } perfitf() //最佳适应算法 { init(); switch(getchar()) { case '1': system("cls"); less_to_more(); disp(); getch(); system("cls"); perfitf(); break; case '2': system("cls"); cur=sub; input(); printf("\n"); while(num!=0) { p=ready; ready=p->link; p->link=NULL; less_to_more(); /*重新排列分区,按从小到大排列*/ perfit(p); num--; } getch(); printf("\n\n\t\t 完成分配后分区表(分区按由小到达排列) \n"); disp(); printf("\n\t\t 已分配作业表 \n"); disp2(); if(is==0) printf("\n 全部作业已经被分配内存."); else printf("\n 作业没有全部被分配内存.\n"); getch(); system("cls"); perfitf(); break; case '3': system("cls"); disp2(); printf("\n\n按任意键进行区域回收."); while(as!=NULL) {getch(); printf("\n"); input2(); printf("按任意键继续..."); getch(); printf("\n"); reclperfit(q); getch(); printf("\n\t\t 回收后的空闲分区表 \n"); disp(); printf("\n\t\t 已分配作业表 \n"); disp2(); printf("\n继续回收...(Enter)"); } printf("\n所有已分配作业已完成!"); getch(); system("cls"); perfitf(); break; case '0': break; default: getch(); system("cls"); perfitf(); break; } } void menu() /*菜单函数*/ { int i; printf("\n\n\n\t\t**************************************\n"); printf("\t\t\t主存空间的分配与回收演示\n"); printf("\t\t**************************************\n");; printf("\t\t\t\n\n"); printf("\t\t\t 1. 首次适应算法 \n"); printf("\t\t\t 2. 循环首次适应算法 \n"); printf("\t\t\t 3. 最佳适应算法 \n"); printf("\t\t\t 0. 退出 \n"); printf("\t\t\t请选择你要的操作:"); switch(getchar()) { case '1': system("cls"); firstfitf(); getch(); system("cls"); menu(); break; case '2': system("cls"); cyclefirstf(); getch(); system("cls"); menu(); break; case '3': system("cls"); perfitf(); getch(); system("cls"); menu(); break; case '0': break; default: getch(); system("cls"); menu(); break; } } void main() /*主函数*/ { init_sub(); print(); menu(); }
5.运行结果:
六、实验总结
用c语言编写了一个主存空间的分配和回收程序,加深了我对动态分区分配方式及其算法的理解。期间遇到了很多的困难,通过看课本,参考了网上的资料,也请教了同学,最终编写出来了。