实习题目
内存管理模型的设计与实现
【问题描述】
1.内存管理模型的设计与实现
对内存的可变分区申请采用链表法管理进行模拟实现。要求:
(1) 对于给定的一个存储空间自己设计数据结构进行管理,可以使用单个链表,也
可以使用多个链表,自己负责存储空间的所有管理组织,要求采用分页方式(指
定单元大小为页,如 4K,2K,进程申请以页为单位)来组织基本内容;
(2) 当进程对内存进行空间申请操作时,模型采用一定的策略(如:首先利用可用
的内存进行分配,如果空间不够时,进行内存紧缩或其他方案进行处理)对进
程给予指定的内存分配;
(3) 从系统开始启动到多个进程参与申请和运行时,进程最少要有 3 个以上,每个
执行申请的时候都要能够对系统当前的内存情况进行查看的接口;
(4) 对内存的申请进行内存分配,对使用过的空间进行回收,对给定的某种页面调
度进行合理的页面分配。
(5) 利用不同的颜色代表不同的进程对内存的占用情况,动态更新这些信息。
一、需求分析
内存分配方式 内存分配方式有三种:
(1) 从静态存储区域分配。 内存在程序编译的时候就已经分配好, 这块内存在程序的整
个运行期间都存在。 例如全局变量,static 变量。
(2)在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执
行结束时这些存 储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,
但是分配的内存容量有限。
(3)从堆上分配,亦称动态内存分配。程序在运行的时候用 malloc 或 new 申请任意多少
的内存,程序员 自己负责在何时用 free 或 delete 释放内存。 动态内存的生存期由我们决
定, 使用非常灵活, 但问题也最多;
要实现对内存的合理化分配和对闲置的进程占有的内存进行分配,需要有个很好的内存管理
模型。
二、设计
1. 设计思想
首次适度算法(FirstFit):从内存的首地址出发,选择第一个能满足进程大小内存空闲块。
最佳适度算法(BestFit):从内存的首地址出发,选择内存空闲块中最适合进程大小的块。
邻近适度算法(NextFit):从上一次分配的地址开始查找第一个能满足进程大小的内存空 闲
块。
2. 设计表示
(1)函数调用关系图
3. 实现注释
(1),分区和节点都用结构体来表示;
(2),对链表的内存申请采用链表的方式存储;
(3),对内存的申请有四种可供选择的策略;
4. 详细设计
分区表的结构体:
typedef struct {
byte subareaSize;//分区大小
int startLoc;//起始地址
int index;// 分区号
}SubareaTable;//分区表
结点的结构体:
typedef struct node{// 结点
SubareaTable subarea;// 分区
struct node *next;
int status;//状态位 0(空闲)1(使用)
}*Node,*LinkList;
进程的结构体:
typedef struct {
byte processSize;
int subareaIndex;//保存分区号
int status;//进程状态,0(新建)1(执行)-1(终止)-2(未绪。申请但没有分配内
存)2(就绪,已分配内存)
}Process;//进程
本程序运用到的变量有:
int subareaSize[num]={8,12,16,32,24,16,64,128,40,64};//分区大小
Process *pro=NULL;//保持进程信息
int ProcessNum=0;//进程数目
int applyProcessNum=0;//每次申请进程数目
int maxApplyNum=0;//最大可申请数目
int *applyIndex=NULL;//申请进程队列
int totalApplyNum=0;//申请总数
int *assignPointer=NULL;//已分配内存的进程队列
int assignFlag=0;//分配索引,表示已申请队列已分配的进程数
int exeIndex;//执行的进程号
三、调试分析
遇到的问题:在开始选择内存分配的时候总是出现调试中断的错误 ,后来在同
学的帮助下调试了好半天才检查出来时内存分配的错误,我发现我经常犯这方面
的错误,这次的实习给了我提示,以后碰到内存分配的时候一定会多加注意的。
五、运行结果
运行结果的部分截图如下:
内存分配:
六、源程序清单
本题中的主要代码如下:
首次适应算法:
Node firstFit(LinkList &head,Process pro){
Node p=head->next;//遍历节点,返回节
点,从第一个节点开始遍历
if(p==NULL){
cout<<"空闲链表不存在!"<
else{
do{
if(p->status==0&&p->subarea.subareaSize>=pro.processSize){
break;
}
}
p=p->next;
while(p!=NULL);
if(p==NULL){//没有找到合适的节点
return head;
}
return p;
}
循环适度算法:
Node nestFit(LinkList &head,Process pro,Node flag){//
循环适应算法
Node p=flag->next;//遍历结点
while(p!=NULL){
if(p->status==0&&p->subarea.subareaSize>=pro.processSize){
break;
}
p=p->next;
}
if(p==NULL){//遍历到链表结尾
p=head;//从头开始遍历
while(p!=flag){//标记结点
p=p->next;
if(p->status==0&&p->subarea.subareaSize>=pro.processSize){
break;
}
}
if(p==flag){//正常跳出循环,没有合适的结点可分配
return head;
}else{
return p;// 在 flag 结点前找到一合适的结点分配
}
}else{
return p;// 在 flag 结点后找到一合适的结点分配
}