虚拟地址空间、页表与 MMU

共 26 题
📑 题目列表 26 题
#
★★★

1. 虚拟地址到物理地址的转换,多级页表与 MMU 的 TLB 缓存如何配合?

虚拟地址到物理地址的转换如何完成?多级页表与 MMU 的 TLB 缓存如何协同?

  • 多级页表结构
  • MMU 与 page table walk
  • TLB 缓存加速

虚拟地址到物理地址的转换由 MMU(内存管理单元)完成。多级页表把虚拟地址拆分为多个层级索引(如 x86-64 的 PML4/PDPT/PD/PT),MMU 逐级索引页表获得物理页框号(PFN),再与页内偏移组合得到物理地址。为避免每次都走完整的页表遍历(page table walk),MMU 内置 TLB(Translation Lookaside Buffer)缓存最近使用的虚拟到物理映射,命中时直接获得物理地址,无需访问内存页表。TLB miss 时才触发 page table walk 并填充 TLB。多级页表减少页表内存占用,TLB 缓存加速地址转换。

多级页表"省内存"(按需分配页表层级),TLB"省时间"(缓存转换结果)。MMU 通过 TLB 优先、页表兜底的策略平衡容量与速度。

#
★★

2. ARM64 VA 48-bit 与 52-bit 配置在 TCR_EL1.IPS 字段?

ARM64 的 VA 48-bit 与 52-bit 配置与 TCR_EL1.IPS 字段有何关系?

  • TCR_EL1.IPS 字段
  • 48-bit vs 52-bit VA
  • IPAs 与系统支持

ARM64 的 TCR_EL1.IPS(Intermediate Physical Address Size)字段配置物理地址(IPA)的大小,决定 MMU 支持的物理地址空间位数。48-bit 支持 256TB 物理地址空间,52-bit 支持 4PB(需配合 Armv8.2-LVA 扩展)。而 Virtual Address 位数由 TCR_EL1.T1SZ/T0SZ 字段控制(类似地 48/52-bit)。IPS 字段影响页表层级的选择:52-bit 需要更多/更宽的页表层级(或更大的 granule)。配置需匹配硬件支持,否则会触发 check 失败。

TCR_EL1 的 IPS 与 T0SZ/T1SZ 分别控制物理与虚拟地址位数,52-bit 需要硬件扩展(LVA/LPA)支持,并影响页表规模与转换器深度。

#
★★

3. Linux 进程虚拟地址空间中 user 与 kernel 区段如何划分?

Linux 进程虚拟地址空间中 user 与 kernel 区段如何划分?

  • 用户态/内核态地址划分
  • x86-64 的 canonical 边界
  • 地址空间隔离

Linux 进程虚拟地址空间分为用户态与内核态两大部分。在 x86-64 上,用户态位于低地址(0x0000000000000000 到 0x00007fffffffffff,约 128TB),内核态位于高地址(0xffff800000000000 以上),以 canonical 地址的高位为界,用户态地址高位为 0,内核态地址高位为 1。用户态与内核态通过该划分实现隔离,用户进程无法访问内核地址(页表权限限制)。内核地址对所有进程共享(同一映射),用户地址则随进程切换而不同。ARM64 也有类似的 TTBR0/TTBR1 划分(用户/内核)。

user/kernel 划分是"地址空间隔离 + 权限控制"的基础:内核高地址、用户低地址,通过页表权限位防止用户访问内核,保证了安全与隔离。

#
★★

4. MMU 将虚拟地址翻译为物理地址的核心动机是什么?

MMU 将虚拟地址翻译为物理地址的核心动机是什么?

  • 进程隔离
  • 内存抽象与保护
  • 虚拟内存(换页、共享)

MMU 的虚拟地址翻译核心动机是:1)进程隔离:每个进程拥有独立的虚拟地址空间,互不干扰,防止进程访问其他进程内存;2)内存保护:通过页表权限位(R/W/X、用户/内核)实现访问控制;3)内存抽象:虚拟地址与物理地址解耦,允许按需分配、对换(swap)、懒分配(lazy allocation)、共享内存(同一物理页映射到多个虚拟地址);4)简化编程:程序使用连续虚拟地址,无需关心物理内存的碎片与布局。这些能力使操作系统能安全、高效地管理内存。

