首页 > 解决方案 > Linux 内核代码似乎忽略了缓存

问题描述

来自Understanding the Linux Kernel 3rd edition,第10.4.4章,其中讨论了内核访问用户空间内存时的页面错误异常:

页面错误处理程序 do_page_fault( ) 执行以下语句:

 if ((fixup = search_exception_tables(regs->eip))) {
 regs->eip = fixup->fixup;
 return 1;
 }

regs->eip 字段包含异常发生时保存在内核模式堆栈上的 eip 寄存器的值。如果寄存器中的值(指令指针)在异常表中,do_page_fault() 将保存的值替换为在 search_exception_tables() 返回的条目中找到的地址。然后页面错误处理程序终止,被中断的程序继续执行修复代码。

很好理解,除了一个关键的事实——内存操作可以被缓存,这意味着在缺页异常发生的那一刻,指令指针包含了另一条与异常无关的指令的地址,作为导致异常的指令被执行较早由 CPU 缓存,但直到此时才被缓存(参考最后几段中的内容)

Linux Kernel 如何在没有副作用的情况下执行上述代码?如何确定在页面错误异常发生时,指令指针寄存器包含访问非法地址的内存操作指令的地址(可以缓存并稍后执行)?

编辑#1: 我相信同一指南在第 2.4.7 章中有提示-

缓存单元插入在分页单元和主存之间

也许这意味着地址转换和签入总是在缓存之前(或期间)完成(至少在本指南所基于的 x86 架构中),这可以通过在 MMU 电路中完成地址签入来解释我的问题在指令执行的那一刻?不幸的是,我在指南和在线搜索中都找不到任何明确的“是”。

编辑#2:我在SuperUser中 找到了另一个来源,加强了我在编辑#1 中的推测:

在提交访问之前仍然需要检查权限

因此,似乎(没有任何来自正式来源的确认)在内存访问时,地址会在缓存之前或期间进入 MMU 电路进行翻译,这意味着地址检查是在指令执行时完成的,而此时正是可以引发页面错误。因此主存访问的缓存延迟与缺页时序无关,当缺页发生时,指令指针寄存器中确实包含了试图访问无效地址的故障指令。我将继续寻找可以证实这一点的来源,或者与该来源相矛盾并提供适当解决方案的来源。

标签: cexceptioncachinglinux-kernelkernel

解决方案


推荐阅读