操作系统核心机制:分页存储是操作系统内存管理的基石,代码实现将抽象概念(如虚拟内存、页表、缺页中断)具体化,帮助理解操作系统底层如何工作。解决实际问题:展示了如何通过分页管理解决内存碎片化问题,实现物理内存的高效利用。
以下是使用 Java 描述分页存储管理方式的代码示例,包含内存分页、页表管理和地址转换逻辑:
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Queue;
// 页表项定义
class PageTableEntry {
int physicalPage; // 物理页号
boolean valid; // 有效位
boolean dirty; // 脏位
boolean referenced; // 访问位
public PageTableEntry() {
this.physicalPage = -1;
this.valid = false;
this.dirty = false;
this.referenced = false;
}
}
// 页表管理
class PageTable {
private PageTableEntry[] entries;
private int pageSize; // 页面大小(字节)
private int pageCount; // 总页数
public PageTable(int virtualPages, int pageSize) {
this.pageSize = pageSize;
this.pageCount = virtualPages;
this.entries = new PageTableEntry[virtualPages];
for (int i = 0; i < virtualPages; i++) {
entries[i] = new PageTableEntry();
}
}
public PageTableEntry getEntry(int pageNumber) {
if (pageNumber >= pageCount) {
throw new IllegalArgumentException("Invalid page number");
}
return entries[pageNumber];
}
}
// 物理内存管理
class PhysicalMemory {
private int frameCount; // 物理页框总数
private int pageSize; // 页面大小
private Queue<Integer> freeFrames; // 空闲页框队列
private HashMap<Integer, Integer> frameMap; // 页框占用映射(帧号→进程页号)
public PhysicalMemory(int totalFrames, int pageSize) {
this.frameCount = totalFrames;
this.pageSize = pageSize;
this.freeFrames = new LinkedList<>();
this.frameMap = new HashMap<>();
// 初始化所有页框为空闲
for (int i = 0; i < frameCount; i++) {
freeFrames.add(i);
}
}
// 分配物理页框(使用FIFO页面置换)
public int allocateFrame(int pageNumber) {
if (!freeFrames.isEmpty()) {
int frame = freeFrames.poll();
frameMap.put(frame, pageNumber);
return frame;
} else {
// 实现页面置换(这里简单返回-1,实际需要置换算法)
return -1; // 需要扩展为实际置换逻辑
}
}
public void freeFrame(int frame) {
freeFrames.add(frame);
frameMap.remove(frame);
}
}
// 分页存储管理系统
class PagingSystem {
private PageTable pageTable;
private PhysicalMemory physicalMemory;
private int pageSize; // 页面大小(字节)
public PagingSystem(int virtualPages, int physicalFrames, int pageSize) {
this.pageSize = pageSize;
this.pageTable = new PageTable(virtualPages, pageSize);
this.physicalMemory = new PhysicalMemory(physicalFrames, pageSize);
}
// 地址转换:将逻辑地址转换为物理地址
public int translateAddress(int logicalAddress) {
int pageNumber = getPageNumber(logicalAddress);
int offset = getOffset(logicalAddress);
PageTableEntry entry = pageTable.getEntry(pageNumber);
if (!entry.valid) {
handlePageFault(pageNumber); // 处理缺页中断
}
entry.referenced = true;
int physicalAddress = (entry.physicalPage * pageSize) + offset;
return physicalAddress;
}
// 处理缺页中断
private void handlePageFault(int pageNumber) {
System.out.println("Page fault occurred for page: " + pageNumber);
// 分配新的物理页框
int frame = physicalMemory.allocateFrame(pageNumber);
if (frame == -1) {
frame = performPageReplacement(); // 执行页面置换
}
// 更新页表
PageTableEntry entry = pageTable.getEntry(pageNumber);
entry.physicalPage = frame;
entry.valid = true;
// 从磁盘加载页面到内存(此处模拟加载过程)
loadPageFromDisk(pageNumber, frame);
}
// 从磁盘加载页面(模拟实现)
private void loadPageFromDisk(int pageNumber, int frame) {
System.out.println("Loading page " + pageNumber + " to frame " + frame);
// 实际实现需要访问磁盘数据
}
// 执行页面置换(示例使用FIFO)
private int performPageReplacement() {
// 需要实现具体置换算法
// 此处返回第一个物理页框作为示例
return 0;
}
// 从逻辑地址提取页号
private int getPageNumber(int logicalAddress) {
return (logicalAddress & 0xFFFF0000) >>> 16; // 假设高16位为页号
}
// 从逻辑地址提取偏移量
private int getOffset(int logicalAddress) {
return logicalAddress & 0x0000FFFF; // 低16位为偏移
}
}
// 使用示例
public class Main {
public static void main(String[] args) {
// 创建分页系统:64个虚拟页,32个物理页框,4KB页面
PagingSystem paging = new PagingSystem(64, 32, 4096);
// 模拟地址转换
int logicalAddress = 0x00051234; // 页号=5,偏移=0x1234
int physicalAddress = paging.translateAddress(logicalAddress);
System.out.printf("Logical: 0x%08X → Physical: 0x%08X\n",
logicalAddress, physicalAddress);
}
}
关键要素说明:
-
地址结构:
-
32位逻辑地址,高16位为页号,低16位为偏移量(可配置)
-
页面大小可配置(示例使用4KB)
-
-
页表管理:
-
使用PageTableEntry记录物理页号、有效位、脏位等
-
页表按虚拟页号索引
-
-
物理内存管理:
-
维护空闲页框队列
-
处理页框分配与回收
-
页面置换框架(需实现具体算法)
-
-
地址转换过程:
-
提取页号和偏移量
-
检查页表项有效性
-
处理缺页中断
-
组合物理地址
-
-
缺页处理:
-
分配物理页框
-
从"磁盘"加载数据(示例中为模拟)
-
更新页表
-
-
页面置换:
-
示例包含置换框架(需实现具体算法如FIFO/LRU)
-
扩展建议:
-
实现完整页面置换算法:
// 在PhysicalMemory中添加置换算法实现
class PhysicalMemory {
// 添加LRU实现示例
private LinkedHashMap<Integer, Integer> lruCache;
public int allocateFrameLRU(int pageNumber) {
if (!freeFrames.isEmpty()) {
return freeFrames.poll();
}
// 找到最近最久未使用的页框
int lruFrame = lruCache.entrySet().iterator().next().getKey();
freeFrame(lruFrame);
return lruFrame;
}
}
-
添加完整的磁盘模拟:
class DiskStorage {
private byte[][] sectors; // 模拟磁盘块
public void readPage(int pageNumber, byte[] frameBuffer) {
System.arraycopy(sectors[pageNumber], 0,
frameBuffer, 0, frameBuffer.length);
}
}
-
增强地址转换验证:
private int getPageNumber(int logicalAddress) {
if (logicalAddress < 0) {
throw new IllegalArgumentException("Invalid logical address");
}
return (logicalAddress / pageSize);
}
这个示例展示了分页存储管理的核心机制,实际实现需要考虑更多细节如:
多级页表支持
页面共享机制
内存保护位
TLB快表加速
更复杂的置换算法实现
完整的磁盘I/O模拟
2万+

被折叠的 条评论
为什么被折叠?



