本程序利用java编程语言对其进行了实现。
源代码移步:http://download.csdn.net/download/chengshijian2015/10215534
可变分区调度算法有:最先适应分配算法,最优适应分配算法,最坏适应算法。
用户提出内存空间的申请;系统根据申请者的要求,按照一定的分配策略分析内存空间的使用情况,找出能满足请求的空闲区,分给申请者;当程序执行完毕或主动归还内存资源时,系统要收回它所占用的内存空间或它归还的部分内存空间。
每当一个进程被创建时,内存分配程序首先要查找空闲内存分区表(链),从中寻找一个合适的空闲块进行划分,并修改空闲内存分区表(链)。当进程运行完毕释放内存时,系统根据回收区的首址,从空闲区表(链)中找到相应的插入点,此时出现如下四种情况:
1) 回收区与插入点的前一个空闲分区F1相邻接,此时可将回收区直接与F1合并,并修改F1的大小;
2) 回收区与插入点的后一个空闲分区F2相邻接,此时可将回收区直接与F2合并,并用回收区的首址最为新空闲区的首址,大小为二者之和;
3) 回收区同时与插入点的前、后两个空闲分区邻接,此时需将三者合并;
4) 回收区不与任何一个空闲区邻接,此时应建一新的表项。
源代码:
DynamicPartAllocate.java:
package com.csi.operatesystem;
import java.util.Scanner;
/**
* Created by ChengShiJian on 2017/11/08.
*
*/
public class DynamicPartAllocate {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("软件1503 程世健 1511030304");
final Scanner scanner = new Scanner(System.in);
new DynamicPartAllocatePresenter().setOnExcuteLisenter(new OnExcuteLisenter() {
@Override
public Job getJob() {
// TODO Auto-generated method stub
while (true) {
System.out.print("请输入作业(作业号 所用空间大小)>");
Job job = new Job();
int id = scanner.nextInt();
if (id < 1) {
System.out.println("作业号必须大于0!");
continue;
}
int length = scanner.nextInt();
job.setJobId(id);
job.setLength(length);
return job;
}
}
@Override
public void onOutOfMemory() {
// TODO Auto-generated method stub
System.out.println("磁盘空间不足!");
}
@Override
public void onAllocateSuccess(Partition partition) {
// TODO Auto-generated method stub
System.out.println("----------------------------当前内存情况------------------------------");
System.out.println(
"起始地址 终点地址 内存大小 状态 作业号");
for (PartBlock block : partition.getBlocks()) {
System.out.printf("%-15d%-15d%-15d%-30s%-15s\n", block.getStartAddress(), block.getEndAddress(),
block.getLength(), block.getState(), block.getJobId()==0?"":String.valueOf(block.getJobId()));
}
System.out.println("------------------------------------------------------------------");
}
@Override
public int getJobId() {
// TODO Auto-generated method stub
System.out.print("请输入作业id>");
return scanner.nextInt();
}
@Override
public void onSearchError(int id) {
// TODO Auto-generated method stub
System.out.println("作业" + id + "不存在!回收内存失败!");
}
@Override
public void onRetrieveSuccess(Partition partition) {
// TODO Auto-generated method stub
System.out.println("----------------------------当前内存情况------------------------------");
System.out.println(
"起始地址 终点地址 内存大小 状态 作业号");
for (PartBlock block : partition.getBlocks()) {
System.out.printf("%-15d%-15d%-15d%-30s%-15s\n", block.getStartAddress(), block.getEndAddress(),
block.getLength(), block.getState(), block.getJobId()==0?"":String.valueOf(block.getJobId()));
}
System.out.println("------------------------------------------------------------------");
}
@Override
public int onGetMethod() {
// TODO Auto-generated method stub
System.out.println("0.最先适应分配算法 1.最优适应分配算法 2.最坏适应分配算法");
System.out.print("请选择分配算法>");
switch (scanner.nextInt()) {
case 0:
return DynamicPartAllocatePresenter.FIRST_FIT;
case 1:
return DynamicPartAllocatePresenter.BEST_FIT;
case 2:
return DynamicPartAllocatePresenter.BAD_FIT;
default:
return -1;
}
}
@Override
public int onGetOperate() {
// TODO Auto-generated method stub
System.out.println("0.分配 1.回收 2.退出");
System.out.print("请选择>");
switch (scanner.nextInt()) {
case 0:
return DynamicPartAllocatePresenter.ALLOCATE;
case 1:
return DynamicPartAllocatePresenter.RETRIVE;
case 2:
System.exit(0);
break;
}
return -1;
}
}).excute();
}
}
DynamicPartAllocatePresenter.java:
package com.chengshijian.operatesystem;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* Created by ChengShiJian on 2017/11/08.
*
* 任命者类,动态内存分配的全部逻辑操作全部在这个类中
*/
public class DynamicPartAllocatePresenter {
public static final int FIRST_FIT = 0;//最先适应算法
public static final int BEST_FIT = 1;//最优适应算法
public static final int BAD_FIT = 2;//最坏适应算法
public static final int ALLOCATE = 3;//分配
public static final int RETRIVE = 4;//回收
private Partition partition = new Partition();//内存
private int method;//算法
private int operate;//操作,指分配还是回收
private boolean isAllocateSuccess = false;//是否分配成功
private boolean isSearchSuccess = false;//是否查找成功
private OnExecuteLisenter lisenter;//执行事件监听器
// 一.实验目的
// 用高级语言编写和调试一个内存分配模拟程序,以加深对动态分区的概念及内存分配原理的理解。
// 二.实验原理
// 可变分区调度算法有:最先适应分配算法,最优适应分配算法,最坏适应算法。
// 用户提出内存空间的申请;系统根据申请者的要求,按照一定的分配策略分析内存空间的使用情况,
// 找出能满足请求的空闲区,分给申请者;当程序执行完毕或主动归还内存资源时,系统要收回它所占用的内存空间或它归还的部分内存空间。
// 每当一个进程被创建时,内存分配程序首先要查找空闲内存分区表(链),从中寻找一个合适的空闲块进行划分,
// 并修改空闲内存分区表(链)。当进程运行完毕释放内存时,系统根据回收区的首址,从空闲区表(链)中找到相应的插入点,此时出现如下四种情况:
// 1) 回收区与插入点的前一个空闲分区F1相邻接,此时可将回收区直接与F1合并,并修改F1的大小;
// 2) 回收区与插入点的后一个空闲分区F2相邻接,此时可将回收区直接与F2合并,并用回收区的首址最为新空闲区的首址,大小为二者之和;
// 3) 回收区同时与插入点的前、后两个空闲分区邻接,此时需将三者合并;
// 4) 回收区不与任何一个空闲区邻接,此时应建一新的表项。
// 三.实验内容
// 编写并调试一个模拟的内存分配程序。具体做法为:使用一个循环,根据提示,由用户选择随时创建一个新的进程,并为其分配存储空间,
// 也随时可以撤销一个进程,可以根据需要随时打印空闲分区表(链)以及打印系统中内存使用情况。
public DynamicPartAllocatePresenter setOnExcuteLisenter(OnExecuteLisenter lisenter) {
this.lisenter = lisenter;
return this;
}
public DynamicPartAllocatePresenter setOperate(int operate) {
this.operate = operate;
return this;
}
public int getMethod() {
return method;
}
public void setMethod(int method) {
this.method = method;
}
//回收
private void retrieve() {
int id = lisenter.getJobId();//获取作业号
int index = 0;//先将目的查找Block 置为0
for (int i = 0; i < partition.getBlocks().size(); i++) {
PartBlock block = partition.getBlocks().get(i);
if (block.getJobId() == id) {
index = i;
isSearchSuccess = true;
break;
}
}
if (isSearchSuccess) {//如果查找成功
List blocks = partition.getBlocks();
sortByAddress(blocks);//将内存中的内存块按起始地址由小到大排序
PartBlock block = partition.getBlocks().get(index);
block.setState(Partition.NOT_ALLOCATE);
block.setJobId(0);
PartBlock afterBlock = null;
PartBlock beforeBlock = null;
int originalBlockSize=blocks.size()-1;//先记录未合并之前内存中内存块的数量
if (index != 0) {
beforeBlock = blocks.get(index - 1);//得到前一个块
}
if (index != blocks.size() - 1) {
afterBlock = partition.getBlocks().get(index + 1);//得到后一个块
}
//向前合并
if (index != 0) {
sortByAddress(partition.getBlocks());
if (beforeBlock.getState().equals(Partition.NOT_ALLOCATE)) {
block.setStartAddress(beforeBlock.getStartAddress());
block.setLength(beforeBlock.getLength() + block.getLength());
block.setEndAddress(block.getStartAddress() + block.getLength());
blocks.remove(beforeBlock);
}
}
//向后合并
if (index != originalBlockSize) {
if (afterBlock.getState().equals(Partition.NOT_ALLOCATE)) {
block.setLength(afterBlock.getLength() + block.getLength());
block.setEndAddress(block.getStartAddress() + block.getLength());
blocks.remove(afterBlock);
}
}
lisenter.onAllocateSuccess(partition);//作事件监听
isSearchSuccess=false;
} else {
lisenter.onSearchError(id);//作事件监听
}
}
//分配
private void allocate() {
Job job = lisenter.getJob();//得到作业对象
for (PartBlock block : partition.getBlocks()) {
if (block.getLength() >= job.getLength() && block.getState().equals(Partition.NOT_ALLOCATE)) {//如果存在未分配并且比作业申请的内存大小大的内存块
PartBlock newBlock = new PartBlock();
newBlock.setJobId(job.getJobId());
newBlock.setLength(job.getLength());
newBlock.setStartAddress(block.getStartAddress());
newBlock.setState(Partition.HAVE_ALLOCATE);
newBlock.setEndAddress(newBlock.getStartAddress() + newBlock.getLength());
block.setStartAddress(block.getStartAddress() + job.getLength());
block.setLength(block.getLength() - job.getLength());
partition.getBlocks().add(newBlock);
isAllocateSuccess = true;
break;
}
}
if (!isAllocateSuccess) {
lisenter.onOutOfMemory();//作事件监听
} else {
sortByAddress(partition.getBlocks());//按起始地址牌下序
lisenter.onAllocateSuccess(partition);//作事件监听
isAllocateSuccess = false;
}
}
//最先适应算法
public void allocteByFirstFit() {
while (true) {
operate = lisenter.onGetOperate();
switch (operate) {
case ALLOCATE:
sortByAddress(partition.getBlocks());
allocate();
break;
case RETRIVE:
retrieve();
break;
default:
break;
}
}
}
//最优适应算法
public void allocteByBestFit() {
while (true) {
operate = lisenter.onGetOperate();
switch (operate) {
case ALLOCATE:
sortByLengthDown(partition.getBlocks());
allocate();
break;
case RETRIVE:
retrieve();
break;
default:
break;
}
}
}
//最坏适应算法
public void allocteByBadestFit() {
while (true) {
operate = lisenter.onGetOperate();
switch (operate) {
case ALLOCATE:
sortByLengthUp(partition.getBlocks());
allocate();
break;
case RETRIVE:
retrieve();
break;
default:
break;
}
}
}
//按地址由小到大排序
private void sortByAddress(List blocks) {
Collections.sort(partition.getBlocks(), new Comparator() {
@Override
public int compare(PartBlock o1, PartBlock o2) {
// TODO Auto-generated method stub
if (o1.getStartAddress() > o2.getStartAddress()) {
return 1;
} else if (o1.getStartAddress() < o2.getStartAddress()) {
return -1;
}
return 0;
}
});
}
//按内存大小由小到大排序
private void sortByLengthDown(List blocks) {
Collections.sort(partition.getBlocks(), new Comparator() {
@Override
public int compare(PartBlock o1, PartBlock o2) {
// TODO Auto-generated method stub
if (o1.getLength() > o2.getLength()) {
return 1;
} else if (o1.getLength() < o2.getLength()) {
return -1;
}
return 0;
}
});
}
//按内存大小由大到小排序
private void sortByLengthUp(List blocks) {
Collections.sort(partition.getBlocks(), new Comparator() {
@Override
public int compare(PartBlock o1, PartBlock o2) {
// TODO Auto-generated method stub
if (o1.getLength() < o2.getLength()) {
return 1;
} else if (o1.getLength() > o2.getLength()) {
return -1;
}
return 0;
}
});
}
//执行,也是起点
public void excute() {
method=lisenter.onGetMethod();
switch (method) {
case FIRST_FIT:
allocteByFirstFit();
break;
case BEST_FIT:
allocteByBestFit();
break;
case BAD_FIT:
allocteByBadestFit();
break;
default:
break;
}
}
}
Job.java:
package com.chengshijian.operatesystem;
/**
* Created by ChengShiJian on 2017/11/08.
*
* 作业类,对作业的一个封装
*/
public class Job {
private int jobId;//作业id
private int length;//作业长度
public int getJobId() {
return jobId;
}
public void setJobId(int jobId) {
this.jobId = jobId;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
}
OnExcuteLisenter.java:
package com.chengshijian.operatesystem;
/**
* Created by ChengShiJian on 2017/11/08.
*
* 执行事件监听器接口
*
*/
public interface OnExecuteLisenter {
Job getJob();//获取作业
int getJobId();//获取作业id
int onGetMethod();//获取算法
int onGetOperate();//获取操作,指分配还是回收
void onSearchError(int id);//当查找失败时,指在回收内存没有找到指定id的内存块时
void onOutOfMemory();//当内存不足,指作业请求的内存大小太大,剩余内存不足以分配时
void onAllocateSuccess(Partition partition);//当分配内存成功时
void onRetrieveSuccess(Partition partition);//当回收内存成功时
}
PartBlock.java:
package com.chengshijian.operatesystem;
/**
* Created by ChengShiJian on 2017/11/08.
*
* 内存块类
*/
public class PartBlock {
private int startAddress;//起始地址
private int endAddress;//终点地址
private int length;//内存块大小
private String state;//内存块状态,已分配还是未分配
private int jobId;//作业id
public int getEndAddress() {
return this.endAddress;
}
public void setEndAddress(int endAddress) {
this.endAddress = endAddress;
}
public PartBlock() {
super();
// TODO Auto-generated constructor stub
}
public PartBlock(int startAddress, int length, String state) {
super();
this.startAddress = startAddress;
this.length = length;
this.state = state;
this.endAddress=this.startAddress+this.length;
}
public int getStartAddress() {
return startAddress;
}
public void setStartAddress(int startAddress) {
this.startAddress = startAddress;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public int getJobId() {
return jobId;
}
public void setJobId(int jobId) {
this.jobId = jobId;
}
@Override
public String toString() {
return "PartBlock [startAddress=" + startAddress + ", endAddress=" + endAddress + ", length=" + length
+ ", state=" + state + ", jobId=" + jobId + "]";
}
}
Partition.java:
package com.chengshijian.operatesystem;
/**
* Created by ChengShiJian on 2017/11/08.
*
* 内存类,核心实质上用来存内存块
*/
import java.util.ArrayList;
import java.util.List;
public class Partition {
public static final String HAVE_ALLOCATE="已分配";
public static final String NOT_ALLOCATE="未分配";
private List blocks=new ArrayList<>();
public int length=1000;
public List getBlocks() {
return blocks;
}
public void setBlocks(List blocks) {
this.blocks = blocks;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public Partition() {
super();
// TODO Auto-generated constructor stub
blocks.add(new PartBlock(0,length,NOT_ALLOCATE));
}
public Partition(int length) {
super();
blocks.add(new PartBlock(0,length,NOT_ALLOCATE));
}
}