分段故障如何在内部工作(内核/硬件)?

从广义上讲,我想知道内核(或CPU)如何知道进程试图访问它缺少权限的内存位置,以及称为MMU的神秘硬件如何帮助实现这一点。

特别是:在我看来,MMU对操作系统内核的内存管理模型(分页,内存区域,进程地址空间……)是不可知的(我认为Linux和Windows页面不完全相同,因为例如,如果我错了,请纠正我。 但是,我的CPU如何确定当前代码是否可以访问位置x ? 它如何向内核发出信号?

这可能是一个太大的话题,无法在这里完全满意地回答; 你会更好地搜索讨论虚拟内存实现背后的硬件的一些论文/文章/书籍(可能从特定的架构开始,因为例如x86,x86_64,sparc等之间存在显着差异……)。

简而言之,硬件是硬件通过页表处理这个问题。 要求MMU处理的每个内存访问都通过页表结构进行validation。 如果描述包含所请求地址的页面的页表条目未标记为允许所请求的访问类型(读/写/执行/ …),则硬件会生成一个陷阱,Linux最终将其称为“分段错误” 。 其他操作系统以不同的名称命名(例如一般保护错误,……)。 操作系统内核然后必须找出故障的原因以及是否可以对其进行任何操作(内核处理许多陷阱以从磁盘交换新页面,映射新的空页等,但有些,如空指针解除引用,内核可以做的最好的事情是将它扔到应用程序中说“你做了坏事”。

MMU被配置(通过其内核设置的逻辑和/或选项位的设计)作为分页模型的实现的硬件部分。

MMU通常必须将逻辑地址转换为映射的物理地址; 当它不能这样做因为所请求的逻辑地址没有相应的物理地址时,它会产生一个故障(通常作为一种中断),它在内核中运行处理程序代码。

如果故障是尝试请求理论上存在的东西 – 比如映射文件的一部分 – 但目前不存在于物理内存中,操作系统的虚拟内存实现可以通过分配一些物理内存并复制相应的磁盘块来解决问题进去。

但是,如果它是对不存在的东西的请求,则不能满足它并且必须作为程序error handling。

写入不允许写入的内容的请求将以类似的方式处理。

在我的脑海中,我不确定是否在MMU中检测到执行非可执行信息的尝试或更多的CPU本身; 如果存在的指令缓存如何适用于那也可能使事情复杂化。 但是,最终结果将是类似的 – 内核发生非法执行尝试的错误条件,内核通常将其视为程序错误。

总之,模型是更简单的硬件层告诉内核发生了一些不寻常的事情,硬件无法使用其当前配置自行处理。 然后,操作系统决定是否可以并且应该发生什么 – 如果是,它会更新硬件配置以使其成为可能。 或者,如果不允许尝试的内容,则声明程序错误。 还有其他可能性,例如,虚拟化层可能决定模拟所请求的操作而不是字面上执行它,从而保留了与硬件的一些隔离。