Appearance
6.1810 2024 第7讲:页错误
虚拟内存的妙用
虚拟内存不仅仅是为了隔离,它提供的“间接层”为内核实现各种酷炫功能提供了机会。本讲的核心思想是:在发生页错误 (Page Fault) 时动态地修改页表。
- 页错误是一种陷阱(trap),类似于系统调用。当一个进程试图访问一个无效的或权限不足的内存地址时,CPU会暂停该进程,并将控制权交给内核。
- xv6的默认行为是直接
panic,但我们可以做得更好:内核可以修复页表中的问题(例如,分配一个物理页),然后让进程从出错的指令处重新开始执行。
利用这个机制,我们可以实现:
- 更好的性能/效率:
- 写时复制 (Copy-on-Write) Fork:
fork()时,父子进程可以共享所有物理页面,并将它们标记为只读。当任何一方尝试写入时,会触发页错误,此时内核才真正复制该页面。 - 按需零填充页: 当应用需要一个全零页面时,内核可以映射到一个全局的、只读的全零物理页。当应用写入时,再为其分配一个新的、可写的零页。
- 写时复制 (Copy-on-Write) Fork:
- 为程序员提供便利:
- 惰性分配 (Lazy Allocation):
sbrk()系统调用可以只增加进程的虚拟内存大小,而不实际分配物理内存。直到应用第一次访问该地址范围时,通过页错误来按需分配物理页。 - 内存映射文件 (Memory-Mapped Files): 允许应用将文件的一部分直接映射到其地址空间,像访问内存一样读写文件。内核会在访问时按需从磁盘加载页面。
- 惰性分配 (Lazy Allocation):
RISC-V 中的页错误
- 当页错误发生时,CPU会将一些关键信息存入
s系列寄存器,以便内核处理:stval: 导致错误的虚拟地址。scause: 错误的类型(是读取、写入还是执行指令导致的错误)。sepc: 发生错误时,用户程序的程序计数器(PC)。
虚拟内存的演进
虚拟内存技术仍在不断发展,以应对新的硬件和安全挑战:
- KPTI (Kernel Page-Table Isolation): 为应对 Meltdown 攻击,现代操作系统将内核页表与用户页表完全分开,xv6也采用了类似的设计。
- 多级页表: 为了支持更大的地址空间(例如57位),页表的层级也在增加。
- 大页面 (Huge Pages): 支持2MB或1GB的大页面,可以减少TLB的压力,提高性能。
总结
分页和页表提供了一个强大的间接层,是现代操作系统实现内存管理、性能优化和安全隔离的核心机制。在接下来的实验中,你将亲手实现写时复制等功能,深入理解其工作原理。