天天看点

[windows内核]页目录表基址/页表基址一.页目录表基址二.页表基址

如果系统要保证某个线性地址是有效的,那么必须为其填充正确的PDE与PTE.

如果我们想填充PDE与PTE,那么必须能够访问PDT与PTT,这样就存在2个问题:

  1. 系统已经为我们访问PDT与PTT挂好了PDE与PTE,我们只用找到这个线性地址就可以了
  2. 系统是怎么帮我们挂好PDE与PTE的?

注意:

CR3中存储的是物理地址,不能在程序中直接读取的。如果想读取,也要把Cr3的值挂到PDT和PTT中才能访问,那么怎么通过线性地址访问PDT和PTT呢?

一.页目录表基址

页目录表基址 = 线性地址:0xC0300000

怎么来论证这个

0xC0300000

就是PDT的基址呢

首先随便找一个进程

[windows内核]页目录表基址/页表基址一.页目录表基址二.页表基址

拆分

0xC0300000

,寻找对应的物理页

0xC0300000

1100 0000 0011 0000 0000 0000 0000 0000

1100 0000 00   //0x300
11 0000 0000   //0x300
0000 0000 0000 //0x0
           
[windows内核]页目录表基址/页表基址一.页目录表基址二.页表基址

可以发现 物理页的内容 与 PDT表的内容 完全相同

所以我们可以得出结论

  1. 线性地址C0300000对应的物理页就是页目录表
  2. 这个物理页即页目录表本身也是页表
  3. 这个物理页是一张特殊的页表,每一项PTE指向的不是普通的物理页,而是指向其它的页表
  4. 访问页目录表的公式:C0300000 + PDI*4(I=index)
    [windows内核]页目录表基址/页表基址一.页目录表基址二.页表基址

二.页表基址

上面我们找到了PDT的基址,但如果我们要设置某个线性地址的PDE和PET那么还要能够访问PTT,那么如何访问呢?

页表基址 = 线性地址:0xC0000000

还是那个进程,这是PDT里的三张PTT表的基址

[windows内核]页目录表基址/页表基址一.页目录表基址二.页表基址

拆分

0xC0000000

十六进制:
	0xC0000000
	
	1100 0000 00   //0x300
	0000 0000 00   //0x0
	0000 0000 0000 //0x0
           
[windows内核]页目录表基址/页表基址一.页目录表基址二.页表基址

可以发现 每一项PTE所指向的物理页的内容 与 每一个PDE所指向的PTT表的内容完全相同

查看线性地址C0001000对应的PTT表

0xC0001000

1100 0000 0000 0000 0001 0000 0000 0000

1100 0000 00   //0x300
00 0000 0001   //0x1
0000 0000 0000 //0x0
           
[windows内核]页目录表基址/页表基址一.页目录表基址二.页表基址

发现线性地址C0001000指向的PTT表的第1项PTE为线性地址0xC0000000指向的PTT表的第2项PTE

通过上述的实验我们总结一下可以得知

  1. 其实页目录表(PDT)本不存在,是抽象出来的.
  2. 页表被映射到了从0xC0000000到0xC03FFFFF的4M地址空间
  3. 在这1024个表中有一张特殊的表:页目录表(PDT)
  4. 页目录被映射到了0xC0300000开始处的4K地址空间
  5. 访问页表的公式:

    0xC0000000 + PDI*4096 + PTI*4(I=index)

还是上面这个图

[windows内核]页目录表基址/页表基址一.页目录表基址二.页表基址

总结

  1. 有了

    0xC0300000

    0xC0000000

    能做什么:

    掌握了这两个地址,就掌握了一个进程所有的物理内存读写权

  2. 公式总结:

    访问页目录表的公式:

    C0300000 + PDI*4(I=index)

    访问页表的公式:

    0xC0000000 + PDI*4096 + PTI*4(I=index)