(操作系统实验)(内存管理、分配与回收模拟实验---可变分区方式)

简要介绍及前提假设

学习操作系统存储管理这一章节后,我们都很清楚可变分区是内存管理中一种比较好的策略,是后续虚拟存储技术的基础。所以做这个模拟用可变分区的方式管理内存的实验。

内存管理方法介绍
本实验模拟的是用可变分区的方式管理内存的,使用两张表来管理内存,一张表是已经分配的内存块表,另一个张表是未分配的内存块表,这两张表构成了伙伴系统(因为他们都是针对内存的,针对同一个东西操控)。

三种内存分配算法介绍

  • (1)首次适应算法 各个空闲地址块按照首地址从小到大的顺序排列,找到第一个能够满足某程序要求空间大小的空闲块分配给该程序。
  • (2)最佳适应算法 各个空闲块按照空间地址范围大小从小到大排列,找到第一个能够满足某程序要求空间大小的空闲块分配给该程序。
  • (3)最坏适应算法 各个空闲块按照空间地址范围大小从大到小排列,找到第一个能够满足某程序要求空间大小的空闲块分配给该程序。

内存块回收算法介绍
当某程序的内存空间被释放,需要把相应的内存空间回收,该内存块由已分配状态变为未分配状态。这里需要注意的是,该内存块和原有的空闲内存块有上邻、下邻、上下邻、上下都不邻的四种情况,如有相邻,要合并。

笔者给出假设
(1)假定可以申请的内存地址空间范围是0-6000。
(2)假定初始化内存快照
在这里插入图片描述

算法设计

有上面的介绍后,我们很清楚地知道按照可变分区的方式管理内存的特点及分配内存、回收内存的算法思路。由此,很容易设计算法如下。
在这里插入图片描述

开发环境及工程文件架构

Windows10+Java8+记事本+eclipse单步调试!

在这里插入图片描述

源代码

MemoryManagement.java


import java.util.*;

public class MemoryManagement{

	public ArrayList<MemoryBlock> usedMemoryBlockList;//已分配内存块表
	public ArrayList<MemoryBlock> unusedMemoryBlockList;//未分配内存块表
	public int threshold;//门限值
	public int memoryAllocationAlgorithm;//内存分配算法。1--首次适应,2--最佳适应,3--最坏适应	
	

	public static void main(String[] args){
		Scanner scan = new Scanner(System.in);
		/*
		 *完成初始化
		*/
		MemoryManagement mm = new MemoryManagement();
		mm.init();
		mm.menu();
		System.out.print("请选择内存分配算法: ");
		mm.memoryAllocationAlgorithm = scan.nextInt();
		System.out.print("请输入门限值: ");
		mm.threshold = scan.nextInt();
		/*
		 *开始实验
		*/
		String allocateOrRecover;//分配或回收
		String programName;//程序名
		int programSize;//程序大小
		while(true){
			System.out.println("===============================================================");
			System.out.println("\n输入格式:[allocate 程序名 程序大小]或[recover 程序名]");
			allocateOrRecover = scan.next();
			if(allocateOrRecover.equals("allocate")){
				programName = scan.next();
				programSize = scan.nextInt();
				mm.runAllocate(programName, programSize);
			}else if(allocateOrRecover.equals("recover")){
				programName = scan.next();
				mm.recover(programName);
			}else{
				System.out.println("输入有误,请按照[allocate 程序名 程序大小]或[recover 程序名]格式重新输入");
			}
			System.out.println("===============================================================");
		}
		
	}

