avatar

Catalog
PDE_PTE属性(部分)

上一篇文章中了解了PDE和PTE,这一篇就来了解一下PDE和PTE的属性。

物理页的属性

一上来看这张图,肯定是一脸懵逼的。先从行开始看,第一行是关于CR3寄存器的,这部分留到控制寄存器的章节再分析。接下来三行是不同类型PDE的,最后两行是PTE的。其中PDE和PTE有很多属性是重合的。而物理页的属性,就是有PDE和PTE共同决定的。计算方法是将相同属性位的值进行与运算。

物理页的属性 = PDE属性 & PTE属性

P位

首先来看P(Present)位:存在位。PDE与PTE的P位均位1时,物理页有效;其余情况,物理页不存在。这也解释了为什么PDE的第三行和PTE的第二行可以直接忽略。

在上一篇文章中,有一个关于0地址赋值的实验。0地址之所以不能赋值是因为它的PTE的P位为0,在我们修改了PTE的P位,并给它挂上一个物理页后,0地址遍可以赋值了。

R/W位

  • R/W = 0 只读
  • R/W = 1 可读可写

R/W很好理解,控制写的权限呗,这个位有何用呢?来看一个小实验。

c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include "stdafx.h"

int main(int argc, char* argv[])
{
char* str = "hello";
printf("%x", str);
getchar();

*str = 'a';


printf("%s", str);
getchar();
return 0;
}

来看这个代码,很明显,执行会是失败的,因为用char*定义的字符串,是会存储在常量区,而不是堆栈中了,又因为常量区的值是不允许修改的,因此

c
1
*str = 'a';

这条语句会执行失败并报错。

那为什么常量区的内容就不可修改呢?其实,说白了,就是常量区挂着的物理页的R/W属性为0,因此只能读,不可写,既然知道了原因,我们只要修改了常量区所在物理页的属性,将R/W位置1即可。

通过printf语句先打印出所在常量区的线性地址,接着拆分跟进PDE和PTE中(具体步骤省略)

可以发现,PTE的R/W位值为0,因此将其修改为1写入,随后运行程序发现,可以成功修改字符串首地址出的字符!

P/S位

P/S(PageSize)位,只对PDE有意义,位于PDE的第7位。

  • PS = 1 PDE直接指向物理页,无PTE,低22位为页内偏移。线性地址只能拆成两段(10-22):页的大小为2的22次方,也就是4MB,俗称“大页”,大页比较少,一般出现在高2G中
  • PS = 0 就是我们比较熟悉的10-10-12分页,页的大小为4KB

U/S位

U/S(User/System)位,位于PDE/PTE的第2位。

  • U/S = 0:特权用户

  • U/S = 1:普通用户

三环程序是不能读写高2G内存的,原因在于高2G内存对应的物理页U/S位被置0了,也就是说只有特权用户才能读写高2G的内存。所以,当普通用户想要读取高2G内存时,就可以把U/S置1,这样就可以访问高2G内存了。

当然,理论如此,不过除了U/S位外,影响高2G内存读写的还有PCD位和PWT位,这部分内容也要到控制寄存器部分才能讲,所以第二种3环程序读写高2G实验(第一种是通过门提权),就要放到后面实现了,这里只要先记住,U/S位是影响访问读写权限的。

与R/W的区别

这里需要注意一下U/S位与R/W位的区别,U/S位的读写控制是根据用户的级别,而R/W位的控制是直接控制读写,不管你是不是特权用户。

A位

A(Accessed)位于PDE/PTE的第5位:表示该物理页是否被访问(读或者写)过,访问过置1,即使只访问一个字节也会导致PDE,PTE置1。

D位

D(Dirty),脏位,是否被写过。0表示没有被写过,1表示被写过

总结

以上是关于PDE/PTE部分属性的含义,还有一部分位没有涉及到,例如G位,PWT位,PCD位,这些需要讲到控制寄存器和TLB相关概念时再细讲。

Author: cataLoc
Link: http://cata1oc.github.io/2020/03/19/PDE-PTE%E5%B1%9E%E6%80%A7/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Donate
  • 微信
    微信
  • 支付寶
    支付寶