设计一个内存分配与回收算法。要求首先构造一个空闲的内存分区表或链,然后构造进程信息(最少构造5个进程),在PCB中设置所需内存大小,增加内存起始位置(用于接收分配内存的首地址),分别应用首次适应算法、最佳适应算法、最坏适应算法模拟内存分配。设计内存回收算法,随机结束一些进程,然后回收内存。显示内存分配和回收后的结果。
·提示:
1)内存分配。系统利用某种内存分配算法,从空闲分区表/链中找到所需大小的内存。设请求的分区大小为usize,空闲分区的大小为msize,若msize-usize≤size(size是事先规定的不再切割的剩余分区大小),说明多余部分太小,不再切割,这时将整个分区分配给请求者;否则,从分区中划分一块内存分配给请求者,余下的部分仍然留在空闲分区表/链中,然后将分配的首地址返回给调用者。
2)内存回收。系统根据回收分区的大小及首地址,在空闲分区表中检查是否有邻接的空闲分区,如果有则合并成一个大的空闲分区,否则,在空闲分区表/链中增加这块内存信息。
package com.example.test;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
class Memory {
int start;
int size;
Memory(int start, int size) {
this.start = start;
this.size = size;
}
}
class Process {
int id;
int size;
int start;
Process(int id, int size) {
this.id = id;
this.size = size;
this.start = -1; // 默认起始位置为-1,表示尚未分配内存
}
}
public class MemoryAllocation {
private static List<Memory> freeMemoryList = new ArrayList<>(); // 空闲分区表
private static List<Process> processList = new ArrayList<>(); // 进程列表
public static void main(String[] args) {
int totalSize = 1000; // 总内存大小
int minSize = 10; // 最小剩余分区大小
int numOfProcesses = 5; // 进程数量
initFreeMemory(totalSize); // 初始化内存空闲分区
// 创建进程列表
for (int i = 0; i < numOfProcesses; i++) {
processList.add(new Process(i+1, getRandomSize()));
}
allocateMemory("First Fit"); // 使用首次适应算法分配内存
printMemoryStatus();
allocateMemory("Best Fit"); // 使用最佳适应算法分配内存
printMemoryStatus();
allocateMemory("Worst Fit"); // 使用最坏适应算法分配内存
printMemoryStatus();
// 随机结束一些进程
Random rand = new Random();
for (int i = 0; i < numOfProcesses / 2; i++) {
int index = rand.nextInt(processList.size());
Process process = processList.get(index);
if (process.start != -1) {
deallocateMemory(process);
processList.remove(index);
}
}
printMemoryStatus();
}
// 生成随机的进程大小
private static int getRandomSize() {
Random rand = new Random();
int minSize = 10;
int maxSize = 100;
return rand.nextInt(maxSize - minSize + 1) + minSize;
}
// 初始化内存空闲分区
private static void initFreeMemory(int totalSize) {
freeMemoryList.clear();
freeMemoryList.add(new Memory(0, totalSize));
}
// 首次适应算法,返回被分配的内存起始位置
private static int firstFit(int processSize) {
// 遍历空闲内存列表
for (Memory memory : freeMemoryList) {
// 如果当前空闲内存大小大于等于进程大小
if (memory.size >= processSize) {
int start = memory.start; // 记录当前空闲内存的起始位置
memory.start += processSize; // 更新当前空闲内存的起始位置
memory.size -= processSize; // 减去已经分配给进程的内存大小
return start; // 返回进程分配的内存起始位置
}
}
return -1; // 内存分配失败,返回-1
}
// 最佳适应算法,返回被分配的内存起始位置
private static int bestFit(int processSize) {
int minSize = Integer.MAX_VALUE;
int startIndex = -1;
for (int i = 0; i < freeMemoryList.size(); i++) {
Memory memory = freeMemoryList.get(i);
if (memory.size >= processSize && memory.size < minSize) {
minSize = memory.size;
startIndex = i;
}
}
if (startIndex != -1) {
Memory memory = freeMemoryList.get(startIndex);
int start = memory.start;
memory.start += processSize;
memory.size -= processSize;
return start;
}
return -1; // 内存分配失败
}
// 最坏适应算法,返回被分配的内存起始位置
private static int worstFit(int processSize) {
int maxSize = Integer.MIN_VALUE;
int startIndex = -1;
for (int i = 0; i < freeMemoryList.size(); i++) {
Memory memory = freeMemoryList.get(i);
if (memory.size >= processSize && memory.size > maxSize) {
maxSize = memory.size;
startIndex = i;
}
}
if (startIndex != -1) {
Memory memory = freeMemoryList.get(startIndex);
int start = memory.start;
memory.start += processSize;
memory.size -= processSize;
return start;
}
return -1; // 内存分配失败
}
// 内存分配
private static void allocateMemory(String algorithm) {
for (Process process : processList) {
if (process.start == -1) { // 尚未分配内存的进程才进行分配
int start;
switch (algorithm) {
case "First Fit":
start = firstFit(process.size);
break;
case "Best Fit":
start = bestFit(process.size);
break;
case "Worst Fit":
start = worstFit(process.size);
break;
default:
return;
}
if (start != -1) {
process.start = start;
}
}
}
}
// 内存回收
private static void deallocateMemory(Process process) {
// 创建一个新的内存块,参数为进程的起始地址和大小
Memory newMemory = new Memory(process.start, process.size);
// 插入位置的索引,默认为-1
int insertIdx = -1;
// 查找回收的内存应该插入的位置
for (int i = 0; i < freeMemoryList.size(); i++) {
// 如果当前空闲内存块的起始地址大于新内存块的起始地址,则找到插入位置
if (freeMemoryList.get(i).start > newMemory.start) {
insertIdx = i;
break;
}
}
// 合并相邻的内存分区
// 检查需要插入新内存块的位置是否存在,并且不越界范围
if (insertIdx != -1 && insertIdx < freeMemoryList.size()) {
// 查找当前位置、前一个位置和后一个位置的内存块
Memory prev = insertIdx > 0 ? freeMemoryList.get(insertIdx - 1) : null;
Memory curr = freeMemoryList.get(insertIdx);
Memory next = insertIdx < freeMemoryList.size() - 1 ? freeMemoryList.get(insertIdx + 1) : null;
// 如果前一个内存块存在且与新内存块相邻,则合并它们
if (prev != null && prev.start + prev.size == newMemory.start) {
prev.size += newMemory.size;
// 如果下一个内存块也与新内存块相邻,则将其合并到前一个内存块
if (next != null && newMemory.start + newMemory.size == next.start) {
prev.size += next.size;
// 移除下一个内存块,因为它已经并入前一个内存块
freeMemoryList.remove(insertIdx + 1);
}
}
// 如果后一个内存块存在且与新内存块相邻,则合并它们
else if (next != null && newMemory.start + newMemory.size == next.start) {
newMemory.size += next.size;
curr.size = newMemory.size;
curr.start = newMemory.start;
// 移除下一个内存块,因为它已经并入新内存块
freeMemoryList.remove(insertIdx + 1);
}
// 如果前后相邻的内存块都不存在,则将新内存块插入列表中指定位置
else {
freeMemoryList.add(insertIdx, newMemory);
}
}
// 如果插入位置为-1或超出了空闲内存列表的索引范围,则直接将新内存块添加到列表中
else {
freeMemoryList.add(newMemory);
}
}
// 打印内存分配和回收后的结果
private static void printMemoryStatus() {
System.out.println("Memory Allocation Status:");
System.out.println("-------------------------");
System.out.println("Free Memory:");
for (Memory memory : freeMemoryList) {
System.out.println("Start: " + memory.start + ", Size: " + memory.size);
}
System.out.println("-------------------------");
System.out.println("Allocated Memory:");
for (Process process : processList) {
if (process.start != -1) {
System.out.println("Process ID: " + process.id + ", Size: " + process.size + ", Start: " + process.start);
}
}
System.out.println("-------------------------");
System.out.println();
}
}