实验内容及步骤:
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 版权协议,转载请附上原文出处链接和本声明。