Windows

分页机制 2-9-9-12

名词解释:

PTE(Page Table Entry):页表项

  • PTE是页表中的一个条目,用于存储一个页面的物理地址和一些控制信息,比如页面是否有效、是否可读写等。通过页表,可以将虚拟地址转换为物理地址。

PDE(Page Directory Entry):页目录项

  • PDE是页目录中的一个条目,用于指向一个页表。每个PDE包含指向页表的物理地址和控制信息。页目录本身是一个包含多个PDE的表,用于管理多个页表。

PTT(Page Table):页表

  • 页表是一个结构,包含多个PTE。每个PTE指向一个物理页的地址。页表用于虚拟地址到物理地址的转换。在分层页表结构中,一个页表对应一个页目录项。

PDI(Page Directory Index):页目录索引

  • PDI是虚拟地址的一部分,用于索引页目录中的某个PDE。通过PDI,操作系统可以找到页目录中对应的PDE,从而找到指向的页表。

页目录索引(PDI, Page Directory Index):用于查找页目录中的某个页目录项(PDE)。

页表索引(PTI, Page Table Index):用于查找页表中的某个页表项(PTE)。

页内偏移(Offset):用于定位物理页内的具体字节。

控制寄存器

CR(Control Register)控制寄存器,这些寄存器只能在0环使用

寄存器名称 描述
CR0 包含处理器标志控制位,例如PE,PG,WP等
CR1 保留
CR2 专门用于保存缺页异常时的线性地址
CR3 保存进程页目录地址,切换进程用
CR4 扩展功能(如判断物理地址扩展模式等),Pentium系列(包括486的后期版本)处理器中才实现

CR0寄存器:

1722081811572

PE:启用保护模式标志,1是保护模式,0是实模式,这个位只是开始或关闭段机制,并没有启用分页机制。

PG:分页机制开关,在启用之前需要确保PE是开启的,否则会出现异常。

WP:写保护标志,禁止0环程序向3环只读页面执行写操作,也就是说当CPL<3的时候,如果WP=0,可以读写任意物理页,只要线性地址有效,如果WP=1,可以读取任意用户级物理页,但是对于只读的物理页,不能写 。

CR4寄存器

1722082069659

PAE (Physical Address Extension,物理地址扩展):
启用PAE可以使处理器支持超过4GB的物理内存寻址能力,增加到36位地址总线,从而支持高达64GB的物理内存。PAE=1开启
启用PAE后,页表结构会发生变化,使用三级页表:页目录指针表(PDP)、页目录(PD)和页表(PT)。
在启动选项 /nopae /pae 分别是关闭和开启PAE标志的指令

PSE (Page Size Extension,页大小扩展) :
PSE标志位是CR4寄存器的第4位(CR4.PSE)。启用PSE可以使处理器支持4MB的大页,从而减少页表开销,提高内存管理效率。 启用PSE后,页表结构中的页目录项(PDE)可以指向一个4MB的大页,而不是传统的4KB小页。

1722082317882

这个表列举了标志位组合起来的情况,(PS(在PDE里面)这个属于页表的标志位)

为什么放弃10-10-12分页机制?

参考: 80x86 2-9-9-12分页 - zpchcbd - 博客园 (cnblogs.com)

首先10-10-12分页模式这个成品是基于设计者的想法而产生的,先要确定的肯定是页的大小也就是4kb大小,那么也就是2^12 -> 4KB大小

那么还剩下”10” “10” 接着又设计PDE和PTE,通过PTE的前20位再加上12位的偏移,那么也就是4G寻址范围(那当时的情况寻址能力已经能足够了)

But,计算机在发展,4G的寻址能力无法满足越来越大的内存,所以开启了新的2-9-9-12分页机制

有什么办法在32位cpu下如何能够提高物理地址的寻址范围呢?

这里就引入了2-9-9-12的分页模式,又被叫做为PAE物理地址扩展

1、页的大小是确定的,4KB不能随便改,所以低12位是可以确定的

2、如果想增大物理内存的访问范围,就需要增大PTE,增大多少了呢?需要找到64G,那么增大到36位,但是还需要考虑对齐的因素,所以对齐到8个字节

知识点:在Windows系统中,对齐大小有利于高效率的执行和搜索

2-9-9-12分页结构

1.页的大小是确定的,4KB不能随便改,所以32位的最后一部分就确定为了12位。

2.如果想增大物理内存的访问范围,就需要增大PTE,增大了多少呢? 需要找到64G,那么增大到36位,考虑对齐的因素,增加到8个字节
由于PTE增大了,而PTT表的大小没变,依然是4KB,所以每张PTT表能放的PTE个数由原来的1024个减少到512个,512等于2的9次方,因此PTI=9

3.由于2的9次方个PDE就能找到所有的PTT表,因此PDI=9

4、同理PDI也是2的9次方 32 - 9 - 9 - 12 还差2位 所以就再做一级叫PDPI(页目录指针表)

