-4

在为特定进程分配逻辑内存空间后,通过使用基址寄存器限制寄存器来强制保护该空间。为了防止访问为进程分配的内存空间之外的内存,CPU 硬件将每个请求的内存地址与这些寄存器进行比较。如果以下两个条件之一成立,则会发生操作系统陷阱:

  1. 目标地址小于基址寄存器
  2. 目标地址大于或等于限制寄存器

这个逻辑可以在下面的图 7.2中直观地观察到。

图 7.2

以上解释了它们是如何发生的,例如

在用户模式下执行的程序访问操作系统内存或其他用户内存的任何尝试都会导致操作系统陷入陷阱。

但是,当请求的地址实际上超出程序分配的内存空间时,有哪些示例?什么会导致这个?

[图片和引用来源:操作系统要点,第 2 版。——亚伯拉罕·西尔伯沙茨]

4

1 回答 1

1

在实践中,当前的硬件(例如 x86-64 PC、ARM 平板电脑,...)不再使用基址和限制寄存器(但i286使用了),但有一个MMU

阅读有关MMU分页分段错误虚拟内存虚拟地址空间操作系统的信息:三个简单的部分(可免费下载)

但是,当请求的地址实际上超出程序分配的内存空间时,有哪些示例?

用户空间中的任何类型的分段错误,特别是取消引用指针(或某些“未初始化”指针变量,其中包含地址空间之外的随机位模式)。此类错误在 C 程序(在用户空间)中很常见。对于一个简化的例子:NULL

int *ptr = NULL;
/// some long code or execution which does not change the `ptr` value
*ptr = 34; // SEGMENTATION FAULT 

内核代码应该是可信的,并且不会出现任何分段错误(通过假设)。内核代码行为不端和取消引用无效地址会使计算机崩溃。

(在实践中,像 Linux 这样的大内核有一些代码可能会“部分”处理内核某些部分中的分段错误,例如某些驱动程序;但一般的想法是内核代码应该是可信的并且没有错误)。

顺便说一句,你的问题没有提到DMA(但你的评论有)。在实践中,DMA由内核管理(例如物理磁盘 I/O),内核在配置和启动它之前确保整个块地址都是有效的(并且分页)。因此,实际上 DMA 中的错误地址永远不会发生(取决于硬件 DMA 可以使用物理地址还是虚拟地址)。更一般地说,内核应该避免像分段错误或其他类型的错误地址这样的错误:用户空间可能有错误的地址(当这种情况发生时内核会产生分段错误,并且在 Unix 上会向应用程序发出一些SIGSEGV 信号),但是内核空间应该是只使用好地址的可信代码。

于 2018-05-11T05:38:23.157 回答