实验目的
1.详细了解系统之中是如何存储进程的。
2.通过实验加强对基于顺序搜索的动态分区分配算法的理解和掌握。
3.加深理解有关存储结构的概念。
4.主存的分配和回收的实现与主存储器的管理方式有关的,通过本次实验帮助学生理解在可变分区管理方式下是怎样实现主存空间的分配和回收。
实验原理
1.动态分区分配是根据进程的实际需要,动态地为作业从可用内存中划分出一个分区,刚好能满足作业的实际需要。而在分配时,须按照一定的分配算法,从空闲分区表或空闲分区链中选出以分区分配给该算法。
2.在本次实验中运用四种算法,分别是首次适应算法、循环首次适应算法、最坏适应算法和最佳适应算法。
整个程序的大致流程
首次适应算法流程图
循环首次适应算法流程图
最佳适应算法流程图
最坏适应算法流程图
public class DPA {
public Memory FF(Memory memory, int size) {
int sum = 0;
for (int i = 0; i < memory.getHoles().size(); i++) { //循环内存中所有分区
sum++;
memory.setLastPoint(i); //为循环首次适应算法设置最后寻址的下标
Hole hole = memory.getHoles().get(i); //获得对应的分区
if (hole.isFree() && hole.getSize() >= size) { //若此分区空闲且大小大于申请的大小,则申请内存
System.out.println("查找" + sum + "次");
return memory.getMemory(size, i, hole);
}
}
System.err.println("内存不够");
return memory;
}
public Memory NF(Memory memory, int size) {
Hole hole = memory.getHoles().get(memory.getLastPoint());
if (hole.isFree() && hole.getSize() >= size) { //判断最后寻址的分区的大小是否足够
return memory.getMemory(size, memory.getLastPoint(), hole);
}
int length = memory.getHoles().size();
int sum = 0; //为区分与首次适应算法循环次数所设置
//如果不够,则从下一个分区开始循环
for (int i = (memory.getLastPoint() + 1) % length; i != memory.getLastPoint(); i = (i + 1) % length) {
sum++;
memory.setLastPoint(i);
hole = memory.getHoles().get(i);
if (hole.isFree() && hole.getSize() >= size) {
System.out.println("查找" + sum + "次");
return memory.getMemory(size, i, hole);
}
}
System.err.println("内存不够");
return memory;
}
public Memory BF(Memory memory, int size) {
int findIndex = -1; //最佳分区的下标
int min = memory.getSize(); //min存储当前找到的最小的合适的分区大小
for (int i = 0; i < memory.getHoles().size(); i++) {
Hole hole = memory.getHoles().get(i);
if (hole.isFree() && hole.getSize() >= size) {
if (min > hole.getSize() - size){ //若当前找到的分区大小比min还要合适(剩余空间更小),则修改其值
min = hole.getSize() - size;
findIndex = i;
}
}
}
if (findIndex != -1) { //若存在合适分区
return memory.getMemory(size, findIndex, memory.getHoles().get(findIndex));
}
System.err.println("内存不够");
return memory;
}
public Memory WF(Memory memory, int size) {
int findIndex = -1;
int max = 0;
for (int i = 0; i < memory.getHoles().size(); i++) {
Hole hole = memory.getHoles().get(i);
if (hole.isFree() && hole.getSize() >= size) {
if (max < hole.getSize() - size){
max = hole.getSize() - size;
findIndex = i;
}
}
}
if (findIndex != -1) {
return memory.getMemory(size, findIndex, memory.getHoles().get(findIndex));
}
System.err.println("内存不够");
return memory;
}
public void showMemory(Memory memory) {
System.out.println("------------------------------------");
System.out.println("分区编号\t分区始址\t分区大小\t空闲状态\t");
System.out.println("------------------------------------");
for (int i = 0; i < memory.getHoles().size(); i++){
Hole hole = memory.getHoles().get(i);
System.out.println(i + "\t\t" + hole.getHead() + "\t\t" + hole.getSize() + " \t" + hole.isFree());
}
System.out.println("------------------------------------");
}
}
public class Hole {
private int head; //内存块的起始地址
private int size; //内存块的大小
private boolean isFree; //内存块的空闲状态
public Hole(int head, int size) {
this.head = head;
this.size = size;
this.isFree = true;
}
@Override
public String toString() {
return "Hole{" +
"head=" + head +
", size=" + size +
", isFree=" + isFree +
'}';
}
public int getHead() {
return head;
}
public void setHead(int head) {
this.head = head;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public boolean isFree() {
return isFree;
}
public void setFree(boolean free) {
isFree = free;
}
}
public class Memory {
private int size; //内存块大小
private int LastPoint; //上次寻址结束的下标
private LinkedList<Hole> holes; //记录内存块分区的双向链表
private static final int MIN_SIZE = 5; //最小剩余分区大小
public Memory getMemory(int size, int location, Hole hole) { //size为申请大小 location为分配分区的下标 hole为location对应的分区
if (hole.getSize() - size >= MIN_SIZE) { //若分配后当前分区剩余大小大于最小分区大小,则把当前分区分为两块
Hole newHole = new Hole(hole.getHead() + size, hole.getSize() - size);
holes.add(location + 1, newHole);
hole.setSize(size);
}
hole.setFree(false); //设置当前分区为非空闲状态
System.out.println("成功分配大小为" + size + "的内存");
return this;
}
public Memory releaseMemory(int id) {
Hole hole = holes.get(id); //此id为分区id
if (hole.isFree()) {
System.out.println("此分区空闲,无需释放:\t" + id);
return this;
}
//如果回收分区不是尾分区且后一个分区为空闲, 则与后一个分区合并
if (id < holes.size() - 1 && holes.get(id + 1).isFree()) {
Hole nextHole = holes.get(id + 1);
hole.setSize(hole.getSize() + nextHole.getSize());
holes.remove(nextHole);
}
//如果回收分区不是首分区且前一个分区为空闲, 则与前一个分区合并
if (id > 0 && holes.get(id - 1).isFree()) {
Hole lastHole = holes.get(id - 1);
lastHole.setSize(hole.getSize() + lastHole.getSize());
holes.remove(id);
id--;
}
holes.get(id).setFree(true);
System.out.println("内存回收成功!");
return this;
}
public Memory(int size) {
this.size = size;
// this.pcbs = new LinkedList<>();
this.holes = new LinkedList<>();
holes.add(new Hole(0, size));
}
@Override
public String toString() {
return "Memory{" +
"size=" + size +
", holes=" + holes.toString() +
'}';
}
public int getLastPoint() {
return LastPoint;
}
public void setLastPoint(int lastFind) {
this.LastPoint = lastFind;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public LinkedList<Hole> getHoles() {
return holes;
}
public void setHoles(LinkedList<Hole> holes) {
this.holes = holes;
}
public static int getMinSize() {
return MIN_SIZE;
}
}
public class Test1 {
public static void main(String[] args) {
DPA dpa = new DPA();
Scanner sr = new Scanner(System.in);
System.out.print("初始化内存大小:");
System.out.println();
Memory memory = new Memory(sr.nextInt());
System.out.println("初始化成功!");
while (true) {
System.out.print("请输入操作数(0、结束进程\t1、申请内存\t2、释放内存):");
switch (sr.nextInt()) {
case 0:
System.exit(0);
break;
case 1:
System.out.print("请选择算法(1、首次适应算法\t2、循环首次适应算法\t3、最佳适应算法\t4、最坏适应算法):");
int algorithm = sr.nextInt();
System.out.print("请输入申请大小:");
int size = sr.nextInt();
switch (algorithm) {
case 1:
memory = dpa.FF(memory, size);
break;
case 2:
memory = dpa.NF(memory, size);
break;
case 3:
memory = dpa.BF(memory, size);
break;
case 4:
memory = dpa.WF(memory, size);
break;
default:
System.out.println("操作取消");
break;
}
dpa.showMemory(memory);
break;
case 2:
System.out.print("请输入需要释放的分区id或进程id:");
int id = sr.nextInt();
System.out.println();
memory = memory.releaseMemory(id);
dpa.showMemory(memory);
break;
default:
System.err.println("未知标识符");
break;
}
}
}
}