import java.util.*;
class VirMM {
// 物理内存的总块数,假设为35
private static final int TOTAL_BLOCKS = 1;
private static final int MAX_PAGES = 1;
private int[] memory;
// 进程队列,用于存储所有创建的进程
public Queue<PCB> processQueue;
// 构造方法,初始化物理内存和进程队列
public VirMM() {
for(int i=0;i<5;i++)
lru[i]=new LRU();
this.memory = new int[TOTAL_BLOCKS]; // 创建物理内存数组
Arrays.fill(this.memory, -1); // 将所有元素初始化为-1,表示空闲
this.frequency = new int[TOTAL_BLOCKS]; // 创建访问频率数组
Arrays.fill(this.frequency, 0); // 将所有元素初始化为0
this.time = new long[TOTAL_BLOCKS]; // 创建访问时间数组
Arrays.fill(this.time, 0); // 将所有元素初始化为0
this.order = new int[TOTAL_BLOCKS]; // 创建入队顺序数组
Arrays.fill(this.order, 0); // 将所有元素初始化为0
this.processQueue = new LinkedList<>(); // 创建进程队列
}
// 创建进程,分配基本物理块,插入就绪队列
public void createProcess(int pid, int pages, int arrivetime, int worktime) {
PCB pcb = new PCB(pid, pages, arrivetime, worktime);
//allocateBlocks(pcb);
processQueue.add(pcb);
System.out.println("进程" + pid + "已创建");
}
public void sortProcessQueueByArrivalTime() {
List<PCB> tempList = new ArrayList<>(processQueue);
//因为只能对列表进行排序,所以我们先转化形成列表,然后对列表进行排序,然后把列表的元素给队列
Collections.sort(tempList, new Comparator<PCB>() {
@Override
public int compare(PCB pcb1, PCB pcb2) {
return pcb1.getArrivetime() - pcb2.getArrivetime();
}
});
processQueue.clear();
processQueue.addAll(tempList);
}
public void executeProcessQueue() {
。。。。自己需要执行的。。。。
}
private int [][] createPageTable(PCB pcb) {
int[][] pageTable = new int[pcb.getPages()][2]; // 页表数组,每个项包含逻辑页号和对应的物理页框号
for (int i = 0; i < pcb.getPages(); i++) {
int logicalPage = i; // 逻辑页号
int physicalBlock = pcb.getBlocks()[i]; // 物理页框号
pageTable[i][0] = logicalPage; // 设置逻辑页号
pageTable[i][1] = physicalBlock; // 设置物理页框号
}
return pageTable;
}
int t=0;
// 选择进程调度并执行
public void Execute() {
if (processQueue.isEmpty()) {
System.out.println("没有可执行的进程");
return;
}
while (!processQueue.isEmpty()) {
PCB currentProcess = processQueue.peek();
currentProcess.setState(1); // 设置进程状态为运行
System.out.println("进程" + currentProcess.getPid() + "开始执行");
boolean isBlocked = false;
while (!currentProcess.isFinished()) {
int currentAddress = currentProcess.getCurrentAddress();
int page = getPageNumber(currentAddress);
int offset = getOffset(currentAddress);
int block = currentProcess.getBlocks()[page];
System.out.println("进程页号" + page + "物理块号" + block);
if (block == -1) { // 如果当前页没有分配物理块,调用页面置换
System.out.println("进程" + currentProcess.getPid() + "被阻塞,执行下一个进程");
processQueue.offer(currentProcess); // 将被阻塞的进程重新加入队列末尾
pageFault(currentProcess, page);
block = currentProcess.getBlocks()[page];
isBlocked = true;
break;
}
lru[currentProcess .getPid()].pushlru(page);
int physicalAddress = getPhysicalAddress(block, offset);
System.out.println("进程" + currentProcess.getPid() + "访问逻辑地址" + currentAddress +
",对应物理地址为" + physicalAddress);
// 更新页面置换算法相关数据
currentProcess.step(); // 更新地址
}
// if (!isBlocked) {
// currentProcess.setState(3); // 设置进程状态为结束
//System.out.println("进程" + currentProcess.getPid() + "执行完毕");
// 释放进程占用的物理块
//releaseBlocks(currentProcess);
// 从就绪队列中移除当前执行完毕的进程
processQueue.poll();
}
}
//}
// 获取页号
private int getPageNumber(int address) {
return address >>> 10;
}
//逻辑地址是由进程生成的地址,而物理地址是实际映射到物理内存中的地址。逻辑地址空间通常被划分为固定大小的页(Page),而物理内存也被划分为相同大小的页框(Page Frame)。
// 获取偏移量
private int getOffset(int address) {
return address & 0b1111111111;
}//保留地址的低10位(二进制表示为10个1),并将其他位设置为0。这样做的目的是提取出地址的低10位,即偏移量部分。
// 获取物理地址
private int getPhysicalAddress(int block, int offset) {
return (block << 10) | offset;
}