目录
一、实验目的
二、实验内容
三、实验思路
四、实验流程图
五、主要数据结构
六、实现代码
七、运行结果
通过这次实验,加深对内存管理的认识,进一步掌握内存的分配、回收算法的思想。
设计程序模拟内存的动态分区内存管理方法。内存分区使用分区(说明)表进行管理,采用最先适应算法从分区表中寻找空闲区进行分配,考虑内存回收时相邻空闲区的合并。
假设初始状态下,可用的内存空间为640KB,并有下列的请求序列:
•作业1申请130KB •作业2申请60KB。
•作业3申请100KB •作业2释放60KB。
•作业4申请200KB •作业3释放100KB。
•作业1释放130KB •作业5申请140KB。
•作业6申请60KB •作业7申请50KB •作业6释放60KB。
最先适应算法:将空闲区按其在存储空间中的起始地址递增的顺序排列。为作业分配存储空间时,从空闲区链的始端开始查找,选择第一个满足要求的空闲区,而不管它究竟有多大。
内存回收原理:找到当前回收的内存区间,首先判断是否和前一个区间相邻且空闲,如果相邻的话则该分区和前一分区合并,形成更大的空闲分区;若和前一空闲分区不相邻,则判断该分区是否和后一分区相邻且空闲,则该分区和后一分区合并,形成更大的空闲分区;如果该分区和前后空闲分区都不相邻,则将该分区以后的所有表目向后移动一个,形成一个新的表目并插入新释放的分区。
本实验模拟内存的动态分区内存管理方法,采用最先适应算法。定义一个链表,记录内存分配情况,并定义内存分配、回收的方法,对内存空间进行管理。
分区节点:包含分区被分配的作业编号、起始地址、终止地址、大小、状态。
集合:显示内存使用情况的集合,用于实现内存空间的分配、回收。
//节点类:
public class Node {
int id; // 作业id,为-1代表空闲分区;大于0代表已分配
String name;// 作业名称
int start; // 初始地址
int last;// 结束地址
int size; // 大小
int state;
}
//主程序:
import java.util.*;
//从空闲分区表的第一个表目起查找该表,把最先能够满足要求的空闲区分配给作业,
public class FF {
// 返回分区链表
private static List init() {
ArrayList list = new ArrayList();
Node node = new Node();
// 初始化,为整个内存空间分配一个空闲节点
node.id = -1;
node.start = 0;
node.last = 640;
node.size = 640;//内存空间为640KB,高端40K用来存放操作系统。
node.state = 0;
list.add(node);
return list;
}
// 为作业id在分区链表list中分配大小为size的内存
//1 语法public E get(int index)2 参数index:要返回的元素的索引。3 返回值返回ArrayList中指定位置的元素
private static boolean add(List list, int id,String name, int size) {
Collections.sort(list, new Comparator() {
@Override
public int compare(Node o1, Node o2) {
// TODO Auto-generated method stub
return o1.start - o2.start;
}
});
Node p = null;
int i;
// 找到第一个未分配且大于size的内存空间节点p,i为其下标
for (i = 0; i < list.size(); i++) {
p = list.get(i);
if (p.id == -1 && p.size >= size)//找到大小符合的空闲区
break;
}
// 当原来节点的大小大于size时需要创建一个新节点temp保留余下的分区,并插在p的后面
if (p.size - size >= 0) {
Node temp = new Node();//后边剩余的空间
temp.id = -1;
temp.start = p.start + size;
temp.last = p.last;
temp.size = p.size - size;
temp.state = 0;
list.add(temp);// 前边是p, 后边是temp
}
// 将原来节点变成已分配的节点并为其分配大小
p.id = id;
p.size = size;
p.last = p.start+p.size;
p.state = 1;
return true;
}
// 回收作业id的内存,并合并相邻的空闲分区
private static boolean del(List list, int id) {
Collections.sort(list, new Comparator() {
@Override
public int compare(Node o1, Node o2) {
// TODO Auto-generated method stub
return o1.start - o2.start;
}
});
Node p = null;
int i;
// 找到作业id所在的节点p,i为其下标
for (i = 0; i < list.size(); i++) {
p = list.get(i);
if (p.id == id) break;//退出后获得i的大小
}
p.id = -1; // 回收分区
p.state = 0;
Node a, b;
if (i != 0) { // 若第i-1个节点和第i个节点相邻,合并两个分区
a = list.get(i - 1);
b = list.get(i);
if (a.id == -1 && b.id == -1 && a.start + a.size == b.start) {
a.size += b.size;
a.last = a.start+a.size;
a.state = 0;
list.remove(i);
// i--;
}
// i--是因为可能存在合并后的节点可能与后一个节点相邻
}
if (i != list.size() - 1) { // 若第i个节点和第i+1个节点相邻,合并两个分区
a = list.get(i);
b = list.get(i + 1);
if (a.id == -1 && b.id == -1 && a.start + a.size == b.start) {
a.size += b.size;
a.last = a.start+a.size;
a.state = 0;
list.remove(i + 1);
}
}
return true;
}
private static void show(List list) {
Collections.sort(list, new Comparator() {
@Override
public int compare(Node o1, Node o2) {
// TODO Auto-generated method stub
return o1.start - o2.start;
}
});
System.out.println("内存分配情况");
System.out.println("作业编号\t起始地址\t终止地址\t大小\t状态");
for (int i = 0; i < list.size(); i++) {
Node p=list.get(i);
if (p.id==-1) {
System.out.println("null"+"\t"+p.start+"\t"+p.last+"\t"+p.size+"KB\t"+p.state);
}
else {
System.out.println("作业"+p.id+"\t"+p.start+"\t"+p.last+"\t"+p.size+"KB\t"+p.state);
}
}
}
public static void main(String[] args) {
List list = init();
System.out.println("内存初始状态");
System.out.println("作业编号\t起始地址\t终止地址\t大小\t状态");
Node p=list.get(0);
System.out.println("null"+"\t"+p.start+"\t"+p.last+"\t"+p.size+"KB\t"+p.state);
System.out.println();
System.out.println("-------------------------------");
// 作业1申请130KB
System.out.println();
System.out.println("作业1申请130KB");
add(list,1,"作业1",130);
show(list);
System.out.println("-------------------------------");
// 作业2申请60KB
System.out.println();
System.out.println("作业2申请60KB");
add(list,2,"作业2",60);
show(list);
System.out.println("-------------------------------");
// 作业3申请100KB
System.out.println();
System.out.println("作业3申请100KB");
add(list,3,"作业3",100);
show(list);
System.out.println("-------------------------------");
// 作业2释放60KB
System.out.println();
System.out.println("作业2释放60KB");
del(list, 2);
show(list);
System.out.println();
System.out.println("-------------------------------");
// 作业4申请200KB
System.out.println();
System.out.println("作业4申请200KB");
add(list,4,"作业4",200);
show(list);
System.out.println("-------------------------------");
// 作业3释放100KB
System.out.println();
System.out.println("作业3释放100KB");
del(list, 3);
show(list);
System.out.println("-------------------------------");
作业1释放130KB
System.out.println();
System.out.println("作业1释放130KB");
del(list, 1);
show(list);
System.out.println("-------------------------------");
// 作业5申请140KB
System.out.println();
System.out.println("作业5申请140KB");
add(list,5,"作业5",140);
show(list);
System.out.println("-------------------------------");
// 作业6申请60KB
System.out.println();
System.out.println("作业6申请60KB");
add(list,6,"作业6",60);
show(list);
System.out.println("-------------------------------");
// 作业7申请50KB
System.out.println();
System.out.println("作业7申请50KB");
add(list,7,"作业7",50);
show(list);
System.out.println("-------------------------------");
// 作业6释放60KB
System.out.println();
System.out.println("作业6释放60KB");
del(list, 6);
show(list);
}
}