	//初始化,并打印给出某中间状况的内存快照
	public void init(){
		usedMemoryBlockList = new ArrayList<MemoryBlock>();
		unusedMemoryBlockList = new ArrayList<MemoryBlock>();
	
		usedMemoryBlockList.add(new MemoryBlock("programA",0,500));
		usedMemoryBlockList.add(new MemoryBlock("programB",5500,500));
		usedMemoryBlockList.add(new MemoryBlock("programC",2500,1500));
		usedMemoryBlockList.add(new MemoryBlock("programD",500,800));
			
		unusedMemoryBlockList.add(new MemoryBlock("unused",1300,1200));
		unusedMemoryBlockList.add(new MemoryBlock("unused",4000,1500));

		print();
	}
	//打印内存快照
	public void print(){
		//为了打印出图形化界面,这里开一个临时的ArrayList
		ArrayList<MemoryBlock> aList = new ArrayList<MemoryBlock>();
		
		//先按照内存块首址排序,之后再打印
		unusedMemoryBlockList.sort(new MyComparatorFirstAdaptation());
		usedMemoryBlockList.sort(new MyComparatorFirstAdaptation());
		System.out.println("-----------------------------------");
		System.out.println("已分配内存块表");
		System.out.println("起始地址\t大小\t程序名");
		for(int i = 0; i < usedMemoryBlockList.size(); i++){
			System.out.println(usedMemoryBlockList.get(i).getStartAddress()+"\t\t"+usedMemoryBlockList.get(i).getSize()+"\t"+usedMemoryBlockList.get(i).getState());
			aList.add(usedMemoryBlockList.get(i));
		}
		System.out.println();
		System.out.println("-----------------------------------");
		System.out.println("未分配内存块表");
		System.out.println("起始地址\t大小\t状态");
		for(int i = 0; i < unusedMemoryBlockList.size(); i++){
			System.out.println(unusedMemoryBlockList.get(i).getStartAddress()+"\t\t"+unusedMemoryBlockList.get(i).getSize()+"\t"+unusedMemoryBlockList.get(i).getState());
			aList.add(unusedMemoryBlockList.get(i));
		}
		System.out.println("-----------------------------------");
		System.out.println();
		
		System.out.println("图形化如下");
		aList.sort(new MyComparatorFirstAdaptation());
		for(int i = 0;i < aList.size();i++) {
			System.out.printf("%10d ------------------\n",aList.get(i).getStartAddress());
			boolean first = true;
			for(int j=0;j<(aList.get(i).getSize()+1000)/1000;j++) {
				
				if(first){
					System.out.println("          |                 |"+aList.get(i).getState());
					
					first = false;
				}else{
					System.out.println("          |                 |");
				}
			}
			if(aList.get(i).getStartAddress()+aList.get(i).getSize() == 6000){
				System.out.printf("%10d ------------------\n",aList.get(i).getStartAddress()+aList.get(i).getSize());
			}
		}
		
	}
	//内存分配
	public void runAllocate(String programName,  int programSize){
		boolean flag = false;//如果没有找到满足的内存块
		switch(memoryAllocationAlgorithm){
			case 1:
				unusedMemoryBlockList.sort(new MyComparatorFirstAdaptation());
				break;
			case 2:
				unusedMemoryBlockList.sort(new MyComparatorBestAdaptation());
				break;
			case 3:
				unusedMemoryBlockList.sort(new MyComparatorWorstAdaptation());
				break;
		}
		for(int i = 0 ; i < unusedMemoryBlockList.size(); i++){
			MemoryBlock mbTmp = unusedMemoryBlockList.get(i);
			if(mbTmp.getSize() >= programSize){
				
				flag = true;
				if(mbTmp.getSize() - programSize <= threshold){
					usedMemoryBlockList.add(new MemoryBlock(programName, mbTmp.getStartAddress(), mbTmp.getSize()));
					
				}else{
					usedMemoryBlockList.add(new MemoryBlock(programName, mbTmp.getStartAddress(), programSize));
					unusedMemoryBlockList.add(new MemoryBlock("unused",mbTmp.getStartAddress()+programSize,mbTmp.getSize() - programSize));
				}
				unusedMemoryBlockList.remove(i);
				break;
			}
		}
		if(flag == false){
			System.out.println("没有空闲块可以满足。。");
		}
		print();
	}
	