知识点:这里需要让PDI也是2的9次方的原因,其实也是就是为了通过PDE同样可以定位到PTE,举个例子,此时2-9-9-12分页下,当前的PTE的前24位是4GB范围以外的,那么如果PDE不是跟PTE同样的结构,那么PDE的前24位就没有,也就是无法找到4GB范围以外,所以为了能够让PDE能够定位到4GB以为的PTE,所以也需要”9”

表结构

PDE结构:

(PS=1为大页的情况下)

当PDE里面的标志位PS位为1的时候,该PDE指向的物理页是大页,35-21位是大页的物理地址,这样36位的物理地址的低21位为0,这就意味着页的大小为2MB,且都是2MB对齐。

1722309871541

(PS=0)

2-9-9-12的9位,它是PDE,这个每项占8个字节,如下图所示

当PS=0时,第35-12位是页表基址,低12位补0,共36位。

1722309905324

P (Present) (第0位):

  • 指示该PDE是否有效。1表示有效,0表示无效。

RW (Read/Write) (第1位):

  • 指示页面是否可写。0表示只读,1表示可读写。

US (User/Supervisor) (第2位):

  • 控制访问权限。0表示内核模式,1表示用户模式。

PWT (Page-level Write-Through) (第3位):

  • 控制缓存写通策略。

PCD (Page-level Cache Disable) (第4位):

  • 控制是否禁用缓存。

A (Accessed) (第5位):

  • 标记该页是否被访问过。

0 (第6位):

  • 保留位,必须为0。

PS (Page Size) (第7位):

  • 指示页的大小。0表示4 KB页,1表示2 MB页(PAE模式下不使用4 MB页)。

G (Global) (第8位):

  • 标记全局页。当启用CR4中的PGE位时,全局页在上下文切换时不会刷新TLB。

0 (第9位):

  • 保留位,必须为0。

Reserved (第10-11位):

  • 保留位,必须为0。

Base Address (第12-35位):

  • 页表的物理基地址,指向下一级的页表(对于4 KB页)

Reserved(set to 0,第36-63位):

  • 保留位,给下一代cpu

PTE

2-9-9-12的9位,它是PTE,这个每项占8个字节,如下图所示

PTE中第35-12是物理页基址,24位,低12位补0物理页基址+12位的页内偏移指向具体数据

1722310011530

PAT用于指定页面的缓存属性的。它与页属性表(Page Attribute Table)一起工作,允许操作系统指定不同的缓存策略以优化内存访问。

PDPTE(Page-Directory-Point-Table-Entry):

2-9-9-12最高的2位,它是页目录指针表项,这个每项占8个字节,如下图所示

1722310064183

P (Present) (第0位):

  • 表示页目录指针表项是否有效。1表示有效,0表示无效。

RW (Read/Write) (第1位):

  • 指示指向的页是否可写。0表示只读,1表示可读写。

US (User/Supervisor) (第2位):

  • 控制访问权限。0表示内核模式,1表示用户模式。

PWT (Page-level Write-Through) (第3位):

  • 控制缓存写通策略。

PCD (Page-level Cache Disable) (第4位):

  • 控制是否禁用缓存。

保留位 (第5-8位):

  • 通常设置为0,不被使用。

Reserved (第9-11位):

  • 保留位,通常为0。

Page-Directory Base Address (第12-35位):

  • 指向页目录的物理地址

Reserved(set to 0):

  • 通常设置为0,不被使用

整体的2-9-9-12架构

先查页目录指针表确定是哪一个页目录表项,占两位,有2^2=4种可能

然后查询页目录表找到页表,由2^9=512种可能

然后查询页表项,有2^9=512种可能

所以总共能映射的内存是4 * 512 * 512* 4k = 4M(一个分页为4K)

如果一个分页大小是4M,那么就没有页表了

1722310099116

逻辑地址转物理地址实战

因为分段机制已经没啥用了,所以 逻辑地址 = 线性地址

现在我们来转换一下0x11A2014这个地址

1722329906119

0x11A2014拆成二进制为:00 000001000 110100010 000000010100

页目录指针index 0
页目录index 0x8
页表index 0x1A2
偏移 0x14

根据页目录指针找到页目录表基地址,加下标得到页目录表项地址:

1
2
1: kd> !dq cr3+0*8
#3eed23a0 00000000`167dc801 00000000`3addd801

分解一下,页目录表的基地址为0x167dc000,属性为0x801,最低位为1,所以是有物理内存映射的

页目录表项地址为0x167dc000 + 0x8*8

根据页目录表项找到页表基地址,加下标得到页表项

1
2
1: kd> !dq 0x167dc000 + 0x8*8
#167dc040 00000000`3c765867 00000000`00000000

分解一下,得到页表基地址为0x3c765000(如果有页表),属性为0x867,查看属性,重点看第0位和第7位,说明物理地址有效并且分页大小为4K,说明有页表

所以页表项地址为0x3c765000+0x1A2*8

根据页表项找到页框物理基地址,加偏移得到物理地址

1
2
1: kd> !dq 0x3c765000+0x1A2*8
#3c765d10 00000000`02df5025 00000000`0046b025

页框物理基地址为0x2df5000

最终物理地址为0x2df5000+0x14=0x2df5014

发现最终也是成功对上了

1722330758974