虚拟地址翻译是"隔离 + 保护 + 抽象"的基石:它让每个进程"独享"一个大的连续地址空间,同时让内核灵活管理物理内存。没有它就没有现代多进程操作系统。

#
★★

5. x86-64 canonical 地址格式中 48-bit 与 57-bit VA 的位模式差异?

x86-64 canonical 地址格式中 48-bit 与 57-bit VA 的位模式差异是什么?

  • canonical 地址规则
  • 48-bit(4-level)vs 57-bit(5-level)
  • 符号扩展

x86-64 要求有效地址必须是 canonical 形式:有效虚拟地址的"有效位"(48 或 57 位)之上的所有位必须等于第 48/57 位的符号扩展(即高位全 0 或全 1)。48-bit VA(4-level 页表)总寻址空间 256TB,其中用户态与内核态各 128TB,有效地址高 16 位是符号扩展;57-bit VA(5-level 页表,LA57)总寻址空间 128PB(用户态与内核态各 64PB),有效地址高 7 位是符号扩展。非 canonical 地址访问会触发 #GP/KVM 错误。差异在于支持地址空间大小与页表层级,以及符号扩展的位数。

canonical 地址通过"符号扩展"限制有效地址范围,保证地址可被当前页表映射。48→57-bit 增加页表层级并扩大地址空间,符号扩展位数相应减少。

#
★★

6. 为何 PIE 二进制使进程加载地址随机化而提升安全性?

为什么 PIE 二进制使进程加载地址随机化而提升安全性?

  • PIE 与 ASLR
  • 重定位与加载地址
  • 缓解信息泄露利用

PIE(Position Independent Executable)使可执行文件可以在任意加载地址运行,配合 ASLR(地址空间布局随机化),操作系统在加载时把进程的代码段、库、堆、栈等随机放到不同地址。由于加载地址随机,攻击者无法预先知道代码、GOT、全局数据的确切地址,从而难以进行 ROP 等基于固定地址的攻击,显著提升利用难度。非 PIE 的可执行文件加载地址固定,攻击者可直接利用已知地址。PIE 通过重定位(相对寻址)和 PLT/GOT 机制实现地址无关。

PIE 的安全性来自"把地址随机化":攻击者需要先泄露地址才能利用,打破了"固定地址+已知布局"的利用前提。这是现代 Linux 发行版默认编译 PIE 的原因。

#
★★

7. vvar 与 vdso 在 Linux 进程虚拟地址的位置与作用?

vvar 与 vdso 在 Linux 进程虚拟地址中的位置与作用是什么?

  • vdso 的虚拟化系统调用
  • vvar 的只读数据区
  • 位置与权限

vdso(virtual dynamic shared object)是内核映射到用户进程的一段只读、可执行的页面,把一些常用系统调用(如 gettimeofday、clock_gettime、getcpu)实现为纯用户态代码,无需陷入内核(避免 mode switch),从而加速这些调用。vvar 是 vdso 配套的只读数据区,存放 vdso 代码需要访问的变量(如当前时间戳、时钟源数据、CLOCK 信息),映射为只读。两者都位于用户进程地址空间的高处(mmap 区附近),由内核在启动时自动映射,对用户透明。作用是减少系统调用开销、提高时间相关调用性能。

vdso/vvar 是"把高频系统调用下放到用户态"的优化:通过只读共享映射,让用户代码直接读取时间数据或执行简单逻辑,避免频繁陷入内核。

#
★★

8. 为何 ELF 动态链接器 ld-linux.so 需要映射到用户态?

为什么 ELF 动态链接器 ld-linux.so 需要映射到用户态?

  • 动态链接器的作用
  • 用户态映射的必然性
  • 与内核装载的关系

