2026/4/3 2:31:23
网站建设
项目流程
可以免费打广告的网站,网站建设 蜂图网络,龙岗品牌网站建设,seo外链发布目录虚拟内存和分页机制介绍MMU 基本概念虚拟地址基本概念物理地址基本概念页表基本概念多节页表的映射过程内核空间页表虚拟内存和分页机制介绍
早期计算机系统的内存是比较小#xff0c;不过相应的程序也是比较小的#xff0c;这时程序可以直接加载到内存中运行#xff0…目录虚拟内存和分页机制介绍MMU 基本概念虚拟地址基本概念物理地址基本概念页表基本概念多节页表的映射过程内核空间页表虚拟内存和分页机制介绍早期计算机系统的内存是比较小不过相应的程序也是比较小的这时程序可以直接加载到内存中运行后来为了支持多个程序的并行内存中出现了固定分区在编译阶段将不同程序划分在不同的内存区域上这种方式存在不少问题内存分区大小与程序大小要匹配是地址空间无法动态的增长内存动态分区思想便诞生了内存上线划出一块区域给操作系统然后剩余的内存空间给用户进程使用这样用户程序所使用的内存空间跟随程序大小及数目进行变动不论是静态分析还是动态分区都存在一些问题进程地址空间安全问题(地址空间不隔离)内存使用效率低(不能动态回收或者交换)虚拟内存技术的产生为了能够让多程序安全、高效地并行运行物理内存中需要存放多个程序的代码及数据这时虚拟内存便诞生了虚拟内存是一个伟大的发明一方面它让每个程序认为自己是独自、连续的使用内存另一方面每个程序之间的内存形成了安全隔离避免程序破坏彼此的内存后来随着软件的快速发展一个程序的大小变得很大这时物理内存大小跟不上程序大小增加的速度这样便不能将整个程序加载到物理内存中一是物理内存没有这么大二是如果将整个程序加载到内存为了多程序并行就需要将大量的数据及代码换入、换出这导致程序运行效率低下虚拟内存并没解决高效使用内存的问题好在程序运行遵循时间、空间局部性原理进而出现了分页机制分页机制从根本上解决了高效使用物理内存的问题每次只需要将几页的代码、数据从磁盘中加载到内存程序就能正常运行当程序运行的过程中需要新的代码、数据会产生缺页异常这些代码、数据就会从磁盘加载到内存然后程序从异常恢复正常运行分页机制的产生对于支持虚拟内存分页机制的系统处理器直接寻址虚拟地址这个地址不会直接发给内存控制器而是先发给内存管理单元Memory Manager UnitMMU就是负责将虚拟地址转换和翻译成物理地址的一个硬件模块其实MMU所做的事完全可以通过CPU来实现为啥还要一个 MMU 硬件模块呢就是为了提升虚拟地址到物理地址转换的速度减少转换所消耗的时间MMU包含两个模块TLBTranslation Lookaside Buffer和TWUTable Walk Unit)TLB是一个高速缓存用于缓存页表转换的结果从而缩短页表查询的时间TWU是一个页表遍历模块页表是由操作系统维护在物理内存中但是页表的遍历查询是由TWU完成的这样减少对CPU资源的消耗MMU 基本概念在SMPSymmetric Multi Process对称多处理器系统中每个处理器内置了 MMU 模块MMU模块包含了TLB和TWU两个子模块TLB是一个高速缓存用于缓存虚拟地址到物理地址的转换结果页表的查询过程是由TWU硬件自动完成的但是页表的维护是需要操作系统实现的页表存放在主存中页表的查询是一个耗时的过程理想情况下TLB命中可以从中直接得到虚拟地址对应的物理地址当TLB未命中的时候MMU才会通过TWU查询页表从而翻译虚拟地址得到物理地址得到物理地址后首先要查询该物理地址的内容是否存在于Cache中若Cache命中则直接取出物理地址对应的内容返回给处理器若Cache没有命中会进一步访问主存获取相应的内容然后回写到Cache并返回给处理器如果没能在页表中查询到虚拟地址对应的物理地址则会触发一个与MMU相关的缺页异常在异常处理的过程中会将ROM 存储器中相关的数据加载到主存然后建立相应的页表然后将物理地址对应的内容返回给Cache及处理器虚拟地址基本概念虚拟内存Virtual MemoryVM为每个进程提供了一致的、连续的、私有的内存空间简化了内存管理虚拟地址空间Virtual Address SpaceVAS每个进程独有每个进程占有的虚拟地址范围虚拟页Virtual PageVP把虚拟内存按照页表大小进行划分虚拟地址Virtual AddressVACPU 处理器实际使用的地址虚拟页号Virtual Page NumberVPN用于定位页表的PTE物理地址基本概念物理内存Physical MemoryPM主存上能够使用的物理空间物理页Physical Page把物理内存按照页表的大小进行划分物理地址Physical AddressPA物理内存划分很多块通过物理内存进行定位物理页号Physical Page NumberPPN定位物理内存中块的位置页表基本概念页表Page Tabel虚拟地址与物理地址映射表的集合(注意是一个映射的集合)页全局目录Page Global DirectoryPGD多级页表中的最高一级页上级目录Page Upper DirectoryPUD多级页表中的次高一级页中间目录Page Middle DirectoryPMD多级页表中的一级页表条目Page Table EntryPTE虚拟地址与独立地址具体对应的记录说明: 页表时一个映射的集合保存在内存中规定了如何映射到物理地址页表Page Table 是操作系统在物理内存RAM中分配的一段数据结构它由一系列 页表项Page Table Entry,PTE 组成每个PTE通常为 8 字节在 64 位系统中每个PTE包含下一级页表或物理页的物理地址高几位权限位可读/可写/可执行是否有效Valid是否被访问过Accessed是否被修改过Dirty是否是全局页Global虽然页表在内存中但CPU需要知道 从哪里开始查找这就用到了寄存器在x86-64中CR3寄存器保存 顶层页表如PML4的物理基地址在ARM64中TTBR0_EL1和TTBR1_EL1寄存器分别保存 用户/内核顶层页表L0的物理基地址TLB是寄存器吗TLBTranslation Lookaside Buffer 是CPU内部的高速缓存Cache用于缓存最近使用的 VA → PA 映射它不是通用寄存器而是专用的关联存储器CAM属于MMU的一部分TLB的内容来源于页表但本身不是页表多节页表的映射过程物理页面大小一级地址总线宽度不同页表的级数也不同以AArch64运行状态4KB大小物理页面48位地址宽度为例页表映射的查询过程如图对于多任务操作系统每个用户进程都拥有独立的进程地址空间也有相应的页表负责虚拟地址到物理地址之间的转换MMU查询的过程中用户进程的一级页表的基址存放在TTBR0操作系统的内核空间公用一块地址空间MMU查询的过程中内核空间的一级页表基址存放在TTBR1当TLB未命中时处理器查询页表的过程如下处理器根据虚拟地址第63位来选择使用TTBR0或者TTBR1当VA[63]为0时选择TTBR0TTBR中存放着L0页表的基址处理器以VA[4739]作为L0的索引在L0页表中查找页表项L0页表有512个页表项L0页表的页表项中存放着L1页表的物理基址处理器以VA[38:30]作为L1索引在L1页表中找到相应的页表项L1页表中有512个页表项 (L1中会存储L2页表的物理基址)L1页表的页表项中存放着L2页表的物理基址处理器以VA[29:21]作为L2索引在L2页表中找到相应的页表项L2页表中有512个页表项L2页表的页表项中存放着L3页表的物理基址处理器以VA[20:12]作为L3索引在L3页表中找到相应的页表项L3页表中有512个页表项L3页表的页表项里存放着 4KB 页面的物理基址然后加上VA[11:0]这样就构成了物理地址至此处理器完成了一次虚拟地址到物理地址的查询与翻译的工作简化的流程TLB 未命中 → 触发页表遍历page table walk检查 VA[63]更准确说是 VA[63:48]若为 0 → 使用 TTBR0_EL1用户空间若为 1 → 使用 TTBR1_EL1内核空间从 TTBR 拿到 L0 页表的物理基址用 VA[47:39] 索引 L0 → 得到 L1 基址用 VA[38:30] 索引 L1 → 得到 L2 基址用 VA[29:21] 索引 L2 → 得到 L3 基址用 VA[20:12] 索引 L3 → 得到 4KB 页的物理基址物理地址 (L3 页表项中的物理页号 12) | VA[11:0]现代CPU通常有 硬件页表遍历器page walker自动完成这个过程无需软件干预内核空间页表即使在内核态kernel modeCPU仍然运行在虚拟地址模式下内核代码、数据、堆栈等都使用虚拟地址所有内核空间的虚拟地址包括直接映射区、vmalloc 区、内核代码段等都必须通过MMU 页表 转换为物理地址内核本身在虚拟地址空间中只是这个空间是所有进程共享的在 x86_64 等架构中高地址部分是内核空间内核页表存放位置页表是内存中的页通常是 4KB 对齐的它们自己也必须能被CPU访问因此页表所在的物理页也被映射到内核的虚拟地址空间中通常是直接映射区例如pgd页全局目录可能位于物理地址0x12345000那么它的虚拟地址就是PAGE_OFFSET 0x12345000进程页表和内核页表内核的页表本质上是普通内存中的数据结构由内核自己分配和管理在支持进程隔离的系统中每个进程有自己的一套页表PGD但所有进程的内核空间页表项是相同的也就是说当进程 A 和进程 B 切换时虽然用户空间页表不同但内核空间的映射是复用的或快速切换切换到内核态时会自动加载页表吗用户态 → 内核态如系统调用、中断)因为当前进程的页表 已经包含了内核空间的映射当 CPU 陷入内核例如执行 syscallMMU 仍然使用当前进程的页表即 CR3 寄存器未变内核可以直接访问其虚拟地址因为页表中已经建立了从内核虚拟地址 → 物理地址的映射进程切换进程 A → 进程 B此时会切换页表将CR3寄存器更新为进程B的PGD页全局目录物理地址但新页表中同样包含完整的内核空间映射所以内核代码依然可访问内核页表初始化启动早期汇编阶段内核在head.S中建立临时页表identity mapping 直接映射启用MMU后跳转到C代码此时已使用虚拟地址start_kernel()阶段调用paging_init()、zone_sizes_init()等函数建立完整的直接映射区、vmalloc区、内核代码段等映射为每个新创建的进程复制/共享内核页表部分