OS 如何在不检查所有指针地址的情况下确定空指针访问?

how does the OS determine null pointer access without checking all pointer addresses?

已知0地址(标记为宏'NULL')是非法访问的。 我想知道操作系统(比如 linux)如何确定何时可以访问代码中某处的空地址,而不必访问代码中的每个指针地址? 我认为它与信号有关,特别是 "sigsegv" 信号。

但我不确定它是如何完成的。

NULL指针被取消引用或访问无效地址时,Memory Management Unit在异常触发中起着关键作用。

MMU 对每次 RAM 访问进行的正常虚拟到物理内存映射过程中,在 [= 中定义的虚拟地址范围内根本找不到未定义地址14=]。如果发生在 OS kernel-space 中,或者只是在 user-space 域中进程终止和清理,这可能会产生灾难性后果。

...how is it that the operating system (say linux) can determine when there is an access to null address, somewhere in the code, without having to access each and every pointer address in the code?

好吧,OS 无法在不访问指针的情况下确定 NULL 取消引用。来自 wiki 分段错误:

In computing, a segmentation fault (often shortened to segfault) or access violation is a fault raised by hardware with memory protection, notifying an operating system (OS) about a memory access violation; on x86 computers this is a form of general protection fault. The OS kernel will in response usually perform some corrective action, generally passing the fault on to the offending process by sending the process a signal....

内存访问违规是 运行 次事件,除非存在 无效 访问,否则 OS 无法提高向进程发出信号。

FWIW,允许进程访问为其分配的内存(在虚拟地址 space 中)。分配的虚拟地址 space 之外的任何地址如果被访问,将生成错误(通过 MMU),进而生成分段错误。

TL;DR - SIGSEV 是在遇到 NULL 指针取消引用时生成的,而不是在此之前。此外,OS 不会 检测到 错误访问本身,而是由 Memory Management Unit via raising a fault.

通知 OS

指针指向虚拟地址space。在虚拟地址space中,每内存都可以映射到真正的物理内存。操作系统为每个进程单独处理此映射。

当您通过指针访问内存时,CPU 查看您的指针指定的虚拟地址的映射,并检查后面是否有真实的物理内存。根据您正在尝试的操作,将进行额外的检查以验证您是否具有对该内存块的读取或写入权限。

如果没有为该地址映射的内存,CPU 会生成一个硬件中断。 OS 捕获该中断并且 - 通常 - 为调用进程发出 sigsegv 信号。

包含 NULL 地址的零页通常有意未映射,因此很容易陷入通常由编程错误引起的 NULL 指针访问。

Linux 从硬件上获得这种支持。处理器被告知各个内存区域的用途及其可用性。如果 "unavailable" 内存区域被访问,处理器将问题通知操作系统,操作系统通知应用程序。

这意味着两件事:

  • 没有与针对 NULL 值检查所有指针相关的软件开销。
  • 没有精确检查允许的指针值。

换句话说,如果您的指针指向 "available" 内存的任何位置,则硬件单元无法识别问题。

首先空指针访问不一定无效。通常,操作系统的程序加载器或链接器(取决于系统)设置进程,以便不映射虚拟地址 space 中的最低页面。

许多执行此操作的系统还允许应用程序映射第一页,使空引用有效。

检查 NULL 指针的方式与检查所有其他内存地址的方式相同:通过 CPU.

的逻辑地址转换

每次处理器访问内存(忽略缓存)时,它都会在进程页面 table 中查找地址。如果没有相应的条目,处理器会触发访问错误(在 Unix 变体中会被转换为信号)。

如果页面 table 中存在该地址的条目,处理器将检查该页面允许的访问。如果您处于用户模式并尝试访问内核保护页面,则会触发错误。如果您尝试写入只读页面,则会触发错误。如果您尝试执行非执行页面table,则会触发错误。

这是一个相当冗长的话题。如果您想了解有关该主题的更多信息,您需要了解逻辑内存翻译(有时误称虚拟内存)。