Linux x86_64架构下的四级分页机制详解
目录
一、x86_64分页概述
二、四级分页结构
三、地址转换过程
四、各级页表详解
1. PGD (Page Global Directory)
2. PUD (Page Upper Directory)
3. PMD (Page Middle Directory)
4. PT (Page Table)
五、页表条目结构
六、大页面支持
七、实际寻址示例
八、Linux内核中的实现
九、性能优化
一、x86_64分页概述
在x86_64架构下,Linux使用四级分页机制来管理虚拟内存到物理内存的映射。这种分级结构允许操作系统高效地管理巨大的地址空间(理论上256TB),同时保持内存使用的灵活性。
二、四级分页结构
x86_64架构下的四级分页包括以下层级:
- PGD (Page Global Directory) - 页全局目录
- PUD (Page Upper Directory) - 页上层目录
- PMD (Page Middle Directory) - 页中间目录
- PT (Page Table) - 页表
三、地址转换过程
一个64位的虚拟地址在分页过程中被划分为多个部分:
63 48 47 39 38 30 29 21 20 12 11 0
+-----------+--------+--------+--------+--------+-----------+
| 符号扩展位 | PGD索引 | PUD索引 | PMD索引 | PT索引 | 页内偏移 |
+-----------+--------+--------+--------+--------+-----------+
- CR3寄存器:存储当前进程的PGD物理地址
- 地址转换步骤:
- 从CR3获取PGD基址
- 用PGD索引找到PUD条目
- 用PUD索引找到PMD条目
- 用PMD索引找到PT条目
- 用PT索引找到最终的物理页框
- 结合页内偏移得到最终物理地址
四、各级页表详解
1. PGD (Page Global Directory)
-
每个进程有独立的PGD
-
存储在
mm_struct->pgd
中 -
上下文切换时会将其物理地址加载到CR3寄存器
-
通常占用9位索引(512个条目)
2. PUD (Page Upper Directory)
-
在x86_64中,PUD通常只使用一个条目
-
主要用于兼容性,为未来扩展预留
-
同样占用9位索引
3. PMD (Page Middle Directory)
-
中间级别的页目录
-
可以指向页表或更大的页面(如2MB大页)
-
占用9位索引
4. PT (Page Table)
-
最终级别的页表
-
直接指向物理页框
-
占用9位索引(512个条目)
-
每个条目映射一个4KB页面
五、页表条目结构
每个页表条目(PTE)是64位(8字节),包含以下重要字段:
63 62 61 52 51 32 31 12 11 9 8 7 6 5 4 3 2 1 0
+-------+-------+--------+-----------+-----------+-------++-+-+-+-+-+-+-+-+
| NX | | | 保留(软件) | 物理页基址 | Avail |D|A| | | |U|W|P|
+-------+-------+--------+-----------+-----------+-------++-+-+-+-+-+-+-+-+
关键标志位:
-
P (Present):页面是否在物理内存中
-
RW (Read/Write):可写权限
-
US (User/Supervisor):用户空间是否可访问
-
PWT/PCD:缓存控制
-
A (Accessed):页面是否被访问过
-
D (Dirty):页面是否被修改过
-
NX (No Execute):禁止执行位(安全特性)
六、大页面支持
x86_64支持多种页面大小:
-
4KB:标准页面,使用全部四级页表
-
2MB:大页面,绕过PT级别,直接在PMD中映射
-
1GB:巨大页面,绕过PMD和PT级别,直接在PUD中映射
大页面减少了TLB缺失,提高了内存访问性能。
七、实际寻址示例
假设48位虚拟地址0xFFFF800012345678的转换过程:
1. 符号扩展为64位:0xFFFFFFFF800012345678
2. 分解各部分:
- PGD索引:0x100 (第257项)
- PUD索引:0x000
- PMD索引:0x001
- PT索引:0x234
- 偏移:0x5678
3. 依次查询各级页表最终得到物理页框基址,加上偏移得到物理地址
八、Linux内核中的实现
关键数据结构:
// 页表条目
typedef struct { unsigned long pte; } pte_t;
// PMD条目
typedef struct { unsigned long pmd; } pmd_t;
// PUD条目
typedef struct { unsigned long pud; } pud_t;
// PGD条目
typedef struct { unsigned long pgd; } pgd_t;
关键宏和函数:
-
pgd_offset(mm, addr)
:获取PGD条目 -
pud_offset(pgd, addr)
:获取PUD条目 -
pmd_offset(pud, addr)
:获取PMD条目 -
pte_offset_map(pmd, addr)
:获取PTE条目
九、性能优化
- TLB (Translation Lookaside Buffer):缓存最近使用的地址转换
- PCID (Process Context ID):减少TLB刷新
- 延迟分配:实际访问时才分配物理页
- 反向映射:高效的反向查找(从物理页到PTE)
四级分页机制是x86_64架构高效管理大内存的关键,通过分级结构平衡了内存占用和查找效率。