进程地址空间
概要:介绍 xv6 进程地址空间:内存映射的初始化流程、用户空间与内核空间的布局划分、直接映射机制,以及“内核借用用户页表”双重映射设计带来的无缝切换与安全隔离优势。
1. 内存映射的初始化
在内核启动初期,内存映射经历了一个从“粗放”到“精细”的过程:
- 初期阶段 (
entry.S):建立初步页表,仅提供足以维持内核 C 代码运行的基础映射。 - 精细化阶段 (
main调用kvmalloc):内核立即切换到由kvmalloc生成的新页表。- 目的:提供更精巧、更完整的内存布局映射。
- 切换机制:每个进程拥有独立页表,xv6 会在进程切换时通知硬件(更新页表基址寄存器)以实现环境隔离。
2. 地址空间布局划分
xv6 的虚拟地址空间以 KERNBASE(通常为 2GB 处)为界,分为用户空间和内核空间:
| 区域 | 虚拟地址范围 | 映射说明 | 访问权限 |
|---|---|---|---|
| 用户空间 | $0$ 至 KERNBASE |
映射到进程私有的物理内存 | 用户模式可访问 ($PTE_U=1$) |
| 内核空间 | KERNBASE 以上 |
包含内核代码、数据及 I/O 设备映射 | 仅内核模式访问 ($PTE_U=0$) |

3. 核心映射机制
用户内存动态管理
- 按需分配:当进程请求更多内存时,xv6 寻找空闲物理页,并在进程页表中添加对应的页表项 (PTE)。
- 标志位控制:通过 PTE 中的标志位确保安全:
PTE_P:存在位(未使用的空间该位为 0)。PTE_W:写许可。PTE_U:用户访问许可。
- 私有化实现:不同进程的页表将相同的虚拟地址映射到不同的物理页,从而实现内存隔离。
内核内存映射策略
- 直接映射:将虚拟地址
KERNBASE : KERNBASE + PHYSTOP直接映射到物理地址0 : PHYSTOP。- 便利性:使内核能够方便地通过虚拟地址读写特定的物理页(如创建页表页时)。
- I/O 映射:对于 $0xFE000000$ 之上的内存映射 I/O 设备,xv6 采用直接映射。
- 局限性:这种设计限制了 xv6 能够使用的物理内存最大不超过 2GB。
4. 设计总结:双重映射的优势
xv6 在每个进程的页表中同时包含用户和内核映射,这一设计实现了两个关键目标:
- 无缝切换:当用户进程通过系统调用或中断陷入内核时,由于内核映射已在当前页表中,不需要切换页表,极大地提高了执行效率。
- 透明性与安全性:
- 连续性:进程看到的内存是从虚拟地址 0 开始的连续空间,而物理上可以是分散的。
- 隔离性:通过严格控制
PTE_U标志位,确保进程无法越权访问其他进程的私有内存或内核敏感数据。
核心逻辑:内核在大多数情况下并没有“自己的”页表,它始终是在“借用”当前活跃用户进程的页表。
留下评论