动态链接器(ld-linux.so,如 /lib64/ld-linux-x86-64.so.2)负责在程序启动时加载所需的共享库、解析符号、完成重定位。它必须映射到用户进程空间,因为:1)动态链接是用户态进程的职责,需要与用户进程共享地址空间、访问其内存;2)链接器本身是用户态程序,执行符号解析、重定位、调用构造函数等都需要用户态权限;3)内核只负责装载 ELF 头和初始映射,真正的动态链接由用户态的链接器完成。因此内核把链接器作为第一个"解释器"(interpreter)映射到用户地址空间,并跳转到其入口。

动态链接器在用户态运行是"职责分离"的结果:内核只做最小装载,链接器在用户态完成复杂链接,既灵活又可与进程共享内存。这也是 ld.so 是特殊 ELF 解释器的原因。

#
★★

9. ARM64 4KB granule 下 4-level 页表的 9+9+9+9+12 位宽?

ARM64 4KB granule 下 4-level 页表的 9+9+9+9+12 位宽是什么?

  • 4-level 页表结构
  • 每级索引位宽
  • 页内偏移

ARM64 以 4KB granule 时使用 4-level 页表,48-bit 虚拟地址被拆分为 9+9+9+9+12 位:前四级各 9 位索引(分别对应 Level 0-3 的页表项 entry),最后 12 位是页内偏移(4KB 页,2^12=4096)。每一级页表有 2^9=512 个 entry(每项 8 字节,共 4KB 页表)。4 级索引覆盖 9+9+9+9=36 位,加上 12 位偏移共 48 位虚拟地址。这一布局使每级页表大小恰好为一页,便于按需分配。

9+9+9+9+12 是 4KB granule + 48-bit VA 的经典拆分:每级 9 位索引(512 项),12 位页内偏移,保证页表与页大小对齐、按需分配。

#
★★

10. ARM64 64KB granule(contiguous bit)页表粒度变化?

ARM64 64KB granule(contiguous bit)的页表粒度变化是什么?

  • 64KB granule 的页大小
  • contiguous bit 合并
  • 页表层级与 TLB 效果

ARM64 64KB granule 使最小页大小为 64KB,页一级的覆盖范围扩大,页表层级更少(48-bit VA 下用 3 级或更少层级即可覆盖)。contiguous bit 允许把相邻的 64KB 页(如 32 个)合并为单个 TLB entry,进一步减少 TLB miss,等效于超大页。其变化是:页表更扁、影子覆盖更大、TLB 命中率更高,但最小分配粒度变大(64KB),内部碎片增加。对以大块连续内存为主的工作负载(如内存数据库)友好。

64KB granule 通过"更大页 + contiguous 合并"换取更小的页表与更高的 TLB 命中,代价是碎片粒度变大。这是"粒度与命中率"的权衡。

#
★★

11. page table walk 在 MMU 中的硬件实现 4-level vs 5-level?

page table walk 在 MMU 中的硬件实现中 4-level 与 5-level 的区别是什么?

  • 4-level vs 5-level 页表
  • 地址空间覆盖
  • 硬件 walker

page table walk 是 MMU 在 TLB miss 时按页表层级逐级索引、找到物理页框号的过程。4-level 页表(如 x86-64 PML4/PDPT/PD/PT,ARM64 4 级)支持 48-bit VA(256TB);5-level 页表(x86-64 LA57,ARM64 5 级)增加一级,支持 57-bit VA(128PB)。5-level 增加一次内存访问,但满足超大内存需求。硬件 walker 自动完成逐级遍历,同时支持超大页(大页提前终止 walk,如 2MB/1GB 页在较低层级即命中),减少 walk 步数。差异核心是地址空间规模与 walk 步数。

4-level 覆盖 48-bit,5-level 覆盖 57-bit,多一级多一次内存访问。大页通过"提前终止 walk"减少层级,是 MMU 硬件支持大页的关键。

#
★★

12. x86-64 4-level 页表(PML4/PDPT/PD/PT)各级大小与覆盖?

