c - 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 电路进行翻译,这意味着地址检查是在指令执行时完成的,而此时正是可以引发页面错误。因此主存访问的缓存延迟与缺页时序无关,当缺页发生时,指令指针寄存器中确实包含了试图访问无效地址的故障指令。我将继续寻找可以证实这一点的来源,或者与该来源相矛盾并提供适当解决方案的来源。
解决方案
推荐阅读
- html - CSS Grid - 在我的图像下方显示大量底部边距
- c# - 在 C#/Unity 中转换类型的问题
- function - 在较低级别(内存)增加/降低速度的情况下,程序中函数/方法的位置是否重要?
- c - 如何保证 write() 将通过套接字传输整个 int?
- python - 在 python 中使用 selenium 处理不可见元素/弹出窗口
- javascript - 将数据从 javascript 发布到 php 不起作用
- c# - Android设备管理器系统镜像下载错误
- input - beaglebone am355 u-boot switch bootpart by GPIO
- asp.net-core - Datatable.Net - 按列搜索未呈现
- kotlin - Plugin [id: 'org.jetbrains.kotlin.plugin.spring'] 在 buildSrc 目录下的 .gradle.kts 文件中定义插件时找不到错误