内存乾坤大挪移:用Java实现操作系统的分页魔法

操作系统核心机制:分页存储是操作系统内存管理的基石,代码实现将抽象概念(如虚拟内存、页表、缺页中断)具体化,帮助理解操作系统底层如何工作。解决实际问题:展示了如何通过分页管理解决内存碎片化问题,实现物理内存的高效利用。

以下是使用 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);
    }
}

关键要素说明:

  1. 地址结构

    • 32位逻辑地址,高16位为页号,低16位为偏移量(可配置)

    • 页面大小可配置(示例使用4KB)

  2. 页表管理

    • 使用PageTableEntry记录物理页号、有效位、脏位等

    • 页表按虚拟页号索引

  3. 物理内存管理

    • 维护空闲页框队列

    • 处理页框分配与回收

    • 页面置换框架(需实现具体算法)

  4. 地址转换过程

    • 提取页号和偏移量

    • 检查页表项有效性

    • 处理缺页中断

    • 组合物理地址

  5. 缺页处理

    • 分配物理页框

    • 从"磁盘"加载数据(示例中为模拟)

    • 更新页表

  6. 页面置换

    • 示例包含置换框架(需实现具体算法如FIFO/LRU)

扩展建议:

  1. 实现完整页面置换算法:

// 在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;
    }
}
  1. 添加完整的磁盘模拟:

class DiskStorage {
    private byte[][] sectors; // 模拟磁盘块

    public void readPage(int pageNumber, byte[] frameBuffer) {
        System.arraycopy(sectors[pageNumber], 0, 
                         frameBuffer, 0, frameBuffer.length);
    }
}
  1. 增强地址转换验证:

private int getPageNumber(int logicalAddress) {
    if (logicalAddress < 0) {
        throw new IllegalArgumentException("Invalid logical address");
    }
    return (logicalAddress / pageSize);
}

这个示例展示了分页存储管理的核心机制,实际实现需要考虑更多细节如:

多级页表支持

页面共享机制

内存保护位

TLB快表加速

更复杂的置换算法实现

完整的磁盘I/O模拟

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值