x86-64 4-level 页表(PML4/PDPT/PD/PT)各级的大小与覆盖范围是什么?

  • 各级 entry 数量
  • 每级覆盖范围
  • 层级与地址

x86-64 4-level 页表:PML4(第 4 级)有 512 个 entry,每个指向一个 PDPT;PDPT(第 3 级)512 entry 指向 PD;PD(第 2 级)512 entry 指向 PT;PT(第 1 级)512 entry 指向物理页。每级 9 位索引(512 项),末 12 位偏移。覆盖:单个 PT 覆盖 512×4KB=2MB;PD 覆盖 512×2MB=1GB;PDPT 覆盖 512×1GB=512GB;PML4 覆盖 512×512GB=256TB。PT 可指向 2MB 大页(PD 层 page size bit),PD 可指向 1GB 大页。每级页表 512×8B=4KB。

各级覆盖按 512 倍递增,最终 256TB。大页通过在某层设 page size bit 提前终止,覆盖更大空间。理解每级覆盖是地址转换与页表内存估算的基础。

#
★★

13. 为何页表需要 present bit 而非单独 valid bit?

为什么页表需要 present bit 而非单独的 valid bit?

  • present bit 的含义
  • present 与 swap 的关系
  • 为何不用 valid

页表项的 present bit 表示该页当前是否"在内存中"(已映射、可访问)。它不同于单纯的 valid(有效)标记,因为页表项在页被换出(swapped out)时,物理地址字段会被复用为 swap 的编码信息(如换出块编号),此时 present 位为 0,但页表项本身仍"有效"(记录了页在 swap 中的位置)。若用单独的 valid bit,则无法区分"从未映射"和"已换出"两种状态。因此 present bit 承担"是否驻留内存"的语义,配合 fault 处理(缺页中断)在需要时换入。

present bit 是"驻留内存"标志,与 valid 的"有效"语义不同。换出页 present=0 但保留 swap 信息,缺页时据此换入,这是虚拟内存对换的基础。

#
★★

14. 页表项(PTE)权限位 R/W/X 与 UXN/PXN 的差异?

页表项(PTE)权限位 R/W/X 与 UXN/PXN 的差异是什么?

  • R/W/X 权限
  • UXN(用户不可执行)/PXN(特权不可执行)
  • ARM64 权限模型

页表项的 R/W/X 权限位控制该页的读写执行权限(R 可读、W 可写、X 可执行),用于实现 NX(不可执行)和普通的读写保护。UXN(Unprivileged execute-never)和 PXN(Privileged execute-never)是 ARM64 特有的位:UXN 禁止用户态(非特权)执行该页,PXN 禁止特权态(内核)执行该页。差异在于:R/W/X 控制"能否读写执行"的基本权限,UXN/PXN 进一步按"执行者特权级别"细分禁止执行,用于强化内核与用户态的隔离(如内核禁止执行用户页,防止绕过 SMEP/PAN)。x86 用 SMEP/SMAP 实现类似功能。

R/W/X 是通用权限,UXN/PXN 是 ARM64 的执行级细分,用于防御"内核执行用户数据"等攻击路径,是内核/用户隔离的硬件支撑。

#
★★

15. 页表 memory type 在 IOMMU 与 CPU MMU 的同步?

页表 memory type 在 IOMMU 与 CPU MMU 的同步是怎样的?

  • IOMMU 页表
  • memory type 的一致性
  • 设备 DMA 与缓存

CPU MMU 和 IOMMU 各自维护页表,用于 CPU 访问内存与设备 DMA 访问内存。页表的 memory type(内存类型,如 normal、device、cacheable)决定缓存与顺序访问语义。同步问题在于:设备通过 IOMMU DMA 访问的内存,其 memory type 与 CPU 页表可能不一致,导致缓存一致性问题(如设备看到脏数据)。内核需保证 IOMMU 页表配置的 memory type 与对应物理内存的 CPU 缓存属性一致,并在页表更新时刷新 TLB/IOMMU TLB,确保双方看到一致的内存视图。IOMMU 页表通常由内核显式管理,需与 CPU 页表同步内存属性。

