从广义上讲,我想知道内核(或 CPU)如何知道一个进程试图访问它没有权限的内存位置,以及名为 MMU 的神秘硬件如何帮助做到这一点。
特别是:在我看来,MMU 对操作系统内核的内存管理模型(分页、内存区域、进程地址空间......)是不可知的(我认为 Linux 和 Windows 页面并不完全相同,因为示例。如果我错了,请纠正我)。但是,我的 CPU 是如何判断当前代码是否可以访问 location 的x
呢?它如何向内核发出信号?
从广义上讲,我想知道内核(或 CPU)如何知道一个进程试图访问它没有权限的内存位置,以及名为 MMU 的神秘硬件如何帮助做到这一点。
特别是:在我看来,MMU 对操作系统内核的内存管理模型(分页、内存区域、进程地址空间......)是不可知的(我认为 Linux 和 Windows 页面并不完全相同,因为示例。如果我错了,请纠正我)。但是,我的 CPU 是如何判断当前代码是否可以访问 location 的x
呢?它如何向内核发出信号?
这可能是一个太大的话题,无法在这里完全令人满意地回答;您最好搜索一些讨论虚拟内存实现背后的硬件的论文/文章/书籍(可能从特定架构开始,因为例如 x86、x86_64、sparc 等之间存在显着差异......)。
不过,简短的回答是硬件通过页表来处理这个问题。要求 MMU 处理的每个内存访问都通过页表结构进行验证。如果描述包含所请求地址的页面的页表条目未标记为允许所请求的访问类型(读/写/执行/...),则硬件会生成一个陷阱,Linux 最终将其称为“分段错误” . 其他操作系统以不同的方式命名它们(例如,一般保护故障,...)。然后操作系统内核必须找出故障的原因以及是否可以采取任何措施(许多陷阱由内核处理以从磁盘交换新页面,映射新的空页面等,但有些陷阱,例如空指针解引用,内核能做的最好的事情就是把它扔给应用程序说“
MMU 被配置(通过设计其逻辑和/或内核设置的选项位)作为分页模型实现的硬件部分。
MMU 通常必须将逻辑地址转换为映射的物理地址;当它因为请求的逻辑地址没有对应的物理地址而无法这样做时,它会生成一个错误(通常作为一种中断类型),该错误会在内核中运行处理程序代码。
如果错误是试图请求理论上存在的东西——比如映射文件的一部分——但当前不存在于物理内存中,操作系统的虚拟内存实现可以通过分配一些物理内存并复制适当的磁盘块来解决问题进去。
但是,如果是对不存在的东西的请求,则无法满足,必须作为程序错误处理。
写入不允许写入的内容的请求将以类似的方式处理。
在我的脑海中,我不确定是否在 MMU 中或在 CPU 本身中检测到执行不可执行信息的尝试;指令缓存(如果存在)如何适应这也可能使事情复杂化。但是,最终结果将是相似的 - 发生非法执行尝试的内核故障条件,内核通常会将其视为程序故障。
总之,该模型是更简单的硬件层告诉内核发生了一些不寻常的事情,而硬件使用其当前配置无法自行处理。操作系统然后决定尝试的操作是否可以并且应该发生 - 如果是,它会更新硬件配置以使其成为可能。或者,如果不应该允许尝试的操作,则声明程序错误。并且还有其他可能性,例如,虚拟化层可以决定模拟请求的操作而不是实际执行它,从而与硬件保持一定的隔离。