Files
2026-03-22 17:40:44 +08:00

3.5 KiB
Raw Permalink Blame History

既然你已经理解了 task_structmm_struct 再到 vm_area_structVMA这一套“账本”系统那么**页表项Page Table Entry, PTE**就是这个系统中最后也是最关键的“映射条目”。

简单来说VMA 只是在内核里划地盘(虚拟地址范围),而 PTE 才是真正把虚拟内存指向物理内存的“指路牌”

在 x86-64 架构下,一个标准的页表项通常是 64 位8 字节)。我们可以把它拆解为两个核心部分:物理页框号PFN标志位Flags


1. 页表项的逻辑构成

一个 PTE 的 64 位并不是乱排的,它的结构大致如下:

位范围 (Bits) 名称 作用
0 P (Present) 存在位。1 表示在物理内存中0 表示不在(可能在 Swap 分区或未分配)。
1 R/W (Read/Write) 读写位。0 表示只读1 表示可读写。
2 U/S (User/Supervisor) 权限位。0 表示仅内核可访问1 表示用户态也可访问。
3 PWT / PCD 缓存策略控制(通常由驱动或内核底层管理)。
5 A (Accessed) 访问位。只要该页被读或写过,硬件会自动置 1。这是 LRU 换出算法的重要依据。
6 D (Dirty) 脏位。页面被写入过则置 1。如果是脏页换出时必须写回磁盘。
7 PS (Page Size) 决定这是指向 4KB 页还是 2MB 大页。
12 ~ 51 Physical Address 物理地址PFN。这是最核心的部分,存放 4KB 对齐的物理内存基地址。
63 NX (No-Execute) 禁止执行位。如果置 1该页的数据不能作为指令执行防范缓冲区溢出攻击

2. 为什么地址位只有 12-51 位?

你可能会好奇,为什么物理地址不占满整个 64 位?

  • 低 12 位0-11:由于内存页通常是 4KB 对齐的($2^{12} = 4096$),物理地址的低 12 位永远是 0。所以这 12 位被挪作他用,变成了上面的 P, R/W, A, D状态标志位
  • 高位:目前的处理器通常只支持 48 位或 52 位的物理寻址,所以 52 位之后的部分目前是保留或用于特殊属性(如 NX 位)。

3. 与 VMA 的协作关系

这是一个非常容易混淆的点:VMA 里有权限PTE 里也有权限,听谁的?

答案是:两者共同作用,取交集。

  1. 第一关 (软件检查):当你访问一个地址,内核先去红黑树找 VMA。如果 VMA 标记这块地只能读,而你想写,内核直接发 SIGSEGV(段错误)。
  2. 第二关 (硬件检查):如果 VMA 允许,但 PTE 里的 R/W 位是 0比如因为“写时复制” Copy-on-Write 机制CPU 硬件会触发缺页中断,让内核来处理。

4. 深度思考:脏位 (Dirty Bit) 的意义

对于你这种偏向底层研究的开发者来说,Dirty Bit 非常重要:

  • 如果一个物理页是“干净”的(和磁盘内容一致),内存紧张时可以直接丢弃。
  • 如果 Dirty Bit 是 1说明数据被改过了内核必须先把它同步回磁盘Swap 或文件系统),才能回收这个页。

接下来你可能感兴趣的:

既然页表项这么精细,但在 64 位系统下,如果每个进程都搞一个平铺的页表,会占用巨大的内存(几个 GB 甚至更多)。

你想了解一下 Linux 是如何通过“多级页表Multi-level Page Tables”来节省这些空间的吗