	//回收
	public void recover(String programName){
		usedMemoryBlockList.sort(new MyComparatorFirstAdaptation());
		unusedMemoryBlockList.sort(new MyComparatorFirstAdaptation());
		boolean flag = false;
		int loc=0;
		for(int i = 0; i < usedMemoryBlockList.size(); i++){
			if(usedMemoryBlockList.get(i).getState().equals(programName)){
				flag = true;
				loc = i;
				break;
			}
		}
		//如果没找到这个程序,就报告没有该程序,无法回收
		if(flag == false){
			System.out.println("找不到该程序,无法回收该程序。。");
		}else{
			MemoryBlock mbTmp = usedMemoryBlockList.get(loc);
			//先判断上邻、下邻、上下邻、上下都不邻
			boolean up = false;
			boolean down = false;
			int upLoc=0, downLoc=0;
			for(int j = 0; j < unusedMemoryBlockList.size(); j++){
				if(mbTmp.getStartAddress() == unusedMemoryBlockList.get(j).getStartAddress()+unusedMemoryBlockList.get(j).getSize()){
					upLoc = j;
					up = true;
				}
				if(mbTmp.getStartAddress() + mbTmp.getSize()== unusedMemoryBlockList.get(j).getStartAddress()){
					downLoc = j;
					down = true;
				}
			}
			if(up==true && down ==true){
				MemoryBlock mb = new MemoryBlock("unused",unusedMemoryBlockList.get(upLoc).getStartAddress(),mbTmp.getSize()+unusedMemoryBlockList.get(upLoc).getSize()+unusedMemoryBlockList.get(downLoc).getSize());
				
				usedMemoryBlockList.remove(loc);
				unusedMemoryBlockList.remove(upLoc);//删除了upLoc,导致数组个数少1
				unusedMemoryBlockList.remove(downLoc-1);//由于数组个数少1,这里注意是downLoc-1
				unusedMemoryBlockList.add(mb);
				
			}else if(up == true && down == false){
				unusedMemoryBlockList.add(new MemoryBlock("unused",unusedMemoryBlockList.get(upLoc).getStartAddress(),mbTmp.getSize()+unusedMemoryBlockList.get(upLoc).getSize()));
				usedMemoryBlockList.remove(loc);
				unusedMemoryBlockList.remove(upLoc);
			}else if(up == false && down == true){
				unusedMemoryBlockList.add(new MemoryBlock("unused",mbTmp.getStartAddress(),mbTmp.getSize()+unusedMemoryBlockList.get(downLoc).getSize()));
				usedMemoryBlockList.remove(loc);
				unusedMemoryBlockList.remove(downLoc);
			}else{
				unusedMemoryBlockList.add(new MemoryBlock("unused",mbTmp.getStartAddress(),mbTmp.getSize()));
				usedMemoryBlockList.remove(loc);
				
			}
		}
		print();
	}

	//用户选择菜单
	public void menu(){
		System.out.println("*******************menu*******************");
		System.out.println("1-----------------首次适应");
		System.out.println("2-----------------最佳适应");
		System.out.println("3-----------------最坏适应");
		System.out.println();
	}

	//自定义排序比较器
	class MyComparatorFirstAdaptation implements Comparator<MemoryBlock>{
		public int compare(MemoryBlock mb1, MemoryBlock mb2){
			return mb1.getStartAddress() - mb2.getStartAddress();
		}
	}
	class MyComparatorBestAdaptation implements Comparator<MemoryBlock>{
		public int compare(MemoryBlock mb1, MemoryBlock mb2){
			return mb1.getSize() - mb2.getSize();
		}
	}
	class MyComparatorWorstAdaptation implements Comparator<MemoryBlock>{
		public int compare(MemoryBlock mb1, MemoryBlock mb2){
			return mb2.getSize() - mb1.getSize();
		}
	}
}

MemoryBlock.java

public class MemoryBlock{
	private int startAddress;//内存块起始地址	
	private int size;//内存块大小
	private String state;//内存块状态,要么是未分配,要么是程序名

	public MemoryBlock(){}

	public MemoryBlock(String programName, int startAddress, int size){
		this.state = programName;
		this.startAddress = startAddress;
		this.size = size;
	}

	public void setStartAddress(int startAddress){
		this.startAddress = startAddress;
	}
	public int getStartAddress(){
		return this.startAddress;
	}
	public void setSize(int size){
		this.size = size;
	}
	public int getSize(){
		return this.size;
	}
	public void setState(String programName){
		this.state = programName;
	}
	public String getState(){
		return this.state;
	}


	public String toString(){
		return ("[state: "+state+", startAddress: "+startAddress+", size: "+size+"]");
	}
	//测试
	public static void main(String[] args){
		MemoryBlock mb = new MemoryBlock();
		mb.setStartAddress(1000);
		mb.setSize(200);
		mb.setState("p1");
		System.out.println(mb.getStartAddress());
		System.out.println(mb.getSize());
		System.out.println(mb.getState());
		System.out.println(mb.toString());

		System.out.println(new MemoryBlock("programName", 2000, 1000));
	}
}

实验结果

(1)最佳适应算法及门界限值实验结果
在这里插入图片描述
(2)最坏适应算法实验结果
在这里插入图片描述
(3)首次适应算法及上下均无相邻回收内存实验结果
在这里插入图片描述
(4)上邻、下邻、上下邻回收内存实验结果
在这里插入图片描述

反思总结

笔者刚开始开发的时候用的是记事本,一直有个bug,不知怎么回事!回收programC程序老是错误。为之奈何?为之奈何?此刻想起了eclipse,利用单步调试,利用单步调试,很容易会发现问题,找到了问题,原来是增加或删除ArrayList的元素后,导致元素总数增加/减少,再去删除原来搜索到的那个ArrayList的第i个元素,可能已经变了。。。

不要老是用记事本了,记得还是用调试工具来的块些啊。。。

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值