第 9 章 虚拟内存管理

  虚拟内存技术允许执行的进程不必完全处于内存,这种方案的一个主要优点是程序可大于物理内存。实现了逻辑内存和物理内存的分离,允许文件和内存通过共享页而为多个进程所共享。

  虚拟地址空间就是进程如何在内存中存放的逻辑视图。

  下面讨论如何实现虚拟内存。

9.1 请求调页

  如何从磁盘加载可执行程序到内存。一种选择是,在程序执行时将整个程序加载到物理内存,然而这种方法的一个问题是,最初不需要整个程序都存在内存,浪费内存资源。

  另一种策略是,仅在需要时才加载页面。这种技术称为请求调页(demand paging),常常用于虚拟内存系统。页面只有在程序执行期间被请求才会被加载。

  请求调页类似具有交换的分页系统,这里进程驻留在外存上,当进程需要执行时,通过调页程序,它被交换到内存中,仅交换需要的某个页面。

硬件支持

  这种方案需要一定的硬件支持,以区分内存的页面和磁盘的页面。8.5.3节所述的有效-无效位方案可用于这一目的。该位被设置为有效,表示相关联的页面合法且在内存中。该位为无效时,表示页面无效或有效但是在磁盘上。

  当进程执行和访问那些内存驻留的页面时,执行会正常进行。如果进程试图访问那些尚未调入内存中的页面时,对标记为无效的页面访问会产生缺页错误(page fault)。分页硬件在通过页表转换地址时会注意到无效位被设置,从而陷入操作系统。处理这种缺页错误的程序很简单:

  • 检查这个进程的内部表(通常与PCB一起保存),以确定该引用是有效还是无效的内存访问。
  • 如果引用无效,那么终止进程。如果引用有效但是尚未调入页面,那么现在就应调入。
  • 找到一个空闲帧。
  • 调度一个磁盘操作,以将所需页面读到刚分配的帧。
  • 当磁盘读取完成时,修改进程的内部表和页表,以指示该也所处于内存中。
  • 重新启动被陷阱中断的指令。

性能

  请求调页可以有效影响计算机系统的性能。

  设缺页错误率为 p 。

  有效访问时间 = (1 - p) x 内存访问时间 + p x 缺页错误时间

9.2 页面置换

  如果增加多道程度,那么可能会过度分配内存。

  内存的过度分配可能会出现错误。当用户进程正在执行时,可能会发生缺页错误。操作系统确定所需页面的磁盘位置,但却发现空闲帧列表上没有空闲帧,所有内存都在使用。这时,操作系统可以终止用户程序,但却不应该让用户意识到,对用户来说,调页应该是透明的。操作系统也可以交换出一个进程,来释放它的所有帧并降低多道程度。即页面置换。

9.2.1 基本页面置换

  修改缺页处理程序:

  1. 找到所需页面的磁盘位置。

  2. 找到一个空闲帧:

    a. 如果有空闲帧,那么就使用它。

    b. 如果没有空闲帧,那么就使用页面置换算法来选择一个牺牲帧。

    c. 将牺牲帧的内容写到磁盘上,修改对应的页表和帧表。

  3. 将所需页面读入空闲帧,修改页表和帧表。

  4. 从发生缺页错误位置,继续用户进程。

  需要注意的是,如果没有空闲帧,那么需要两个页面传输(一个调入,一个调出)。这种情况实际上加倍了缺页错误处理的时间,并增加了有效访问的时间。

  采用修改位(modify bit 或脏位(dirty bit))可减少这种开销。每个页面和帧都有一个修改位,两者之间的关联采用硬件。每当页面内的任何字节被写入时,它的页面修改位会由硬件来设置,以表示该页面被修改过了。

  当要选择一个页面进行置换时,就检查它的修改位。如果该位已被设置,表示该页面从磁盘读入后已被修改,这种情况下应将页面写入磁盘。如果该位未设置,那么表示还未被修改过,这种情况下,不需要将内存页面写到磁盘里,因为它已经存在。这种方案可用明显地降低缺页错误处理的数据,因为如果页面没有被修改,可以减低一半的 I/O 时间。

  为了实现请求调页,必须解决两个问题:

  • 帧分配算法 : 如果有多进程在内存中,必须决定要为每个进程分配多少帧。
  • 页面置换算法 :当页面需要置换时,必须选择要置换的帧。

  有效访问时间和缺页错误率成正比,所以我们通常采用缺页错误率最低的算法。

  为此,可以有这样的评估算法:针对特定的引用串,运行某个置换你算法,并计算缺页错误的数量。内存引用的串称为引用串。为了减少数据的数量,可以利用以下两个事实:

  • 对于给定的页面大小(通常由硬件或系统来决定),只需考虑页码,而非完整地址。
  • 如果有一个对页面 p 的引用,那么此后的对页面 p 的任何引用绝不会引起缺页错误。这是因为页面 p 在第一次引用后在内存中。

  下面讨论几种页面置换算法。

