页式地址重定位模拟(JAVA语言)

  • Post author:
  • Post category:java



实验内容及步骤:


1.用户输入内存大小(单位GB),系统把内存分块,每块大小由用户输入设置,单位为KB,按字节寻址(B),也就是一个地址对应一个字节的大小

2.用户输入进程大小(单位KB)

3.为进程设置一个页表(页号,块号(块号的分配由系统随机产生)(先检查块号是否已经分配出去))

4.用户输入逻辑地址,

页号=255/页面大小 取整

页内偏移量=255%页面大小 取余 KB 注意单位,KB和B

物理地址=所在块号

页面大小

1024 + 业内偏移量 B


代码实现

package com.os;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Scanner;

import sun.applet.Main;

public class Test {
	/*
 用户输入内存大小(单位GB),系统把内存分块,每块大小由用户输入设置,单位为KB,按字节寻址(B),也就是一个地址对应一个字节的大小

用户输入进程大小(单位KB)
为进程设置一个页表(页号,块号(块号的分配由系统随机产生)(先检查块号    是否已经分配出去))

用户输入逻辑地址,
页号=255/页面大小 取整
页内偏移量=255%页面大小 取余  KB               注意单位,KB和B
物理地址=所在块号*页面大小*1024 + 业内偏移量  B

	 * 
	 * */
	
	public static void main(String[] args) {
		Random random = new Random();
		Scanner scanner = new Scanner(System.in);
		//寻址单位为字节B
		//一个内存块有4KB * 1024 个地址
		
		//用户自定义内存大小,单位为GB
		System.out.println("请输入内存大小(单位为GB):");
				
		//memorySize:内存大小(用户输入,必须整数)
		int memorySize = scanner.nextInt();
		
		System.out.println("请设置页面大小(单位KB):");
		//memoryBlockSize一个内存块大小(单位为KB)
		int memoryBlockSize = scanner.nextInt();
		System.out.println("系统内存块(页面)大小为" + memoryBlockSize + "KB,寻址单位为字节B");
		
		//系统把内存分块,每块物理内存大小为memoryBlockSize KB
		//memoryBlockCount:内存块数 = 内存大小(GB) * 1024(MB) * 1024(KB) / memoryBlockSize KB
		int memoryBlockCount = (memorySize * 1024 * 1024) / memoryBlockSize;
		System.out.println("内存大小为:" + memorySize + "GB," + "一个内存块大小为:" + memoryBlockSize + "KB,共分为:" + memoryBlockCount + "个内存块。");
		
		//定义一个数组haveBeenUsedMemoryBlockNum,用来存储已经分配出去的内存块号,这样就可以在后面的随机分配内存块号时,把已经分配的内存块剔除出去
		
		//每分配出去一个内存块,就把块号存储到haveBeenUsedMemoryBlockNum数组中
		ArrayList<Integer> haveBeenUsedMemoryBlockNum = new ArrayList<Integer>();
		
//		//progressSice :进程大小,用户输入进程大小
		
		System.out.println("请输入进程大小(单位为KB):");
		//进程大小 用户输入,单位为KB
		int progressSice = scanner.nextInt();
		
		//页面数量:进程大小 % 页面大小 = 0 ? 进程大小 / 页面大小 : 进程大小 / 页面大小 + 1
		int progressPageCount = progressSice % memoryBlockSize == 0 ? progressSice / memoryBlockSize : progressSice / memoryBlockSize + 1;
		
		//页号数组 progressPageNumberList
		int[] progressPageNumberList = new int[progressPageCount];
		//存储页号
		for (int i = 0; i < progressPageCount; i++) {
			progressPageNumberList[0] = i;
		}
		
		//HashMap类型集合,存储进程页号和块号的分配情况(页表)
		Map<Integer, Integer> pageNumToBlockNum = new HashMap<Integer, Integer>();
		//为每一页随机分配一个内存块号,内存块号的范围为0~memoryBlockCount-1
		for (int i = 0; i < progressPageNumberList.length; i++) {
			//产生一个随机数,表示随机产生的块号,这个数要和haveBeenUsedMemoryBlockNum中的数字进行比较,如果没有,就存储进去并分配给当前页号,如果已经存在,则重新生成一个随机块号
			int randomBlockNum = random.nextInt(memoryBlockCount);//里面的值为内存块数,范围是0~memoryBlockCount-1
			//判断生成的数字是否存在haveBeenUsedMemoryBlockNum中
			if (haveBeenUsedMemoryBlockNum.size() == 0) {
				haveBeenUsedMemoryBlockNum.add(randomBlockNum);
			}else {
				//递归判断存储已经分配出去的内存块号集合haveBeenUsedMemoryBlockNum中是否已经存在刚随机产生的内存块号,如果存在,重新生成
				randomBlockNum = HaveBeenUsedMemoryToBlockNum(haveBeenUsedMemoryBlockNum, randomBlockNum, random, memoryBlockCount);
			}
			
			//把页号i和分配给它的块号randomBlockNum添加到pageNumToBlockNum中
			pageNumToBlockNum.put(i, randomBlockNum);//key值是页号,value值是内存块号
		}
		
		System.out.println("页表:");
		System.out.println("页号----块号");
		for (Entry<Integer, Integer>entry : pageNumToBlockNum.entrySet()) {
			System.out.println(entry.getKey() + "---->" + entry.getValue());
		}
		
		//用户输入要寻址的逻辑地址(B)
		System.out.println("请输入要查询的逻辑地址:");
		int logicAddress = scanner.nextInt();
		//判断逻辑地址是否超过进程的大小
		//如果超过,提示用户,并重新输入
		logicAddress = LogicAddress(logicAddress, progressSice, scanner);
		//计算逻辑地址所在页号 逻辑地址/(页面大小memoryBlockSize KB * 1024)
		int logicAddressPageNum = logicAddress / (memoryBlockSize * 1024);
		//根据页号,取出当前页号所在的块号
		int pageNumOfBlockNum = pageNumToBlockNum.get(logicAddressPageNum);
		//计算逻辑地址页内偏移量 逻辑地址 % (页面大小memoryBlockSize KB * 1024)
		int pageOffset = logicAddress % (memoryBlockSize * 1024);
		
		//计算物理地址 memoryBlockSize * 1024 * 块号 + 页内偏移量
		long physicalAddress = pageNumOfBlockNum * memoryBlockSize * 1024 + pageOffset;
		System.out.println("逻辑地址:" + logicAddress + "\n所在页号为:" + logicAddressPageNum + "\n页内偏移量为:" + pageOffset + "\n所在块号为:" + pageNumOfBlockNum + "\n物理地址为:" + physicalAddress);
	}
	
