美文网首页
手写操作系统 - 实现虚拟内存管理

手写操作系统 - 实现虚拟内存管理

作者: 红橙Darren | 来源:发表于2025-10-20 17:29 被阅读0次

1、为什么需要虚拟内存

虚拟内存是现代操作系统的核心功能之一,它解决了物理内存管理的多个关键问题:
内存隔离与保护: 在没有虚拟内存的系统中,所有进程都直接访问物理内存。一个进程的错误操作可能破坏其他进程甚至操作系统的数据。虚拟内存为每个进程提供独立的地址空间,实现真正的进程隔离。
简化内存管理:程序员无需关心物理内存的实际布局。每个进程都拥有从0开始的连续地址空间,编译器链接器可以生成固定的内存布局。
突破物理内存限制:通过分页机制,可以将暂时不用的内存页换出到磁盘,当需要时再换入,使得程序可以使用比实际物理内存更大的地址空间。
高效的内存共享:不同的进程可以映射到相同的物理页,实现代码和数据的共享,如共享库机制。

2、如何实现虚拟内存

虚拟内存的核心实现机制是分页。x86 架构 32 位采用二级页表结构:
虚拟地址: 程序使用的地址,通常为32位或64位
物理地址:实际内存硬件的地址
页:内存管理的基本单位,通常为4KB
页表:存储虚拟页到物理页映射关系的数据结构
MMU:内存管理单元,负责地址转换,32 位虚拟地址分解为:
页目录索引(10位)
页表索引(10位)
页内偏移(12位)
CPU 通过 CR3 寄存器定位页目录,经过二级查表将虚拟地址转换为物理地址。

MMU工作流程

3、手写实现虚拟内存管理

static page_mapping_table_t* find_create_page_mapping_table(page_mapping_dir_t* page_dir, void* virtual_addr) {
    page_mapping_dir_t* target_page_dir = (page_dir + PDE_INDEX(virtual_addr));
    page_mapping_table_t* target_page_table = nullptr;
    if (target_page_dir->present) {
        // 大部分同学可能都看不懂
        target_page_table = (page_mapping_table_t*)(target_page_dir->phy_pt_addr << 12);
    } else {
        target_page_table = alloc_a_page();
        target_page_dir->present = 1;
        target_page_dir->read_write = 1; // 代码段
        target_page_dir->user_mode_acc = 0; // 只能内核访问
        target_page_dir->phy_pt_addr = (u32_t)target_page_table >> 12;
    }
    return target_page_table + PTE_INDEX(virtual_addr);
}

void create_memory_mapping(page_mapping_dir_t* page_dir, void* virtual_addr, void* physics_addr, u32_t count) {
    for (size_t i = 0; i < count; i++)
    {
        page_mapping_table_t* page_mapping_table = find_create_page_mapping_table(page_dir, virtual_addr);
        page_mapping_table->phy_page_addr = (u32_t)physics_addr >> 12;
        assert(page_mapping_table->present == 0);
        page_mapping_table->present = 1;
        page_mapping_table->read_write = 1; // 代码段
        page_mapping_table->user_mode_acc = 0; // 只能内核访问,后面再写进程加载进入用户态,会闪退
        virtual_addr += PAGE_SIZE;
        physics_addr += PAGE_SIZE;
    }
}

// 打开虚拟内存,建立内核的初始化映射
static void init_virtual_memory_mapping() {
    page_mapping_dir_t* page_table_dir = alloc_a_page();
    // 初始化先建立 4M 的内存映射,并且前 4M 的虚拟内存映射到真实(物理)内存的前 4M
    create_memory_mapping(page_table_dir, 0, 0, KERNEL_INIT_MAPPING_SIZE / PAGE_SIZE);
    // 设置 cr3 寄存器(页目录地址)
    set_cr3(page_table_dir);
    // 打开 mmu 虚拟映射硬件
    open_cr0_enable_page();
}

4、手写实现缺页异常

void do_interrupt_handler_page_fault(exception_frame_t* exception_frame) {
    printk("do_interrupt_handler_page_fault\r\n");
    // 哪一块缺页了呢?
    void* page_fault_addr = (void*)read_cr2();
    // 虚拟地址要往下对齐 4kb
    void* virtual_addr = (void*)DOWN_ON(page_fault_addr, PAGE_SIZE);
    page_mapping_dir_t* page_mapping_dir = (page_mapping_dir_t*)read_cr3();
    // 新的物理页映射地址
    void* new_physics_addr = alloc_a_page();
    create_memory_mapping(page_mapping_dir, virtual_addr, new_physics_addr, 1);
    flush_tlb(page_fault_addr);
}

5、用户进程虚拟内存管理

用户进程虚拟内存管理.png

相关文章

  • linux内核

    虚拟内存的作用? 虚拟内存的实现? 操作系统层面对内存的管理? 内存池的作用?STL里[内存池如何实现] 进程空间...

  • 什么是虚拟内存,分页、分段又是什么?

    操作系统——内存管理之内存分配(分页,分段,段页)多级页表与快表 共享内存可以用虚拟内存来实现。 共享内存的方式原...

  • MMU

    现代操作系统普遍采用虚拟内存管理( Virtual Memory Management) 机制,这需要MMU( M...

  • 请求分页管理方式

    前言 本文接着上文虚拟内存技术的实现,虚拟内存技术的三种实现:请求分页管理方式、请求分段方式、请求段页管理方式。这...

  • Linux hugetlb介绍与创建

    引言 随着计算需求规模的不断增大,应用程序对内存的需求也越来越大。为了实现虚拟内存管理机制,操作系统对内存实行分页...

  • 深入理解计算机系统

    1.6 存储设备形成层次结构 1.7 操作系统管理硬件 1.7.1进程 1.73 虚拟内存

  • Linux中MMU内存管理【进阶学习】

    前言 现代操作系统普遍采用虚拟内存管理(Virtual Memory Management)机制,这需要处理器中的...

  • 关于iOS内存优化--虚拟内存概览

    虚拟内存允许操作系统避开物理RAM的限制。虚拟内存管理器为每个进程创建一个逻辑地址空间(或者虚拟地址空间)并且将它...

  • 启动优化之二进制重排

    涉及的基础知识点 虚拟内存和分页 我们知道,现代操作系统一般都采用虚拟内存管理机制,用分段(segment)和分页...

  • 清华大学操作系统课程 ucore Lab3 虚拟内存管理 实验报

    操作系统 Lab3 虚拟内存管理 实验报告 课程信息所在网址:https://github.com/chyyuu/...

网友评论

      本文标题:手写操作系统 - 实现虚拟内存管理

      本文链接:https://www.haomeiwen.com/subject/vkwtxstx.html