第 15 讲:分段、段页式与 x86 地址映射

分页主要回答“怎么高效分配物理内存”,分段则从程序的逻辑结构出发:代码、数据、栈、共享库是性质不同的对象,应当能独立增长、保护和共享。

分段的地址是二维的

分段地址写作二元组 (s,d)(s,d):

  • ss 是段号,表示选哪个逻辑对象;
  • dd 是段内偏移,每个段都从 0 开始。

段表项至少包含物理基址 base、段长 limit 和权限。转换顺序是:

  1. 检查段号 ss 是否落在段表长度内;
  2. 找到段表项,检查存在位与访问权限;
  3. 检查 0≤d<limit0\le d<limit;
  4. 计算 PA=base+dPA=base+d。

越界检查必须在加基址前做,不能只看加出来的物理地址“似乎在内存中”。

转换算例

设段 3 的段表项为 base=40000, limit=1200:

  • (3,900)(3,900) 合法,物理地址 40000+900=4090040000+900=40900;
  • (3,1500)(3,1500) 越过段长,应产生保护异常,不能算成 41500。

为什么分段更易共享和保护

一个 160 KiB 编辑器代码被 40 个用户进程共享:

  • 分页时,4 KiB 页需要让每个进程的 40 个页表项指向共享页框;
  • 分段时,每个进程只需一个代码段描述符指向同一物理区,并标记只读可执行。

段边界与逻辑边界对齐,所以“这段代码可共享但不可写”很自然。页是物理粒度,一页可能恰好混入两个逻辑模块,语义不如段直观。

分页与分段的对比

角度分页分段
单位固定大小的物理管理单位可变长的逻辑信息单位
地址空间一维段号 + 偏移的二维结构
碎片页内的内部碎片可变段之间的外部碎片
对用户通常透明可见或与程序模块对应
共享/保护按页按逻辑段,更自然

分段的突出问题是可变长连续分配依然有外部碎片,段增长可能迫使移动。

段页式:逻辑按段,物理按页

段页式将一个进程先分成段,再将每段分成页。逻辑地址变成 (s,p,d)(s,p,d):

  1. 段号 ss 查段表,得到该段的页表基址和页数;
  2. 检查页号 pp 是否越过该段页数;
  3. 用 pp 查该段页表,得到 PFN;
  4. 用 PFN×page_size+dPFN\times page\_size+d 得物理地址。

好处是段能按逻辑独立保护和共享,段内又不必占连续物理内存;代价是表更多,转换链更长。

x86 的两阶段地址映射

课件以 32 位 x86 保护模式为例:

逻辑地址:段选择子 : 段内偏移
         ↓ 分段机制(GDT/LDT + 段描述符)
线性地址:Directory | Table | Offset
         ↓ 分页机制(CR3 + PDE + PTE)
物理地址:PFN | Offset

第一阶段:段选择子找段描述符

x86 有 CS、DS、SS、ES、FS、GS 等段寄存器。寄存器中不直接存整个段描述符,而存一个选择子,其中包含:

  • 描述符表内索引;
  • 选 GDT 还是当前任务的 LDT;
  • 请求特权级。

GDT 是全局描述符表,LDT 是局部/任务相关表。段描述符记录基址、界限、类型、特权级、存在位和粒度等。处理器检查权限和界限后:

linear=segment_base+offset.linear=segment\_base+offset.

第二阶段:线性地址查两级页表

4 KiB 页的 32 位线性地址常拆为 10 | 10 | 12。

  1. CR3 指向页目录的物理基址;
  2. 高 10 位索引 PDE,PDE 指向二级页表;
  3. 中 10 位索引 PTE,PTE 给出物理页框;
  4. 低 12 位偏移原样拼接。

PDE/PTE 中的存在位 P、R/W、U/S、访问位 A、脏位 D 等决定页面当前是否在内存、允许谁怎样访问,也为页面置换提供状态。

Linux 为什么说是“扁平段”

x86 保护模式的分段机制不能简单消失,但 Linux 通常将主要代码/数据段设为基址 0、覆盖整个线性空间。这样:

linear=0+offset=offset,linear=0+offset=offset,

真正的虚拟内存隔离和粒度保护主要由分页完成。“扁平”不是说硬件完全没有段检查,而是把段的地址变换影响降到最小。

三类越界不要混

  1. 段号越界:选不到合法段描述符;
  2. 段内偏移越界:偏移超过 limit;
  3. 分页保护/不存在:线性地址已经形成,但 PDE/PTE 不允许或页尚未驻留。

转换是分阶段的,所以题目问“是否能得到物理地址”时,必须沿段检查—线性地址—页检查的顺序逐步回答。

评论