【发布时间】:2012-04-03 07:19:07
【问题描述】:
众所周知,当访问内存中不存在的页面时会导致页面错误,但是写入只读页面也会导致页面错误?在异常处理程序中如何识别这两种类型的缺页?
【问题讨论】:
标签: exception exception-handling operating-system x86 kernel
众所周知,当访问内存中不存在的页面时会导致页面错误,但是写入只读页面也会导致页面错误?在异常处理程序中如何识别这两种类型的缺页?
【问题讨论】:
标签: exception exception-handling operating-system x86 kernel
尝试写入只读通常会导致分段错误 (SIGSEGV)。
http://en.wikipedia.org/wiki/Segmentation_fault
我认为它在 x86 用语中称为访问冲突异常(内存访问冲突)。
【讨论】:
在调用页面错误处理程序之前,您读取了 CPU 放置在堆栈上的异常错误代码。此错误码包含 5 位,您对这 4 位感兴趣:
如果您得到 P=0,则页面不存在。
如果您得到 P=1,则权限不足,无法访问该页面。 U/S 会告诉您它是在内核中还是在应用程序中。 I/D 告诉您是否是因为代码指令读取(读取/写入数据)。 W/R 告诉你是读还是写不能完成。
这在Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 3: System Programming Guide 的Interrupt 14—Page-Fault Exception (#PF) 部分进行了描述。
【讨论】:
Alex 的回答完全正确,但是您还需要将该信息与您自己的一些信息结合起来(即通过查看内存管理器数据)。例如,某些操作系统在第一次引用它们之前不会分配支持内存的页面,因此如果您对不存在的页面进行读取或写入,您可能会发现它不存在的原因是你还没有分配它,你应该分配它并从异常中继续。类似地,对只读页面的写入可以作为写时复制机制的一部分发生(许多系统都这样做,最显着的是执行 fork() 时的 posix 样式系统),因此您可以检测到对只读页面的写入,检查内存管理器表并查看应该复制的页面,复制页面,更新页面表并继续。
我发现,Alex 提到的列表中唯一有趣的标志通常是表明它是读取还是写入的标志。除此之外,您还需要检查 MM 表中的所有其他内容。
【讨论】: