实验五-动态分区存储管理
动态分区管理实验报告

实验五动态分区管理模拟实验报告关键问题:写一动态分区管理程序,使其内存分配采用最优适应分配算法。
设计思路:在空闲分区链中找最适合的空闲块,使内存碎片尽量的减少!根据最佳适应算法原理,在内存分配函数ffallocation()中,增加记录适合空白块的标记sp,然后拿当前空白块fp减去后jl的后的大小和它后面的另一空白块sp减去jl的大小相比较。
如果前者大于后者,且后者的空白区大于jl的大小,则当前空白块为sp,否则继续往后比较,直到空闲分区链末尾!则当前空白块为最适合的空白块!然后就把当前空白块分配给作业。
其他部分的代码与实例相同!实现的关键代码://------------------------------------------------------------------- //有两个链:空白块链及作业链.空白块链描述空白块,链首指针freep,初始为一大块空白块.//作业链按从高址到低址的顺序链接,链首指针jobp//为作业jn分配jl大小内存,起始地址为javoid ffallocation(int jl,char jn[10],int* ja){mat* jp=NULL;//作业链当前节点mat* jp2=NULL;//新的作业节点mat* jp1=NULL;//freearea* fp=NULL;//当前空白块//修改部分 freearea* sp;//记录适合的空白块int i;*ja=-1;if (totalfree<jl) //剩余空间大小不能满足作业要求return;*ja=0;fp=freep;//取空白块链首块,将顺着链寻找第一块满足作业要求的块。
sp=freep;while (fp!=NULL){if (fp->freesize<jl){fp=fp->next;//当前空白块大小不满足要求sp=sp->next;}else //将当前空白块分配给作业{/*当当前空白块fp与它的下一块空白块sp相比较,如果它减去jl后大于下一空白块sp减去jl,且下一空白块sp大于等于jl,则当前空白块为sp;否则sp继续往后查找,直到空闲块查找完毕,然后当前空闲块为所要查找的适合空闲块!*/while(sp!=NULL){if((fp->freesize-jl>sp->freesize-jl)&(sp->freesize>=jl)){fp=sp;}else{sp=sp->next;}}// jobnumber++;totalfree=totalfree-jl;jp2=new mat;//申请一块作业节点空间//在节点上登记为该作业分配的内存空间// for (i=0;i<10;i++) (jp2->jobname)[i]=' ';i=-1;while(jn[++i])(jp2->jobname)[i]=jn[i];(jp2->jobname)[i]='\0';jp2->joblength=jl;jp2->jobaddress=fp->freeaddress;//登记该作业的起始地址*ja=jp2->jobaddress;//将节点jp2插入作业链jobp,按高址到低址的顺序。
存储管理实验报告总结(3篇)

第1篇一、实验背景存储管理是操作系统的重要组成部分,负责对计算机的存储资源进行合理分配、有效利用和保护。
为了加深对存储管理原理和方法的理解,我们进行了存储管理实验,通过编写和调试模拟程序,对存储管理技术进行了深入学习和实践。
二、实验目的1. 理解存储管理的概念、原理和方法。
2. 掌握不同存储管理技术的实现过程。
3. 分析存储管理技术的优缺点,为实际应用提供参考。
三、实验内容1. 可变分区存储管理实验实验目的:了解可变分区存储管理的原理和实现方法。
实验内容:(1)编写程序实现内存空间的分配和回收。
(2)采用最优适应算法、首次适应算法、下次适应算法等,模拟内存分配过程。
(3)分析不同分配算法的性能。
实验结果:通过实验,我们了解了可变分区存储管理的原理和实现方法,并分析了不同分配算法的性能。
2. 分页存储管理实验实验目的:掌握分页存储管理的基本概念和实现方法。
实验内容:(1)编写程序实现内存空间的分配和回收。
(2)采用页式存储管理技术,模拟内存分配过程。
(3)分析页面置换算法的性能,如LRU、FIFO等。
实验结果:通过实验,我们掌握了分页存储管理的基本概念和实现方法,并分析了页面置换算法的性能。
3. 虚拟页式存储管理实验实验目的:了解虚拟页式存储管理的原理和实现方法。
实验内容:(1)编写程序实现虚拟内存的分配和回收。
(2)采用工作集算法、抖动预防等技术,模拟虚拟内存的访问和页面置换过程。
(3)分析虚拟页式存储管理技术的优缺点。
实验结果:通过实验,我们了解了虚拟页式存储管理的原理和实现方法,并分析了其优缺点。
四、实验总结1. 通过本次实验,我们对存储管理技术有了更深入的理解,掌握了不同存储管理技术的实现方法。
2. 实验过程中,我们学会了编写模拟程序,通过程序模拟存储管理过程,验证了存储管理技术的性能。
3. 实验结果分析表明,不同存储管理技术具有不同的优缺点,在实际应用中应根据具体需求选择合适的存储管理技术。
分区存储管理模拟实验报告

分区存储管理模拟实验报告分区存储管理模拟实验报告1.实验目的了解动态分区存储管理方式中的数据结构和分配算法,加深对动态分区存储管理方式及其实现技术的理解。
2. 实验内容▪用C语言或Pascal语言分别实现采用首次适应算法和最佳适应算法的动态分区分配过程Allocate()和回收过程Free()。
其中,空闲分区采用空闲分区链来组织,内存分配时,优先使用空闲区低地址部分的空间。
▪假设初始状态,可用内存空间为640KB,作业请求序列如下(也可以编程从键盘输入,R 表示请求,F表示释放):✧作业1请求130 KB。
✧作业2请求60 KB。
✧作业3请求100 KB。
到第一个足以满足要球的空闲块就停止查找,并把它分配出去;如果该空闲空间与所需空间大小一样,则从空闲表中取消该项;如果还有剩余,则余下的部分仍留在空闲表中,但应修改分区大小和分区始址。
最佳适应算法:当要分配内存空间时,就查找空闲表中满足要求的空闲块,并使得剩余块是最小的。
然后把它分配出去,若大小恰好合适,则直按分配;若有剩余块,则仍保留该余下的空闲分区,并修改分区大小的起始地址。
内存回收:将释放作业所在内存块的状态改为空闲状态,删除其作业名,设置为空。
并判断该空闲块是否与其他空闲块相连,若释放的内存空间与空闲块相连时,则合并为同一个空闲块,同时修改分区大小及起始地址。
typedef struct freearea{}ElemType;定义一个空闲区说明表结构,每申请一个作业,改作业便具有此结构体typedef struct DuLNode{}DuLNode,*DuLinkList;定义一个双向链表Status Initblock(){}开创带头结点的内存空间链表,通过双向链表把申请的作业链接起来,作业的插入和删除,和链表中节点的插入和删除类似。
双向链表如图1所示Status First_fit(int ID,int request){}传入作业名及申请量采用首次适应算法实现动态内存分区分配的模拟,初始态640KB,只是一个虚态,每申请成功一个作业,便相应的640KB做相应的减少,同过双向链表模拟主存的分配情况。
操作系统-存储管理动态分区分配和恢复算法(带源代码).doc

操作系统-存储管理动态分区分配和恢复算法(带源代码)。
存储管理动态分区分配和恢复算法课程名称:计算机操作系统课程: 信函1501-计算机操作系统类别:信1501:陈丽实验日期:5月XXXX,5月XXXX,5月20日分数: 教师签名:首先,实验目的分区管理是一种广泛使用的存储管理技术。
本实验要求用结构化的高级语言构造分区描述符,编写动态分区分配算法和恢复算法仿真程序,并讨论不同分配算法的特点。
二、实验要求1.写作:首次拟合算法2.写作:最佳拟合算法3.写作:自由区域恢复算法三、实验过程(一)主要程序1.定义分区描述符节点,包括3个元素:(1)adr——分区标题地址(2)大小——分区大小(3)next——指向下一个分区的指针2.定义3个指向节点结构的指针变量:(1)head1——空闲区队列头指针(2)back1——指针指向空闲区节点结构(3)assign——指针指向应用的内存分区节点结构3.定义一个成形变量:免费——用户申请存储区域大小(由用户键入)(2)流程1.定义检查过程以检查指定发布块(由用户键入)的合法性2.定义分配1流程并实施首次拟合算法3.定义分配2过程并实现最佳匹配算法。
4.定义接受1 1流程,并实施首次拟合算法的恢复算法。
5.定义接受2 2过程,实现最佳匹配算法的恢复算法。
6.定义打印过程,打印空闲区队列(3)执行程序首先应用于整个空闲区,第一个地址为0,大小为32767;然后,系统会提示用户使用哪种分配算法,然后是分配还是回收。
分配需要应用程序区域的大小,回收需要释放区域的第一个地址和大小。
CPP # include # include # include # include using命名空间标准;#定义MAX_SIZE 32767typedef结构节点{ int idint adrint大小;结构节点*下一步;}节点;节点*head1,*head2,*back1,*back2,*分配;int请求;内部检查(内部添加、内部大小、字符c){节点*p,*头;int check=1;if(add 0 | | siz next;同时((p!=NULL)检查)如果(((添加:“);sca nf(“% d”,r);if(choosed==' F ' | | choosed==' F ')assign=assign ment 1(num,r);else assign=assignment2(num,r);如果(assign-adr==-1) {printf('未能分配内存!\ n ');Elseprintf('分配成功!分配的内存的第一个地址是:%d\n ',assign-ADR);休息;事例2: printf('输入释放内存的第一个地址:);scanf(“% d”,添加);Printf('输入释放的内存量:);scanf(“% d”,r);Printf('输入释放的内存数量:);scanf(“% d”,rd);if(检查(添加,r,选择)){ if(选择=='f' ||选择=='F') acceptment1(添加,r,rd);else acceptment2(add,r,rd);}休息;case 3:print(已选择);休息;判例4: menu();休息;}}} }}void main()//main函数{ init();菜单();}四.实验结果第五,实验总结通过本实验,我实践了存储管理的动态分区分配和恢复算法,对操作系统中的动态可变分区存储管理有了更深的了解。
动态内存分配实验报告

Free[free_p].len=length;
free_p++;
//
sort(Free,Free+free_p,cmp);
for(j=0;j<free_p;j++)
{
1].address)
if(j + 1 < free_p&&Free[j].address+Free[j].len==Free[j +
if(used[i].run_id==id) {
int add=used[i].address; int length=used[i].len; used_p--; for(j=i;j<used_p;j++) {
used[j]=used[j+1]; }
Free[free_p].address=add;
Free[i].address+=len; Free[i].len-=len; } else { free_p--;
for(j=i;j<free_p;j++) {
Free[j]=Free[j+1]; } } break; } }
} void reclaim(int id) {
int i,j,k; for(i=0;i<used_p;i++) {
{ Free[j].len+=Free[j + 1].len; free_p--; for(k =j + 1; k < free_p;k++) { Free[k]=Free[k+1]; }
}
}
} }
} void show() {
实验五 存储管理(实验报告格式)

实验五:存储管理一、实验目的(1)熟悉内存空闲分区的分配方式;(2)理解动态分区存储管理方式;(3)掌握动态分区的分配与回收的过程。
二、实验环境微型计算机,Ubuntu Linux10.04 ,gedit,gcc三、实验内容根据流程图和参考程序,完成模拟内存分配和回收过程。
内存空间大小为100,进程数为5,每个进程所需空间为随机产生,大小为1~20,编制程序,首先对5个进程进行内存分配,然后回收指定的进程空间,并进行适当的空闲分区合并操作,要求每次操作结束后都能显示当前的内存分配情况。
四、实验结果截图一截图二截图三五、源代码#include<stdio.h>#include<malloc.h>typedef struct MEMORY_BLOCK{int name; //进程名int address; //起始地址int length; //长度int flag; //标志,表示该块是否被分配。
struct MEMORY_BLOCK *next; //指向下一个进程}MEMORY_BLOCK;#define NUM 5#define LEN sizeof(MEMORY_BLOCK)void allocation(MEMORY_BLOCK *Header,int name,int length_p){ MEMORY_BLOCK *temp,*t,*tt;int minsize=2; //不可切割的分区阈值while(t!=0){if(t->length>length_p&&t->flag==0) break;t=t->next;}if(t->length-length_p>minsize){ //分割temp=(MEMORY_BLOCK*)malloc(LEN);temp->name=-1;temp->flag=0;temp->length=t->length-length_p;temp->address=t->address+length_p;t->name=name;t->flag=1;t->length=length_p;temp->next=t->next;t->next=temp;}else{ //直接分配t->name=name;t->flag=1;}}void reclaim(int processname, MEMORY_BLOCK *Header){ MEMORY_BLOCK *temp,*t,*tt;temp=t;while(t->name!=processname){temp=t;t=t->next;}if(t->next!=NULL){ //t非尾结点if(temp->flag==0&&t->next->flag==0){ //左右为空temp->name=-1;temp->length=temp->length+t->length+t->next->length;tt=t->next;temp->next=tt->next;}else if(temp->flag==0){ //左为空temp->name=-1;temp->length=temp->length+t->length;temp->next=t->next;}else if(t->next->flag==0){ //右为空t->name=-1;t->length=t->length+t->next->length;t->flag=0;tt=t->next;t->next=tt->next;}else{ //左右不为空t->name=-1;t->flag=0;}else{ //t是尾结点if(temp->flag==0){ //左为空temp->name=-1;temp->length=temp->length+t->length;temp=t->next;}else{ //左不为空t->name=-1;t->flag=0;}}}void main(){ //主函数int length_p,i,processname;MEMORY_BLOCK *Header,*t;Header=(MEMORY_BLOCK*)malloc(LEN); //初始化存储空间Header->name=-1;Header->address=0;Header->length=100;Header->flag=0;Header->next=NULL;srand((int)time(0));for(i=1;i<=NUM+1;i++){length_p=rand()%20+1; //随机产生进程所需存储空间,至少为1allocation(Header,i,length_p);}printf("当前内存分配情况:\n");t=Header;while(t!=0){printf("process_name:%d,address:%d,length:%d,flag:%d\n",t->name,t->address,t->length,t->flag);t=t->next;}printf("请输入回收的进程号(输入0结束):\n");scanf("%d",&processname);while(processname!=0){printf("回收process name %d\n",processname);reclaim(processname,Header);printf("当前内存分配情况:\n");t=Header;while(t!=0){printf("process_name:%d,address:%d,length=%d,flag=%d\n", t->name, t->address, t->length,t->flag);t=t->next;}。
动态分区算法实验报告

动态分区算法实验报告动态分区算法实验报告一、引言计算机操作系统是现代计算机系统中的核心组成部分,它负责管理计算机硬件资源,并提供各种服务。
内存管理是操作系统的重要功能之一,它负责管理计算机的内存资源,为进程提供运行环境。
在内存管理中,动态分区算法是一种常用的内存分配策略。
本实验旨在通过实践,深入了解动态分区算法的原理和实现。
二、实验目的1. 了解动态分区算法的基本原理和实现方式;2. 掌握动态分区算法的实验环境搭建和使用方法;3. 分析动态分区算法的优缺点,并比较不同算法的性能差异。
三、实验环境本实验使用C语言编程实现,实验环境如下:1. 操作系统:Windows 10;2. 开发工具:Visual Studio 2019;3. 编程语言:C语言。
四、实验过程1. 实验准备在开始实验之前,我们首先需要了解动态分区算法的基本原理。
动态分区算法根据进程的内存需求,将内存划分为若干个不同大小的分区,并按照进程的请求进行分配和释放。
常用的动态分区算法有首次适应算法、最佳适应算法和最坏适应算法等。
2. 实验设计本实验选择实现首次适应算法,并设计以下几个函数:- 初始化内存空间:初始化一块指定大小的内存空间,将其划分为一个个的分区,并设置分区的状态;- 分配内存:根据进程的内存需求,在内存空间中找到合适的分区进行分配,并更新分区的状态;- 释放内存:将已分配的内存空间进行释放,并更新分区的状态;- 显示内存状态:打印当前内存空间的分区状态。
3. 实验实现根据上述设计,我们使用C语言实现了动态分区算法的相关函数。
通过调用这些函数,我们可以模拟动态分区算法的运行过程,并观察分区的分配和释放情况。
4. 实验结果经过实验,我们得到了以下结果:- 动态分区算法可以有效地管理内存资源,根据进程的需求进行灵活的内存分配;- 首次适应算法在内存分配效率和速度方面表现良好,但可能会导致内存碎片的产生;- 释放内存时,及时合并相邻的空闲分区可以减少内存碎片的数量。
动态分区存储管理

《操作系统》课程实验报告实验名称:动态分区存储管理姓名:学号:地点:指导老师:专业班级:一、实验目的:1、熟悉并掌握动态分区分配的算法。
2、熟悉并掌握动态分区中分区回收的各种情况,并能够实现分区合并。
二、实验内容:用高级语言模拟实现动态分区存储管理,要求:1、分区分配算法至少实现首次适应算法、最佳适应算法和最坏适应算法中的至少一种。
熟悉并掌握各种算法的空闲区组织方式。
2、分区的初始化——可以由用户输入初始分区的大小。
(初始化后只有一个空闲分区,起始地址为0,大小是用户输入的大小)3、分区的动态分配过程:由用户输入作业号和作业的大小,实现分区过程。
4、分区的回收:用户输入作业号,实现分区回收,同时,分区的合并要体现出来。
(注意:不存在的作业号要给出错误提示!)5、分区的显示:任何时刻,可以查看当前内存的情况(起始地址是什么,大小多大的分区时空闲的,或者占用的,能够显示出来)6、要求考虑:(1)内存空间不足的情况,要有相应的显示;(2)作业不能同名,但是删除后可以再用这个名字;(3)作业空间回收是输入作业名,回收相应的空间,如果这个作业名不存在,也要有相应的提示。
三、实验代码#include<stdio.h>#include<stdlib.h>#define SIZE 800 // 内存初始大小#define MINSIZE 5 // 碎片最小值enum STATE { Free, Busy };struct subAreaNode {int addr; // 起始地址int size; // 分区大小int taskId; // 作业号STATE state; // 分区状态subAreaNode *pre; // 分区前向指针subAreaNode *nxt; // 分区后向指针}subHead;// 初始化空闲分区链void intSubArea(){// 分配初始分区内存subAreaNode *fir = (subAreaNode *)malloc(sizeof(subAreaNode)); // 给首个分区赋值fir->addr = 0;fir->size = SIZE;fir->state = Free;fir->taskId = -1;fir->pre = &subHead;fir->nxt = NULL;// 初始化分区头部信息subHead.pre = NULL;subHead.nxt = fir;}// 首次适应算法int firstFit(int taskId, int size){subAreaNode *p = subHead.nxt;while(p != NULL){if(p->state == Free && p->size >= size) {// 找到要分配的空闲分区if(p->size - size <= MINSIZE) {// 整块分配p->state = Busy;p->taskId = taskId;} else {// 分配大小为size的区间subAreaNode *node = (subAreaNode*)malloc(sizeof(subAreaNode));node->addr = p->addr + size;node->size = p->size - size;node->state = Free;node->taskId = -1;// 修改分区链节点指针node->pre = p;node->nxt = p->nxt;if(p->nxt != NULL) {p->nxt->pre = node;}p->nxt = node;// 分配空闲区间p->size = size;p->state = Busy;p->taskId = taskId;}printf("内存分配成功!\n");return 1;}p = p->nxt;}printf("找不到合适的内存分区,分配失败...\n");return 0;}// 最佳适应算法int bestFit(int taskId, int size){subAreaNode *tar = NULL;int tarSize = SIZE + 1;subAreaNode *p = subHead.nxt;while(p != NULL){// 寻找最佳空闲区间if(p->state == Free && p->size >= size && p->size < tarSize) { tar = p;tarSize = p->size;}p = p->nxt;}if(tar != NULL) {// 找到要分配的空闲分区if(tar->size - size <= MINSIZE) {// 整块分配tar->state = Busy;tar->taskId = taskId;} else {// 分配大小为size的区间subAreaNode *node = (subAreaNode*)malloc(sizeof(subAreaNode));node->addr = tar->addr + size;node->size = tar->size - size;node->state = Free;node->taskId = -1;// 修改分区链节点指针node->pre = tar;node->nxt = tar->nxt;if(tar->nxt != NULL) {tar->nxt->pre = node;}tar->nxt = node;// 分配空闲区间tar->size = size;tar->state = Busy;tar->taskId = taskId;}printf("内存分配成功!\n");return 1;} else {// 找不到合适的空闲分区printf("找不到合适的内存分区,分配失败...\n");return 0;}}// 回收内存int freeSubArea(int taskId){int flag = 0;subAreaNode *p = subHead.nxt, *pp;while(p != NULL){if(p->state == Busy && p->taskId == taskId) {flag = 1;if((p->pre != &subHead && p->pre->state == Free) && (p->nxt != NULL && p->nxt->state == Free)) { // 情况1:合并上下两个分区// 先合并上区间pp = p;p = p->pre;p->size += pp->size;p->nxt = pp->nxt;pp->nxt->pre = p;free(pp);// 后合并下区间pp = p->nxt;p->size += pp->size;p->nxt = pp->nxt;if(pp->nxt != NULL) {pp->nxt->pre = p;}free(pp);} else if((p->pre == &subHead || p->pre->state == Busy) && (p->nxt != NULL && p->nxt->state == Free)) {// 情况2:只合并下面的分区pp = p->nxt;p->size += pp->size;p->state = Free;p->taskId = -1;p->nxt = pp->nxt;if(pp->nxt != NULL) {pp->nxt->pre = p;}free(pp);} else if((p->pre != &subHead && p->pre->state == Free) && (p->nxt == NULL || p->nxt->state == Busy)) {// 情况3:只合并上面的分区pp = p;p = p->pre;p->size += pp->size;p->nxt = pp->nxt;if(pp->nxt != NULL) {pp->nxt->pre = p;}free(pp);} else {// 情况4:上下分区均不用合并p->state = Free;p->taskId = -1;}}p = p->nxt;}if(flag == 1) {// 回收成功printf("内存分区回收成功...\n");return 1;} else {// 找不到目标作业,回收失败printf("找不到目标作业,内存分区回收失败...\n");return 0;}}// 显示空闲分区链情况void showSubArea(){printf(" 当前的内存分配情况如下: \n");printf("\n");printf("起始地址\t空间大小\t工作状态\t作业号 \n");subAreaNode *p = subHead.nxt;while(p != NULL){printf("\n");printf("%d k\t ", p->addr);printf("%d k\t ", p->size);printf("%s \t ", p->state == Free ? "Free" : "Busy"); if(p->taskId > 0) {printf("%d ", p->taskId);} else {printf(" ");}printf("\n");p = p->nxt;}}int main(){int option, ope, taskId, size;// 初始化空闲分区链intSubArea();// 选择分配算法while(1){printf("请选择要模拟的分配算法: 0 表示首次适应算法,1 表示最佳适应算法\n");scanf("%d", &option);if(option == 0) {printf("你选择了首次适应算法,下面进行算法的模拟\n");break;} else if(option == 1) {printf("你选择了最佳适应算法,下面进行算法的模拟\n");break;} else {printf("错误:请输入 0/1\n\n");}}// 模拟动态分区分配算法while(1){printf("\n");printf("*********************************************\n"); printf(" 1: 分配内存 2: 回收内存 0: 退出 \n");printf("*********************************************\n"); scanf("%d", &ope);if(ope == 0) break;if(ope == 1) {// 模拟分配内存printf("请输入作业号: ");scanf("%d", &taskId);printf("请输入需要分配的内存大小(KB): ");scanf("%d", &size);if(size <= 0) {printf("错误:分配内存大小必须为正值\n");continue;}// 调用分配算法if(option == 0) {firstFit(taskId, size);} else {bestFit(taskId, size);}// 显示空闲分区链情况showSubArea();} else if(ope == 2) {// 模拟回收内存printf("请输入要回收的作业号: ");scanf("%d", &taskId);freeSubArea(taskId);// 显示空闲分区链情况showSubArea();} else {printf("错误:请输入 0/1/2\n");}}printf("分配算法模拟结束\n");return 0;}四、实验结果五、实验总结本实验极大的帮助我们理解了动态分区作业存储管理的实现过程。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验五动态分区存储管理一、实验目的深入了解采用动态分区存储管理方式的内存分配回收的实现。
通过编写和调试存储管理的模拟程序以加深对存储管理方案的理解,熟悉动态分区存储管理的内存分配和回收。
二、实验内容编写程序完成动态分区存储管理方式的内存分配回收。
具体包括:确定内存空间分配表;采用最优适应算法完成内存空间的分配和回收;编写主函数对所做工作进行测试。
三、设计思路整体思路:动态分区管理方式将内存除操作系统占用区域外的空间看成一个大的空闲区。
当作业要求装入内存时,根据作业需要内存空间的大小查询内存中的各个空闲区,当从内存空间中找到一个大于或等于该作业大小的内存空闲区时,选择其中一个空闲区,按作业需求量划出一个分区装人该作业,作业执行完后,其所占的内存分区被收回,成为一个空闲区。
如果该空闲区的相邻分区也是空闲区,则需要将相邻空闲区合并成一个空闲区。
设计所采用的算法:采用最优适应算法,每次为作业分配内存时,总是把既能满足要求、又是最小的空闲分区分配给作业。
但最优适应算法容易出现找到的一个分区可能只比作业所需求的长度略大一点的情行,这时,空闲区分割后剩下的空闲区就很小以致很难再使用,降低了内存的使用率。
为解决此问题,设定一个限值minsize,如果空闲区的大小减去作业需求长度得到的值小于等于minsize,不再将空闲区分成己分分区和空闲区两部分,而是将整个空闲区都分配给作业。
内存分配与回收所使用的结构体:为便于对内存的分配和回收,建立两张表记录内存的使用情况。
一张为记录作业占用分区的“内存分配表”,内容包括分区起始地址、长度、作业名/标志(为0时作为标志位表示空栏目);一张为记录空闲区的“空闲分区表”,内容包括分区起始地址、长度、标志(0表空栏目,1表未分配)。
两张表都采用顺序表形式。
关于分配留下的内存小碎片问题:当要装入一个作业时,从“空闲分区表”中查找标志为“1”(未分配)且满足作业所需内存大小的最小空闲区,若空闲区的大小与作业所需大小的差值小于或等于minsize,把该分区全部分配给作业,并把该空闲区的标志改为“0”(空栏目)。
同时,在已分配区表中找到一个标志为“0”的栏目登记新装人作业所占用分区的起始地址,长度和作业名。
若空闲区的大小与作业所需大小的差值大于minsize。
则把空闲区分成两部分,一部分用来装入作业,另外一部分仍为空闲区。
这时只要修改原空闲区的长度,且把新装人的作业登记到已分配区表中。
内存的回收:在动态分区方式下回收内存空间时,先检查是否有与归还区相邻的空闲区(上邻空闲区,下邻空闲区)。
若有,则将它们合件成一个空闲区。
程序实现时,首先将要释放的作业在“内存分配表”中的记录项的标志改为“0”(空栏目),然后检查“空闲区表”中标志为‘1’(未分配)的栏目,查找是否有相邻的空闲区,若有,将之合并,并修改空闲区的起始地址和长度。
四、数据结构定义(1)已分配表的定义:struct{float address; //已分分区起始地址float length; //已分分区长度,单位为字节int flag; //已分配区表登记栏标志,"0"表示空栏目,实验中只支持一个字符的作业名}used_table[n]; //已分配区表(2)空闲分区表的定义:struct{float address; //空闲区起始地址float length; //空闲区长度,单位为字节int flag; //空闲区表登记栏标志,用"0"表示空栏目,用"1"表示未分配}free_table[m]; //空闲区表(3)全局变量float minsize=5;#define n 10 //假定系统允许的最大作业数量为n#define m 10 //假定系统允许的空闲区表最大为m五、源程序代码#include <iostream.h>#include <iomanip.h>//全局变量float minsize=5;int count1=0;int count2=0;#define M 10 //假定系统允许的空闲区表最大为m#define N 10 //假定系统允许的最大作业数量为n//已分配表的定义struct{float address; //已分分区起始地址float length; //已分分区长度,单位为字节int flag; //已分配区表登记栏标志,"0"表示空栏目}used_table[N]; //已分配区表对象名//空闲区表的定义:struct{float address; //空闲区起始地址float length; //空闲区长度,单位为字节int flag; //空闲区表登记栏标志,用"0"表示空栏目,用"1"表示未分配}free_table[M]; //空闲区表对象名//函数声明void initialize(void);int distribute(int, float);int recycle(int);void show();//初始化两个表void initialize(void){int a;for(a=0; a<=N-1; a++)used_table[a].flag=0; //已分配表的表项全部置为空表项free_table[0].address=1000;free_table[0].length=1024;free_table[0].flag=1; //空闲区表的表项全部为未分配}//最优分配算法实现的动态分区int distribute(int process_name, float need_length){int i, k=-1; //k用于定位在空闲表中选择的未分配栏float ads, len;int count=0;i=0;while(i<=M-1) //循环找到最佳的空闲分区{if(free_table[i].flag==1 && need_length <=free_table[i].length){count++;if(count==1||free_table[i].length < free_table[k].length)k=i;}i=i+1;}if(k!=-1){if((free_table[k].length-need_length)<=minsize) //整个分配{free_table[k].flag=0;ads=free_table[k].address;len=free_table[k].length;}else{ //切割空闲区ads=free_table[k].address;len=need_length;free_table[k].address+=need_length;free_table[k].length-=need_length;}i=0;//循环寻找内存分配表中标志为空栏目的项while(used_table[i].flag!=0){i=i+1;}if(i<=N-1) //找到,在已分配区表中登记一个表项{used_table[i].address=ads;used_table[i].length=len;used_table[i].flag=process_name;count1++;}else //已分配区表长度不足{if(free_table[k].flag == 0) //将已做的整个分配撤销{free_table[k].flag=1;free_table[k].address=ads;free_table[k].length=len;}else //将已做的切割分配撤销{free_table[k].address=ads;free_table[k].length+=len;}cout<<"内存分配区已满,分配失败!\n";return 0;}}else{cout <<"无法为该作业找到合适分区!\n";return 0;}return process_name;}int recycle(int process_name){int y=0;float recycle_address, recycle_length;int i, j, k; //j栏是下邻空闲区,k栏是上栏空闲区int x;//在内存分配表中找到要回收的作业while(y<=N-1&&used_table[y].flag!=process_name){ y=y+1;}if(y<=N-1) //找到作业后,将该栏的标志置为'0'{recycle_address=used_table[y].address;recycle_length=used_table[y].length;used_table[y].flag=0;count2++;}else //未能找到作业,回收失败{cout<<"该作业不存在!\n";return 0;}j=k=-1;i=0;while(!(i>=M||(k!=-1&&j!=-1))) //修改空闲分区表{if(free_table[i].flag==1){if((free_table[i].address+free_table[i].length)==recycle_address) k=i; //判断是否有上邻接if((recycle_address+recycle_length)==free_table[i].address)j=i; //判断是否有下邻接}i=i+1;}//合并空闲区if(k!=-1) //回收区有上邻接{if(j!=-1){ //回收区也有下邻接,和上下邻接合并free_table[k].length+=free_table[j].length+recycle_length;free_table[j].flag=0; //将第j栏的标记置为'0'}else //不存在下邻接,和上邻接合并free_table[k].length+=recycle_length;}else if(j!=-1){ //只有下邻接,和下邻接合并free_table[j].length+=recycle_length;free_table[j].address=recycle_address;}else{ //上下邻接都没有x=0;while(free_table[x].flag!=0)x=x+1; //在空闲区表中查找一个状态为'0'的栏目if(x<=M-1){ //找到后,在空闲分区中登记回收的内存free_table[x].address=recycle_address;free_table[x].length=recycle_length;free_table[x].flag=1;}else{ //空闲表已满,执行回收失败used_table[y].flag=process_name;cout<<"空闲区已满,回收失败!\n";return 0;}}return process_name;}void show() //程序执行时输出模拟的内存分配回收表{cout<<"+++++++++++++++++++++++++++++++++++++++\n ";cout<<"+++++++ 空闲区+++++++\n";cout<<"+++++++++++++++++++++++++++++++++++++++\n";for(int i=0;i<=count2;i++)if(free_table[i].flag!=0)cout<<"初始地址:"<<free_table[i].address<<" "<<"长度:"<<free_table[i].length<<" "<<"状态:"<<free_table[i].flag<<endl;cout<<"+++++++++++++++++++++++++++++++++++++++\n ";cout<<"+++++++ 已分配区++++++\n";cout<<"+++++++++++++++++++++++++++++++++++++++\n";for(int j=0;j<count1;j++)if(used_table[j].flag!=0)cout<<"初始地址:"<<used_table[j].address<<" "<<"长度:"<<used_table[j].length<<" "<<"作业名:"<<used_table[j].flag<<endl;}void main() //主函数调用各功能函数对所有工作进行测试{int choice; //用来选择将要进行的操作int job_name;float need_memory;bool exitFlag=false;cout<<" 动态分区分配方式的模拟\n";cout<<"************************************\n";cout<<"请选择操作类型:\n";initialize(); //开创空闲区和已分配区两个表while(!exitFlag){cout<<"********************************************\n";cout<<"** 1: 分配内存2: 回收内存**\n";cout<<"** 3: 查看分配0: 退出**\n";cout<<"********************************************\n";cout<<"请输入您的操作:";cin>>choice;switch(choice){case 0:exitFlag=true; //退出操作break;case 1:cout<<"请输入作业号和所需内存:";cin>>job_name>>need_memory;if(job_name!=0&&need_memory!=0)distribute(job_name, need_memory); // 分配内存else if(job_name==0)cout<<"作业号不能为零!\n请重新选择操作:\n";else if(need_memory==0)cout<<"内存分配数不能为零!\n请重新选择操作:\n";break;case 2:int ID;cout<<"请输入您要释放的作业号:";cin>>ID;if(ID!=0)recycle(ID); //回收内存elsecout<<"作业名不能为零!\n请重新选择操作:\n";break;case 3:show();break;}}}六、实验结果分析1. 运行源程序,模拟内存的分配与回收操作,并记录实验结果。