区分页目录项和页表项的结构😡

场景设定


第一步:逻辑地址的结构分解

首先,我们必须把逻辑地址 0x016843C5 按照二级分页的结构进行拆分。

  1. 转换为二进制:

    0x016843C5 = 0000 0001 0110 1000 0100 0011 1100 0101

  2. 按结构拆分:

    根据我们之前定义的结构 (p1: 10位, p2: 10位, d: 12位) 进行切分。

    • 一级页目录号 (p1): 0000 0001 01 (二进制) = 5 (十进制)

    • 二级页表号 (p2): 10 1000 0100 (二进制) = 644 (十进制)

    • 页内偏移 (d): 0011 1100 0101 (二进制) = 0x3C5 (十六进制) = 965 (十进制)

我们可以用一个表格清晰地展示这个分解结果:

表格一:逻辑地址 0x016843C5 的结构

部分名称 二进制表示 十六进制表示 十进制值 作用
一级页目录号 (p1) 0000 0001 01 0x005 5 用于在页目录表中查找PDE
二级页表号 (p2) 10 1000 0100 0x284 644 用于在二级页表中查找PTE
页内偏移 (d) 0011 1100 0101 0x3C5 965 最终在物理页帧内的偏移地址

第二步:查找页目录项 (PDE)

现在,CPU的内存管理单元(MMU)开始工作。

  1. 定位页目录表: 从页目录表基地址寄存器(PDTR) 中获取页目录表的物理基地址:0x00100000

  2. 计算PDE地址:

    • 我们要找的PDE是页目录表中的第 p1 (=5) 项。

    • 每个PDE大小为4字节。

    • 所以,目标PDE的物理地址 = 基地址 + 索引 * 表项大小

      = 0x00100000 + 5 * 4

      = 0x00100014

  3. 获取PDE内容:

    MMU从物理地址 0x00100014 处读取到4个字节的PDE内容。我们假设读到的内容是 0x00099067。

让我们用表格来展示这张“页目录表”中我们关心的这一项:

表格二:页目录表中的第5项 (PDE)

物理地址 索引 (p1) PDE内容 (十六进制) PDE内容 (二进制)
0x00100014 5 0x00099067 0000 0000 0000 1001 1001 0000 0110 0111

解读这个PDE (0x00099067):


第三步:查找页表项 (PTE)

现在我们已经拿到了二级页表的“指针”,继续寻址。

  1. 定位二级页表: 根据上一步PDE提供的信息,我们知道二级页表的物理基地址是 0x00099000

  2. 计算PTE地址:

    • 我们要找的PTE是这张二级页表中的第 p2 (=644) 项。

    • 每个PTE大小为4字节。

    • 所以,目标PTE的物理地址 = 基地址 + 索引 * 表项大小

      = 0x00099000 + 644 * 4

      = 0x00099000 + 2576 (十进制)

      = 0x00099000 + 0xA10 (十六进制)

      = 0x00099A10

  3. 获取PTE内容:

    MMU从物理地址 0x00099A10 处读取到4个字节的PTE内容。我们假设读到的内容是 0x00785067。

表格三:二级页表中的第644项 (PTE)

物理地址 索引 (p2) PTE内容 (十六进制) PTE内容 (二进制)
0x00099A10 644 0x00785067 0000 0000 0111 1000 0101 0000 0110 0111

解读这个PTE (0x00785067):


第四步:形成最终物理地址

寻宝图的最后一步,拼接最终地址。

  1. 获取物理页基地址: 从上一步的PTE中,我们得到了物理页帧号 0x00785,其对应的物理基地址是 0x00785000

  2. 获取页内偏移: 从第一步分解逻辑地址时,我们得到了页内偏移 d,其值为 0x3C5

  3. 计算最终物理地址:

    • 最终物理地址 = 物理页基地址 + 页内偏移

      = 0x00785000 + 0x3C5

      = 0x007853C5

结论:逻辑地址 0x016843C5 经过二级页表的转换,最终映射到了物理地址 0x007853C5

问题一:“页目录项都是20bit吗?”

答:不是。这是一个非常普遍的误解,但非常关键。

一个页目录项 (PDE) 本身是一个完整的数据结构,在32位系统中,它通常是32位(即4字节)

你提到的“20bit”是页目录项内部一个非常重要的字段的长度,即**“页表的物理基地址”**字段。

让我们把一个32位的页目录项(PDE)想象成一个信息卡片,这张卡片被分成了两部分:

  1. 核心信息区(20位): 用来存放它所指向的那个二级页表的物理基地址(或者说是物理页帧号)。

  2. 控制/状态信息区(12位): 用来存放各种标志位,如**存在位(P)、读写权限位(R/W)、用户/超级用户位(U/S)**等。

所以,完整的关系是:

一个32位的页目录项 = 20位的页表基地址 + 12位的控制位

这个结构与页表项(PTE)非常相似,PTE也是一个32位的项,由20位的物理页帧号和12位的控制位组成。

为什么是20位?

因为在我们的例子中(32位系统,4KB页面),物理地址也是32位。一个物理页帧的地址由于是4K对齐的,所以其低12位必然全为0。因此,我们只需要存储其高20位(即物理页帧号PFN)就足以定位这个页帧了。20位页帧号 + 12个0 = 32位物理基地址。


问题二:“页目录项应该不包括页内偏移量吧?”

答:你说的完全正确!

页目录项 (PDE) 和页表项 (PTE) 的结构中,绝对不包含页内偏移量。

原因在于它们在地址转换过程中扮演的角色是完全不同的:

  1. 页目录项(PDE)和页表项(PTE)的使命:

    它们的唯一使命是将逻辑地址中的“页号”部分翻译成物理地址中的“页帧号”部分。它们是“页到帧”的翻译官。

  2. 页内偏移(d)的使命:

    页内偏移量的使命是在已经找到的那个正确的物理页帧内部,定位到具体的字节地址。它是“帧内寻址”的导航员。

地址转换流程清晰地体现了这一点:

  1. CPU拿出逻辑地址中的 p1 部分去查页目录表,找到对应的 PDE

  2. 从PDE中取出页表的地址

  3. CPU拿出逻辑地址中的 p2 部分去查这个页表,找到对应的 PTE

  4. 从PTE中取出最终物理页帧的地址

  5. 直到此时,CPU才拿出逻辑地址中的 d (页内偏移) 部分,与上一步得到的物理页帧地址相加,形成最终的物理地址。