memory type 同步是"CPU 缓存与设备 DMA 一致性"的关键:两种页表必须对同一物理内存的缓存/顺序属性达成一致,否则数据不一致。这依赖内核的 IOMMU 编程与缓存刷新。

#
★★

16. 页表项的结构,标志位、物理页框号与大页(HugePage)如何组织?

页表项(PTE)的结构是什么?标志位、物理页框号与大页(HugePage)如何体现?

  • PTE 的组成(PFN + 标志位)
  • 大页的标志(page size bit)
  • 大页如何减少层级

页表项(PTE)通常包含物理页框号(PFN,物理页的高位地址)和一组标志位(present、R/W/X、dirty、accessed、user、global、NX 等)。CPU 通过 PFN 与页内偏移得到物理地址。大页(HugePage)通过页表项中的 page size bit(PS,如 x86-64 的 PS bit 在 PD/PDPT 层)表示该层直接指向一个大页(2MB/1GB),从而提前终止页表遍历,减少层级。大页 PTE 的 PFN 指向大页的起始物理地址,配合标志位控制权限。标志位用于权限、缓存、脏页管理等。

PTE 是"物理地址 + 权限/状态"的编码。PFN 指向物理页,标志位控制访问,PS bit 指示大页提前终止 walk,是页表稀疏与分层的核心。

#
★★

17. 进程切换时地址空间的切换,CR3 与 TLB flush 如何执行?

进程切换时地址空间的切换如何完成?CR3 与 TLB flush 的作用是什么?

  • CR3 指向页表基址
  • TLB 缓存失效
  • 上下文切换的开销

每个进程有独立的页表,CR3 寄存器(x86-64)保存当前进程页表的物理基址(PML4)。进程切换时,操作系统更新 CR3 指向新进程的页表,从而切换地址空间。由于 TLB 缓存了旧进程的虚拟到物理映射,切换后这些缓存失效,需要 flush TLB(否则会命中错误的映射)。flush 可通过写 CR3、INVLPG、或 PCID/ASID 技术(x86 用 PCID 配合 INVPCID,ARM 用 ASID)来避免全部 flush,只失效相关条目。频繁切换会因 TLB flush 和缓存失效带来开销,因此现代内核用 PCID/ASID 降低 TLB 刷新成本。

CR3 是"切换页表"的开关,TLB flush 是"清除旧映射"的必要步骤。PCID/ASID 通过给 TLB 条目打上地址空间标签,避免全量 flush,是优化上下文切换的关键。

#

18. RISC-V Sv39 三级页表与 Sv48 四级页表的 VA 宽度差异?

RISC-V Sv39 三级页表与 Sv48 四级页表的 VA 宽度差异是什么?

  • Sv39 的 39-bit VA
  • Sv48 的 48-bit VA
  • 页表层级

RISC-V 的 Sv39 使用三级页表,支持 39-bit 虚拟地址(512GB 地址空间);Sv48 使用四级页表,支持 48-bit 虚拟地址(256TB)。页表层数:Sv39 用 3 级(每级 9 位索引 + 12 位偏移 = 39 位),Sv48 用 4 级(每级 9 位 + 12 位 = 48 位)。更大的 VA 需要更多层级,但占用更多页表内存。选择取决于地址空间需求:Sv39 足够大多数应用,Sv48 用于大地址空间。高 25 位(Sv39)或 16 位(Sv48)为符号扩展限制。

Sv39 与 Sv48 的差异是"地址空间规模 vs 页表层级":更大的 VA 用更多页表层级,覆盖更大空间。这与 ARM64 的 4/5-level 类似。

#

19. RISC-V Sv39 3-level 页表的 9+9+9+12 split?

RISC-V Sv39 3-level 页表的 9+9+9+12 split 是什么?

  • 三级页表索引
  • 位宽分配
  • 页内偏移

