首页/操作系统/03-memory/多级页表计算详解 🔗 在 Obsidian 中打开
操作系统 · 03-memory

多级页表计算详解

重要度 ⭐⭐ 操作系统/内存管理
速查
多级页表把页表本身分页,只分配实际使用的页表页;核心公式:每级页号位数 $= \log_2\left(\dfrac{\text{页面大小}}{\text{页表项大小}}\right)$;n 级页表无 TLB 需 n+1 次访存

速查

项目
核心概念将页表本身分页,用层次化结构节省内存
关键公式总虚拟地址位数 V $=$ 一级页号 $+$ 二级页号 $+$ 偏移
访存次数n 级页表无 TLB 需 n+1 次访存
考试频率⭐⭐⭐⭐⭐

核心概念

多级页表是为了解决单级页表过大的问题而引入的。核心思想是将页表本身也分页,用层次化的页表结构节省内存。

为什么需要多级页表

问题说明
页表太大32 位地址空间 + 4KB 页面 → 需要 $2^{20}$ 个页表项(4MB 页表)
连续存储单级页表要求页表项连续存储
浪费内存大部分虚拟地址空间未使用,但页表项必须全部存在
解决方案多级页表:只在需要时才分配页表页
单级页表:VPN → PPN(一次查表)

二级页表:
一级页号 → 二级页表基址 → 二级页号 → PPN(两次查表)

关键定义与公式

字段说明位数计算
一级页号(页目录号)索引一级页表(页目录表)取决于设计
二级页号索引二级页表取决于设计
页内偏移页面内的字节偏移$\log_2(\text{页面大小})$
参数公式
页内偏移位数$d = \log_2(\text{页面大小})$
总虚拟地址位数$V = \text{一级页号} + \text{二级页号} + \text{偏移}$
一级页表项数$2^{\text{一级页号位数}}$
二级页表项数$2^{\text{二级页号位数}}$
每个页表项大小通常 4 字节(32 位系统)
一页能放的页表项数$\dfrac{\text{页面大小}}{\text{页表项大小}}$
访存次数n 级页表需要 n+1 次访存(无 TLB 时)

手算示例

示例1:经典二级页表计算

某系统 32 位虚拟地址,页面大小 4KB,采用二级页表,每个页表项 4 字节。地址划分:一级页号 10 位,二级页号 10 位,偏移 12 位。

32位虚拟地址:
| 一级页号(10位) | 二级页号(10位) | 页内偏移(12位) |
  • 验证:$10 + 10 + 12 = 32$ ✓
  • 一级页号 10 位 → $2^{10} = 1024$ 个页目录项
  • 二级页号 10 位 → $2^{10} = 1024$ 个页表项/每个二级页表
  • 偏移 12 位 → 页面大小 $= 2^{12} = 4\text{KB}$ ✓

页表大小:一级页表 $1024 \times 4\text{B} = $ 4KB(恰好 1 页);每个二级页表同样 4KB;最多 1024 个二级页表。

访存次数:无 TLB 时需要 3 次——①查页目录表(一级页表)得二级页表地址;②查二级页表得物理页框号;③访问目标数据。

示例2:根据页面大小和页表项推导地址划分

64 位系统,页面大小 8KB,页表项 8 字节,采用四级页表。

  • 偏移位数:$\log_2(8\text{KB}) = \log_2(2^{13}) = $ 13 位
  • 每页能放页表项数:$8\text{KB} / 8\text{B} = $ 1024 项
  • 每级页号位数:$\log_2(1024) = $ 10 位
  • 四级页号共 $4 \times 10 = $ 40 位;使用的虚拟地址位数 $40 + 13 = $ 53 位
64位虚拟地址(实际使用53位):
| 一级(10) | 二级(10) | 三级(10) | 四级(10) | 偏移(13) |

示例3:页表项数计算(每级恰好占一页)

某系统虚拟地址 32 位,页面大小 4KB,页表项大小 4B,二级页表,设计使得每级页表恰好占一页。

  • 每页页表项数 $= 4\text{KB} / 4\text{B} = 1024$ 项 → 每级页号 10 位
  • 偏移 $= \log_2(4\text{KB}) = 12$ 位
  • 二级页号 10 位;一级页号 $= 32 - 10 - 12 = $ 10 位
