Linux 内存管理单元 MMU(上)
前言Linux系统中的一个重要概念 —— 内存管理单元也叫MMU。今天我们来通俗易懂的解释一下这MMU的工作机制。目录一、虚拟内存 与 MMU二、用借书类比三、分页机制四、地址转换过程一、虚拟内存 与 MMU在介绍MMU之前我们先来理解另一个基础概念 —— 虚拟内存(地址)。虚拟地址在 Linux 中每个进程拿到的都是“虚拟地址空间”比如 0–4GB(32位)64 位更大。物理地址内存条上真实的地址叫做“物理地址”。为什么需要虚拟地址现代计算机系统中应用程序对内存的需求往往远超物理内存的实际容量。如果每个程序都直接独占物理内存会造成内存资源的极大浪费而且容易导致多个程序之间发生冲突。为解决这些问题现代操作系统引入了虚拟内存技术。虚拟内存允许每个进程拥有一个独立、连续且巨大的地址空间即使物理内存不足以容纳所有进程的全部数据也能通过在硬盘和内存之间按需交换数据从而支持更大的寻址空间。那什么是MMU呢内存管理单元MMU是实现虚拟内存机制的关键。它位于CPU与物理内存之间充当虚拟地址与物理地址之间的桥梁。它负责将程序所使用的虚拟地址逻辑地址转换为实际的物理地址。二、用借书类比在深入讲解MMU地址转换逻辑之前我们先用形象的生活事件来进行简单类比假如你去图书馆借书CPU 你虚拟地址 书编号物理地址 图书馆仓库MMU 页表 借书管理系统包含书编号与实际所在仓库位置的对应关系等【页表在下一节介绍】三、分页机制MMU的“单位”是页。MMU 不是“一个字节一个字节”地翻译而是“分页”。分页将虚拟地址空间划分为固定大小的块称为页常见的页大小为4KB将物理内存划分为固定大小的块称为页框。每个虚拟页通过页表映射到一个物理页框。页表是一种数据结构存储了虚拟页与物理页帧之间的映射关系。每个进程都有自己的页表由操作系统维护用于描述该进程虚拟地址空间的布局。页表中除了存储映射关系外还包含一些控制位如权限位和存在位。typedef struct { unsigned long pfn; // 物理页框号 unsigned int present : 1; // 页表项是否存在 unsigned int rw : 1; // 读/写权限 unsigned int us : 1; // 用户权限 // 其他控制位 } PageTable;四、地址转换过程MMU将虚拟地址分为页号和页内偏移两部分。-------------------------- | 页号 (p) | 页内偏移 (d) | -------------------------- ↑ ↑ 高位地址 低位地址当进程访问一个虚拟地址时MMU会根据虚拟地址页号去页表中查找得到对应的物理帧号然后将物理页号与页内偏移组合形成完整的物理地址最就能够访问真实的物理地址了。虚拟地址: (页号p, 偏移d) ↓ [页表查询] ↓ 物理地址: (帧号f, 偏移d) ← 偏移保持不变这里举一个简易的示例 ; 单级页表虚拟地址转换演示 ; 页大小4KB12位偏移 mov ecx, eax ; 保存原始虚拟地址到 ECX shr eax, 12 ; 提取虚拟页号(虚拟地址 12) ; 计算页表项地址 mov ebx, page_table_base ; EBX 页表虚拟地址假设已设置 mov edx, [ebx eax*4] ; EDX 页表项PTE ; 检查页是否存在P位 test edx, 0x1 ; 测试Present位bit 0 jz .page_not_present ; 如果为0页不存在 ; 提取物理页框号 and edx, 0xFFFFF000 ; 清除低12位标志位保留物理页框号 ; 计算物理地址 and ecx, 0xFFF ; ECX 页内偏移原始虚拟地址低12位 or eax, edx ; EAX 物理页框号 or eax, ecx ; EAX 物理页框号 | 偏移 完整物理地址写在最后本文采用通俗易懂的方式解释了MMU的基本知识旨在让大家快速理解入门其中还有很多细节如多级页表、缺页异常处理、TLB我们在后续文章中继续介绍。