RISC-V Sv39 的 39-bit 虚拟地址被拆分为 9+9+9+12:前三级各 9 位索引(分别对应 Level 0/1/2 的页表项),最后 12 位是页内偏移(4KB 页)。每级页表有 2^9=512 个 entry,每项 8 字节,共 4KB。三级索引覆盖 27 位,加 12 位偏移共 39 位。这一设计与 x86-64/ARM64 的 4KB 页模型一致,每级页表恰好一页,便于按需分配。

9+9+9+12 是 Sv39 的标准拆分:每级 9 位索引(512 项)、12 位页内偏移,保证页表与页对齐、覆盖 512GB 地址空间。

#

20. ASLR 随机化 stack/heap/mmap/binary 在 64-bit 系统的熵?

ASLR 随机化 stack/heap/mmap/binary 在 64-bit 系统的熵是多少?

  • ASLR 的作用
  • 各区域随机化位数
  • 64-bit 的熵

ASLR 在 64-bit 系统上随机化二进制、mmap、堆、栈的加载地址。近似熵:stack 的随机化约 10-22 位(x86-64 上约 22 位,受低地址空间限制),mmap(含共享库)约 16-28 位,binary(PIE)约 28 位,heap 约 11-13 位。具体位数受内核配置(如 vm.mmap_rnd_bits)、地址空间大小和架构影响。熵越大,地址越难预测,攻击者越难利用,但也可能因过度随机化浪费地址空间。ASLR 的强度是"熵值"与"可用性"的权衡。

64-bit 因地址空间大提供更高熵,使 stack/heap/mmap/binary 的随机化更能阻止攻击者预测地址。熵值量化了 ASLR 的防御强度。

#

21. Linux 中 stack guard page 的虚拟地址布局与越界 SIGSEGV?

Linux 中 stack guard page 的虚拟地址布局与越界 SIGSEGV 是什么?

  • guard page 的位置
  • 检测栈溢出
  • SIGSEGV 触发

Linux 在栈的底部(高地址端,即栈顶通过 guard page 与相邻映射隔开)保留一个或几个不可访问的 guard page(虚拟地址上标记为不可访问)。当栈向下增长越过 guard page 时,访问该地址会触发缺页,但该页被标记为不可访问(PROT_NONE),内核判定为栈溢出并发送 SIGSEGV(段错误)信号终止进程,而非无限扩展栈。guard page 的布局使栈与其上方(高位)的相邻映射(如 mmap 区)隔离,防止栈增长侵入其他映射。它同时检测栈溢出并防止栈与相邻区域碰撞。

guard page 是"栈的防火墙":不可访问的哨兵页,栈越界即触发 SIGSEGV,既检测溢出又防止栈与相邻映射交叉。这是栈安全的关键机制。

#

22. mmap(NULL, ...) 创建匿名映射为何能扩展虚拟地址空间?

mmap(NULL, ...) 创建匿名映射为何能扩展虚拟地址空间?

  • mmap 的虚拟地址分配
  • 匿名映射不占物理内存
  • 惰性分配

mmap(NULL, ...) 让内核在进程虚拟地址空间中分配一段指定大小的虚拟地址(匿名映射),这段虚拟地址被标记为"已映射但未分配物理页",物理页在首次访问时按需分配(缺页)。因此 mmap 是在"虚拟地址空间"上划线,扩大了可用的虚拟地址范围,而不立即消耗物理内存。这使进程能保留(reserve)大块虚拟地址供后续使用(如预留缓冲、堆扩展),也支持惰性分配。虚拟地址空间(64-bit 下巨大)远大于物理内存,mmap 因此能"扩展"可用虚拟地址。

mmap 扩展的是"虚拟地址空间"而非物理内存:它建立 VMA 记录映射,物理页延迟到访问时分配。这利用了虚拟地址与物理内存的解耦,是预留大块内存的基础。

#

23. PTE 中 dirty bit 与 accessed bit 在 OS 中的角色?