| 一级页号(10) | 二级页号(10) | 偏移(12) |

验证:一级 $2^{10} \times 4\text{B} = 4\text{KB} = 1$ 页 ✓;二级同理 ✓。

示例4:访存次数分析

上述二级页表系统,无 TLB 时访问一个数据需要 3 次访存(页目录表 → 二级页表 → 目标数据);有 TLB:命中 1 次访存,未命中 3 次 + 将结果写入 TLB。

示例5:反向计算——给定页表大小求地址划分

某系统虚拟地址 36 位,页面大小 16KB,要求每级页表恰好占一页,页表项大小 4B。

  • 偏移 $= \log_2(16\text{KB}) = 14$ 位;每页页表项数 $= 16\text{KB}/4\text{B} = 4096$ 项 → 每级页号 12 位
  • 页号部分总位数 $= 36 - 14 = 22$ 位;级数 $= 22 / 12 \approx 1.83$ → 向上取整 2 级
  • 实际划分:一级页号 $22 - 12 = 10$ 位、二级页号 12 位、偏移 14 位
| 一级页号(10) | 二级页号(12) | 偏移(14) |

常见考法

  1. 地址划分计算:给定系统参数,求各级页号和偏移的位数
  2. 页表大小计算:各级页表占用多少空间
  3. 访存次数分析:有无 TLB 时的访存次数
  4. 设计题:给定约束条件,设计页表级数和地址划分
  5. 与快表 TLB 结合:TLB 命中率对平均访存时间的影响
平均访存时间$$\text{平均访存时间} = \text{命中率} \times 1 + (1 - \text{命中率}) \times (n+1)$$

易错点

注意
  1. 偏移位数 $= \log_2(\text{页面大小})$,不是页表项大小
  2. 访存次数:n 级页表无 TLB 需要 n+1 次访存(n 次查页表 + 1 次取数据)
  3. 页号位数 k → 页表项数 $= 2^k$
  4. 多级页表不需要为未使用的虚拟地址空间分配页表
  5. 「页表恰好占一页」是设计约束,不是自动满足的
  6. 32 位地址 ≠ 32 位都用:有时实际使用的位数少于地址总线宽度

核心结论

必背
  1. 多级页表节省内存:只分配实际使用的页表页
  2. 每级页号位数 $= \log_2(\text{每页页表项数})$:核心公式
  3. n 级页表需要 n+1 次访存(无 TLB 时)
  4. TLB 能大幅降低访存时间:命中只需 1 次访存
  5. 「页表恰好占一页」是常见设计约束:方便管理和分配
  6. 地址划分总和 = 虚拟地址位数:各级页号 + 偏移 = 总位数

记忆卡片

为什么需要多级页表?
单级页表要求连续存储、大小固定;多级页表可离散存储且只分配实际使用的部分。
n 级页表(无 TLB)访问一次数据几次访存?
n+1 次:n 次查表 + 1 次取数据。二级页表 = 3 次。
每级页号位数如何确定?
$\log_2(\text{每页页表项数}) = \log_2(\frac{\text{页面大小}}{\text{页表项大小}})$。
32位+4KB+二级10-10-12,一级页表多大?
$2^{10} \times 4\text{B} = 4\text{KB}$,恰好一页。
TLB 对访存次数的影响?
命中 1 次;未命中 n+1 次。平均访存时间按命中率加权。

交互动画 · 地址划分与访存流程

虚拟地址位域(示例切换)
点击示例按钮查看地址划分;点「访存次数」查看无 TLB 时的 3 次访存
n 级页表无 TLB:n+1 次访存
橙色 = 一级页号,紫色 = 二级(及以下)页号,灰色 = 页内偏移。

相关知识点

virtual-memory-management tlb-translation-lookaside opt-page-replacement

↑ 以上为站内 HTML 相对链接(纯网页可浏览);本页右上「在 Obsidian 中打开」跳回源笔记。