	//递归判断存储已经分配出去的内存块号集合haveBeenUsedMemoryBlockNum中是否已经存在刚随机产生的内存块号,如果存在,重新生成
	public static int HaveBeenUsedMemoryToBlockNum(ArrayList<Integer> haveBeenUsedMemoryBlockNum, int randomBlockNum, Random random, int memoryBlockCount){
		int count = 0;
		for (int j = 0; j < haveBeenUsedMemoryBlockNum.size(); j++) {
			if (haveBeenUsedMemoryBlockNum.get(j) == randomBlockNum) {
				//已分配块号中没有产生的随机块号,添加进去
//				haveBeenUsedMemoryBlockNum.add(randomBlockNum);
				count++;
			}else {
				continue;
			}
		}
		if (count == 0) {
			//说明集合中没有
			//已分配块号中没有产生的随机块号,添加进去
			haveBeenUsedMemoryBlockNum.add(randomBlockNum);
		}else {
			//已分配块号中有产生的随机块号,重新生成一个
			randomBlockNum = random.nextInt(memoryBlockCount);
			//重新检测
			HaveBeenUsedMemoryToBlockNum(haveBeenUsedMemoryBlockNum, randomBlockNum, random, memoryBlockCount);
		}
		return randomBlockNum;
	}
	
	//判断逻辑地址是否超过进程的大小
	//如果超过,提示用户,并重新输入
	public static int LogicAddress(int logicAddress, int progressSice, Scanner scanner){
		if (logicAddress > progressSice * 1024) {
			//判断逻辑地址是否超过进程的大小
			//如果超过,提示用户,并重新输入
			System.out.println("数值越界,请重新输入!");
			logicAddress = scanner.nextInt();
			logicAddress = LogicAddress(logicAddress, progressSice, scanner);
		}
		return logicAddress;
	}
}


实验结果


在这里插入图片描述



版权声明:本文为qq_42444651原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。