首页 王道操作系统笔记-内存内存(27)-- 内存管理9
文章
取消

王道操作系统笔记-内存内存(27)-- 内存管理9

王道操作系统笔记-内存内存(27)– 内存管理9

虚拟内存1

为什么需要虚拟内存

进程必须全部被放入内存后才可以运行。但是如果进程的大小大于内存的容量,或者是内存中同时运行多个进程的话怎么办?我们可以通过覆盖这种方式来解决(之前笔记有。类似于c++内存管理使用union实现的嵌入式指针),但是需要让程序员做很多工作。所以我们可以通过逻辑上去扩充内存。

  • 从逻辑上去扩充内存,满足在小内存的机器上运行较多程序

  • 为进程提供统一的地址空间,简化内存管理
    • 每个进程都假设系统中只有自己存在。我们给每一个进程的地址都限制为0-4G,这样可以简化内存管理。因为每个进程有自己的页表,可以通过自己的页表去查询物理页面映射。
  • 保护进程地址空间不被其他进程破坏
    • 进程的隔离性也是由此而来。我们不希望其他进程去干扰本进程的地址。为了做到这一点,我们让不同进程的相同虚拟地址映射到不同的物理地址。这样进程不会直接访问物理地址而是间接访问。这样就不会发生冲突或者是误操作。

常规存储器的特征和程序的局部性理论。

  • 一次性作业在运行前需要一次性的全部装入内存

  • 驻留性作业装入内存后,便一直驻留在内存中,直到作业结束。

正是由于一次性和驻留性,使得程序中暂时不用的数据占用了大量的内存空间,从而需要运行的作业无法装入内存。但是这两个特性并不是必须的。因为程序不是所有的部分都被同时需要。

一般来说,在一段时间内,程序的执行仅局限于某个部分;相应地,它所访问的存储空间也局限于某个区域内(局部性原理)。

  1. 因为程序在执行时,除了少部分的转移和过程调用指令外,大多数仍是顺序执行的。

  2. 即使子程序调用将会使程序的执行由一部分内存区域转至另一部分区域,但是跳转至另一区域后仍然大概率是顺序执行的。

  3. 程序中存在许多循环结构,循环体中的指令被多次执行。(刚刚访问过的地址空间很可能马上又要访问)

  4. 程序中还包括许多对数据结构的处理,如对连续的存储空间——数组的访问,往往局限于很小的范围内。

局部性分为时间局部性和空间局部性

  • 时间局部性

    1. 如果程序中的某条指令一旦执行,则不久的将来该指令可能再次被执行;
    2. 如果某个存储单元被访问,则不久以后该存储单元可能再次被访问。
    3. 产生时间局限性的典型原因是在程序中存在着大量的循环操作。
  • 空间局部性

    1. 一旦程序访问了某个存储单元,则在不久的将来,其附近的存储单元也最有可能被访问。即程序在一段时间内所访问的地址,可能集中在一定的范围内,其典型原因是程序是顺序执行的。

虚拟内存

虚拟内存是一种允许进程部分装入内存就可以执行的技术。因为只有运行的部分程序需要在内存中。正因为如此,逻辑地址空间可以比物理地址空间要大,因为可以换入和换出。

  • 基于局部性原理,在程序装入时,可以将程序中很快会用到的部分装入内存,暂时用不到的部分留在外存,就可以让程序开始执行。
  • 在程序执行过程中,当所访问的信息不在内存时,由操作系统负责将所需信息从外存调入内存,然后继续执行程序。(请求调页/段)
  • 若内存空间不够,由操作系统负责将内存中暂时用不到的信息换出到外存。(页面/段置换)
  • 在操作系统的管理下,在用户看来似乎有一个比实际内存大得多的内存,这就是虚拟内存

虚拟内存有三个主要特征:

  1. 多次性:无需在作业运行时一次性全部装入内存,而是允许被分成多次调入内存。
  2. 对换性:在作业运行时无需一直常驻内存,而是允许在作业运行过程中,将作业换入、换出。
  3. 虚拟性:从逻辑上扩充了内存的容量,使用户看到的内存容量,远大于实际的容量。

虚拟内存技术,允许一个作业分多次调入内存。如果采用连续分配方式,会不方便实现。因此虚拟内存的实现需要建立在离散分配的内存管理方式基础上。

正如传统的非连续分配储存管理分为三种:基本分页,基本分段,基本段页式一样,虚拟内存也分为三种。即请求分页,请求分段,请求段页式

请求分页管理方式

  • 在程序执行过程中,当所访问的信息不在内存时,由操作系统负责将所需信息从外存调入内存,然后继续执行程序。(操作系统要提请求调页功能将缺失页面从存调入内存。)

    • 与基本分页管理相比,请求分页管理中,为了实现“请求调页”,操作系统需要知道每个页面是否已经调入内存:如果还没调入,那么也需要知道该页面在外存中存放的位置。
  • 若内存空间不够,由操作系统负责将内存中暂时用不到的信息换出到外存。(操作系统要提供页面置换的功能,将暂时用不到的页面换出外存)

    • 当内存空间不够时,要实现“页面置换”,操作系统需要通过某些指标来决定到底换出哪个页面:有的页面没有被修改过,就不用再浪费时间写回外存。有的页面修改过,就需要将外存中的旧数据覆盖,因此,操作系统也需要记录各个页面是否被修改的信息。

请求分页管理方式的页表

QQ截图20220720061957

缺页中断机构

在请求分页系统中,每当要访问的页面不在内存时,便产生一个缺页中断,然后由操作系统的缺页中断处理程序处理中断。 此时缺页的进程阻塞,放入阻塞队列,调页完成后再将其唤醒,放回就绪队列。

  • 如果此时内存中有空闲块,则为进程分配一个空闲块,将所缺页面装入该块,并修改页表中相应的页表项。
  • 如果此时内存中没有空闲块,则由页面置换算法选择一个页面淘汰,若该页面在内存期间被修改过,则要将其写回外存。(不写回数据不就丢了么)。未修改过的页面不用写回外存。

缺页中断是因为当前执行的指令想要访问的目标页面未调入内存而产生的,因此属于内中断的故障(fault)。一条指令在执行期间,可能产生多次缺页中断。(如: copy A to B,即将逻辑地址A中的数据复制逻辑地址B,而A、B属于不同的页面,则有可能产生两次缺页中断)

QQ截图20220720062408

缺页中断于一般中断的区别

  1. 缺页中断在指令执行期间产生和处理中断信号,而一般中断在一条指令执行完后检查和处理中断信号。
  2. 缺页中断返回到该指令的开始重新执行该指令,而一般中断返回到该指令的下一条指令执行。
  3. 一条指令在执行期间,可能产生多次缺页中断。

细节

  1. 只有“写指令”才需要修改“修改位”。并且,一般来说只需修改快表中的数据,只有要将快表项删除时才需要写回内存中的慢表。这样可以减少访存次数。

  2. 和普通的中断处理一样,缺页中断处理依然需要保留CPU现场。

  3. 需要用某种“页面置换算法”来决定一个换出页面(下节内容)

  4. 换入/换出页面都需要启动慢速的I/O操作,可见,如果换入/换出太频繁,会有很大的开销。

  5. 页面调入内存后,需要修改慢表,同时也需要将表项复制到快表中。

    • 在具有快表机构的请求分页系统中,访问一个逻辑地址时,若发生缺页,则地址变换步骤是:

      查快表(未命中)――查慢表(发现未调入内存)—―调页(调入的页面对应的表项会直接加入快表)――查快表(命中)――访问目标内存单元

本文由作者按照 CC BY 4.0 进行授权