进程启动时分页(虚拟内存)系统中会发生什么情况



我正在学习Tanenbaum的"现代操作系统"一书,只是阅读了书中的以下段落:

当进程启动时,其所有页表条目都标记为不在内存中。一旦引用任何页面,就会发生页面错误。然后,操作系统设置 R 位(在其内部表中),以只读模式更改页表条目以指向正确的页,并重新启动指令。如果随后修改页面,将发生另一个页面错误,允许操作系统设置 M 位并将页面模式更改为读/写。

这对我来说似乎非常天真。他建议,当一个进程启动时,必须发生很多页面错误,并且在执行指令时,真正的内存被填满。

在我看来,至少进程的文本在开始时放在内存中似乎更合乎逻辑,而不是在每次指令执行时都放在内存中(每个指令执行都有页面错误)。

有人可以解释一下这本书解释的这种方法的优点是什么吗?

>Tanenbaum在这一段中描述了两种技术:

当进程启动时,其所有页表条目都标记为不在内存中。一旦引用任何页面>,就会发生页面错误。然后,操作系统设置> R 位(在其内部表中),将页表条目更改为指向正确的页,以只读模式>,然后重新启动指令。

此技术也称为按需分页(如果发生页面错误,则按需将页面从磁盘加载到内存)。我至少可以想到两个原因,为什么你想这样做:

    内存
  1. 消耗:只有真正需要的页面才会从磁盘加载到主内存中,程序的某些部分可能从未执行过,或者数据部分中的某些部分在执行过程中从未写入。在这种情况下,这些部分永远不会首先加载,这意味着您有更多的 RAM 可用于其他进程。如今,有了大量的内存,你当然可以争论这是否仍然是一个有效的论点。

  2. 速度:从磁盘加载很慢,十年前要慢得多。以懒惰的方式按需执行分页表设置允许延迟从磁盘获取的块。一次加载所有内容可能会延迟程序的执行。同样,磁盘现在要快得多,SSD使这一论点更加无效。另一方面,由于动态库,二进制文件不是那么大,通常只需要几个页面错误,直到它们加载到 RAM 中。

如果随后修改页面,将发生另一个页面错误,允许 操作系统设置 M 位并将页面模式更改为读/写。

同样,其原因是内存消耗。在过去,内存稀缺,交换(如果内存已满,则再次将页面移回磁盘)是为您提供更大工作页面集的错觉的解决方案。如果一个页面之前已经被换掉了,并且从未在中间修改过,你可以通过删除页表中的当前位来摆脱页面,从而释放页面之前占用的内存来加载另一个帧。修改后的位可帮助您检测是否需要将页面的新版本写回磁盘,或者您是否实际上可以保持旧版本不变,并在需要时将其重新交换回来。

您提到的设置预填充所有页表条目的进程(也称为预分页)的方法完全有效。您正在用内存消耗换取速度。页表遍历和设置修改后的位是在硬件(在 x86 上)实现的,这意味着它的性能并不差。但是,预填充可以使您免于执行页面错误处理程序,尽管通常经过大量优化,但在软件中实现。

最新更新