PTE 中 dirty bit 与 accessed bit 在 OS 中的角色是什么?

  • dirty bit 表示被写
  • accessed bit 表示被访问
  • 页回收与换出

PTE 的 dirty bit 表示该页自上次清理以来是否被写入(脏页),accessed bit 表示该页是否被访问过(读或写)。OS 利用它们做内存管理:1)页回收(page reclaim)时,accessed bit 用于实现 LRU 式的老化算法(active/inactive 链表),判断页是否被频繁使用,决定回收优先级;2)换出(swap out)时,dirty bit 决定是否需要写回磁盘(脏页要写,干净页可直接丢弃),避免不必要的磁盘写;3)dirty 页表明脏数据,换出前必须写回。OS 在缺页和定期清理时读取/清除这些位,并可用软件模拟(如定期清位判断活跃度)。

dirty/accessed 位是"硬件提供的页使用元数据":accessed 支持 LRU 式回收决策,dirty 支持换出时的写回决策。OS 据此实现高效的页管理与换页。

#

24. huge page 在 PTE 中的 PS 位(page size bit)?

huge page 在 PTE 中的 PS 位(page size bit)是什么?

  • PS 位的含义
  • 大页提前终止 walk
  • 覆盖范围

PS 位(page size bit)是页表项中的一个标志位,指示该页表项直接指向一个大页(如 x86-64 的 2MB/1GB 大页),而非下一级页表。当 PS 位被设置时,MMU 在较低层级(如 PD 层的 2MB、PDPT 层的 1GB)即终止 page table walk,直接使用该 PTE 的 PFN 作为大页的物理基地址,从而减少页表层级和 TLB miss。PS 位使大页能在一个页表项中覆盖更大范围,是硬件支持大页的关键。

PS 位是"大页开关":设置了就提前终止 walk,用单个 PTE 覆盖大块内存。这使大页既能减少页表占用又能提升 TLB 命中率。

#

25. page fault 的原因,not present、权限违规、reserved 位如何区分?

page fault 的原因有哪些?not present、权限违规、reserved 位分别是什么?

  • 缺页的三种原因
  • not present(缺页)
  • 权限违规与 reserved 位

page fault(缺页异常)由 MMU 在地址转换失败时触发,原因主要分三类:1)not present(页面不存在):PTE 的 present 位为 0,表示页未被映射(首次访问、懒分配、已换出),OS 需分配物理页或换入;2)权限违规(protection violation):PTE 存在但访问违反权限(如写只读页、执行不可执行页、用户访问内核页),OS 报错或触发 COW;3)reserved 位(保留位):PTE 中保留位被设置(非法编码),通常是 bug 或内核错误,通常是致命错误。OS 通过缺页错误码(error code 的 P/W/U/R 位)区分原因,分别处理。

page fault 的三种原因对应"没有映射、权限不符、编码非法",OS 依据错误码分别处置(分配/换入、报错或 COW、致命错误)。这是虚拟内存异常处理的核心。

#

26. 内存保护与隔离,用户态/内核态与页表权限位如何协同?

内存保护与隔离如何通过用户态/内核态与页表权限位实现?

  • 特权级(CPL)
  • 页表权限位
  • 隔离机制

内存保护与隔离通过"特权级 + 页表权限位"实现:CPU 有特权级(x86 的 CPL0 内核态 / CPL3 用户态),页表项有 user/supervisor 位(U/S)、R/W 位、NX 位等。用户态代码(CPL3)访问内存时,MMU 检查页表权限:若页的 user 位为 0(仅内核可访问),用户访问会触发权限违规 fault。用户态无法读取或修改内核页,内核态则可访问所有页(特殊技巧如 SMAP 限制)。这样结合"特权级区分"与"页表权限位",实现内核与用户、进程与进程之间的隔离与保护。这是操作系统安全的基础。

隔离 = 特权级(谁能执行)+ 页表权限(谁能访问)。用户态受限于页表权限无法碰内核,进程间通过独立页表隔离,共同构建内存安全边界。