# 分页机制

先说说最基本的未开启PAE时的10-10-12分页 (PDE为页表地址，PTE为物理页地址)

![](/files/-LnBsJF2FPKDbhQ6yPMd)

CR3存有页目录表的物理地址，页目录表有1024项，存有页表的物理地址，每张页表有1024项，存有物理页的地址。由于系统的内存通常都是按照4kb对齐，所以页目录表和页表中的地址的低12位都是保留位，另做他用。

但其实上面这种结构方式是错误的，正确的的结构方式是这样的：

![](/files/-LnBsJF46pT02kUOEtSG)

其实页目录表(PDT)本不存在，是抽象出来的.

* 页表被映射到了从0xC0000000到0xC03FFFFF的4M地址空间
* 在这1024个表中有一张特殊的表：页目录表
* 页目录被映射到了0xC0300000开始处的4K地址空间

所以我们就能根据线性地址计算所在物理页地址

**访问页目录表的公式： 0xC0300000 + PDI\*4**

**访问页表的公式： 0xC0000000 + PDI\*4096 + PTI\*4**

(PDI为页目录表偏移是线性地址高10位，PTI为页表偏移是线性地址的高12-21位)

**但本次实验环境 win7 x86 默认分页方式为 2-9-9-12分页，四页式。**

```
根据 CR3 找到 Page Directory Pointer Table
根据一级索引在 Page Directory Pointer Table 中查询到 Page Directory
根据二级索引在 Page Directory 中查询到 Page Table
根据三级索引在 Page Table 中查询到普通 4KB 物理页
在物理页中查找第四段偏移。
```

如下图：

![](/files/-Ld8E0o704wifcz5D5wH)

根据以上描述，第一段索引其实就是 Page Directory Pointer Table(PDPT) 这张表的索引。 下面的彩图也许能帮助你理解。

![](https://firebasestorage.googleapis.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LckC1dmB2Mb2F1Bgx_H%2Fuploads%2FJQKI9Vr3NKPfnGEQqUtu%2Ffile.png?alt=media)

这种分页方式不同于三段式，三段式分页最大只支持4GB内存寻址，intel把处理器的管脚数从32位增加到36个满足了更大的内存需求。

三段式分页中的 PDE 和 PTE 都是 4 字节，无论是 PDT 还是 PTT 都有1024个表项。而PAE分页中，PDPT只有 4 个表项，PDT 和 PTT 有 512 个表项，PDPTE、PDE、PTE 的大小是 8 字节。 PDPT 表一共占用 32 字节，PDT 、PTT 表仍然占用 4KB 的物理页。

这里列出它的PTE结构图：

![](/files/-LdE5xeQTV6gVxZCCPnS)

PTE结构的低12位同三段式分页仍然是属性，唯一的区别就是，Page Base Address 由原来的 20 位变成了现在的 24 位，相对以前扩展了 4 位。注意从 36-63 位这28位是保留位，不可用的。

这意味着，PTE 可以索引到的物理页页号由原来的 2的20次方 变成现在的 2的24次方，同样的，一个物理页大小是 4KB，那么PTE可以索引到的最大物理地址将会达到 2^24 \* 2^12 =64GB。

其实，PAE 所做的事情，只是把线性地址的 4GB 虚拟空间打散到了物理地址的64 GB 空间中。

形如图：

![](/files/-LdE5xeSADvDs_0qoKYB)

> 这里就直接给出该分页模式下 PDE 和 PTE 地址计算公式

addr 存放的是线性地址

```c
pPDE = (int*)(0xc0600000 + ((addr >> 18) & 0x3ff8));
pPTE = (int*)(0xc0000000 + ((addr >> 9) & 0x7ffff8));
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://b0ldfrev.gitbook.io/note/linux_operating_system/fen-ye-ji-zhi.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
