区分页目录表当中的表项和页表的页目录项的逻辑地址结构组成😡
场景设定
-
体系结构: 32位系统。
-
内存管理: 二级页式存储管理。
-
页面大小: 4KB (212 字节)。
-
表项大小: 页目录项(PDE) 和 页表项(PTE) 都是4字节(32位)。
-
已知条件:
-
当前进程的页目录表基地址寄存器(PDTR) 的值为
0x00100000
(页目录表存放在这个物理地址开始的地方)。 -
我们需要转换一个逻辑地址:
0x016843C5
。
-
第一步:逻辑地址的结构分解
首先,我们必须把逻辑地址 0x016843C5
按照二级分页的结构进行拆分。
-
转换为二进制:
0x016843C5 = 0000 0001 0110 1000 0100 0011 1100 0101
-
按结构拆分:
根据我们之前定义的结构 (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)开始工作。
-
定位页目录表: 从页目录表基地址寄存器(PDTR) 中获取页目录表的物理基地址:
0x00100000
。 -
计算PDE地址:
-
我们要找的PDE是页目录表中的第
p1
(=5
) 项。 -
每个PDE大小为4字节。
-
所以,目标PDE的物理地址 = 基地址 + 索引 * 表项大小
= 0x00100000 + 5 * 4
= 0x00100014
-
-
获取PDE内容:
MMU从物理地址 0x00100014 处读取到4个字节的PDE内容。我们假设读到的内容是 0x00099067。
让我们用表格来展示这张“页目录表”中我们关心的这一项:
表格二:页目录表中的第5项 (PDE)
物理地址 | 索引 (p1) | PDE内容 (十六进制) | PDE内容 (二进制) |
---|---|---|---|
0x00100014 |
5 | 0x00099067 |
0000 0000 0000 1001 1001 0000 0110 0111 |
解读这个PDE (0x00099067
):
-
页表的物理基地址 (高20位):
0x00099
。这意味着我们需要的二级页表,存放在物理页帧号为0x00099
的地方。其物理基地址是0x00099000
。 -
存在位 P (bit 0):
1
,表示这个二级页表在内存中,有效。 -
其他控制位...
第三步:查找页表项 (PTE)
现在我们已经拿到了二级页表的“指针”,继续寻址。
-
定位二级页表: 根据上一步PDE提供的信息,我们知道二级页表的物理基地址是
0x00099000
。 -
计算PTE地址:
-
我们要找的PTE是这张二级页表中的第
p2
(=644
) 项。 -
每个PTE大小为4字节。
-
所以,目标PTE的物理地址 = 基地址 + 索引 * 表项大小
= 0x00099000 + 644 * 4
= 0x00099000 + 2576 (十进制)
= 0x00099000 + 0xA10 (十六进制)
= 0x00099A10
-
-
获取PTE内容:
MMU从物理地址 0x00099A10 处读取到4个字节的PTE内容。我们假设读到的内容是 0x00785067。
表格三:二级页表中的第644项 (PTE)
物理地址 | 索引 (p2) | PTE内容 (十六进制) | PTE内容 (二进制) |
---|---|---|---|
0x00099A10 |
644 | 0x00785067 |
0000 0000 0111 1000 0101 0000 0110 0111 |
解读这个PTE (0x00785067
):
-
物理页帧号 (高20位):
0x00785
。这就是我们最终要找的数据所在的物理页帧号!它的物理基地址是0x00785000
。 -
存在位 P (bit 0):
1
,表示这个数据页在内存中,有效。 -
其他控制位...
第四步:形成最终物理地址
寻宝图的最后一步,拼接最终地址。
-
获取物理页基地址: 从上一步的PTE中,我们得到了物理页帧号
0x00785
,其对应的物理基地址是0x00785000
。 -
获取页内偏移: 从第一步分解逻辑地址时,我们得到了页内偏移
d
,其值为0x3C5
。 -
计算最终物理地址:
-
最终物理地址 = 物理页基地址 + 页内偏移
= 0x00785000 + 0x3C5
= 0x007853C5
-
结论:逻辑地址 0x016843C5
经过二级页表的转换,最终映射到了物理地址 0x007853C5
。
问题一:“页目录项都是20bit吗?”
答:不是。这是一个非常普遍的误解,但非常关键。
一个页目录项 (PDE) 本身是一个完整的数据结构,在32位系统中,它通常是32位(即4字节)。
你提到的“20bit”是页目录项内部一个非常重要的字段的长度,即**“页表的物理基地址”**字段。
让我们把一个32位的页目录项(PDE)想象成一个信息卡片,这张卡片被分成了两部分:
-
核心信息区(20位): 用来存放它所指向的那个二级页表的物理基地址(或者说是物理页帧号)。
-
控制/状态信息区(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) 的结构中,绝对不包含页内偏移量。
原因在于它们在地址转换过程中扮演的角色是完全不同的:
-
页目录项(PDE)和页表项(PTE)的使命:
它们的唯一使命是将逻辑地址中的“页号”部分翻译成物理地址中的“页帧号”部分。它们是“页到帧”的翻译官。
-
页内偏移(d)的使命:
页内偏移量的使命是在已经找到的那个正确的物理页帧内部,定位到具体的字节地址。它是“帧内寻址”的导航员。
地址转换流程清晰地体现了这一点:
-
CPU拿出逻辑地址中的
p1
部分去查页目录表,找到对应的 PDE。 -
从PDE中取出页表的地址。
-
CPU拿出逻辑地址中的
p2
部分去查这个页表,找到对应的 PTE。 -
从PTE中取出最终物理页帧的地址。
-
直到此时,CPU才拿出逻辑地址中的
d
(页内偏移) 部分,与上一步得到的物理页帧地址相加,形成最终的物理地址。