9.2.2 FIFO页面置换

  最简单的页面置换算法。FIFO页面置换算法为每个页面记录了调到内存的时间。当必须置换页面时,将选择最旧的页面。

  注意不需要记录确切时间,而是可以创建一个FIFO队列来管理使用内存页面。置换的是队列的首个页面,新调入的页面添加到队尾。

          

   FIFO页面置换性能不理想。如果一个页面早就初始化但任然在不停使用:

  请注意,即使选择正在使用的一个页面来置换,一切任然工作正常。只不过之后几乎会立即发生缺页错误,以取回活动页面。因此选择不当的置换会增加缺页错误率,并且减慢处理执行。

9.2.3 最优页面置换

  Belady异常:对于有些页面置换算法,随着分配帧数量的增加,缺页错误率可能会增加。

  发现Belady异常的一个处理是寻找最优页面置换,这个算法具有最低的缺页错误率,并且不会遭受Belady异常。被称为OPT或MIN,简单地说:

  置换最长时间不会使用的页面。

          

   最优置换算法难以实现,因为要预知未来。

9.2.4 LRU页面置换

  用最近的过去作为不远将来的近似,这种方法称为最近最少使用算法(Least-Recent-Used algorithm,LRU)。选择最长时间没有使用的页面。时间上向后看而不是向前看。

      

   它的问题是确定由上次使用时间定义的帧的顺序:计数器和堆栈。

9.3 帧分配

  ...

9.4 系统抖动

  如果进程没有需要支持活动使用页面的帧数,那么它很快会产生缺页错误。此时,必须置换某个页面,然而,由于它的所有页面都在使用,所以必须立即置换所需再次使用的页面。因此,它会再次快速产生缺页错误,再一次置换必须立即返回的页面,如此快速进行。

  这种高度的页面调度活动称为抖动。如果一个进程的调用时间多于它的执行时间,那么这个进程就在抖动。

系统抖动的原因

  操作系统监视CPU利用率。如果CPU利用率太低,那么通过向系统引入新的进程来增加多道程序。采用全局置换算法会置换任何页面,而不管页面属于哪个进程。

  假设进程在执行时需要更多的帧,它开始出现缺页错误,并从其他进程中获取帧。然而这些进程也需要这些页面,因此它们也会出现缺页错误,并且从其他进程中获取帧。,这些缺页错误进程必须使用调页设备以将页面换入和换出。当它们为调页设备排队时,就绪队列就会清空。随着进程等待调页设备,CPU利用率会降低。

  CPU调度程序看到CPU利用率的降低,进而会增加多道程序。新进程试图从其他运行进程中获取帧来启动,从而导致更多的缺页错误和更长的调页设备队列。因此CPU利用率进一步下降,并且CPU调度程序试图再次增加多道程度。这样就出现了抖动,系统的吞吐量骤降。缺页错误率显著增加。结果,有效内存访问时间增加,没有工作可以完成,因为进程总是忙于调页。

  

  通过局部置换算法或优先权置换算法可以限制系统抖动。

猜你喜欢

转载自www.cnblogs.com/astonc/p/12157048.html