虚拟内存

虽然存储器容量增长快速,但是软件大小的增长更快。

操作系统必须能够支持多个程序同时运行,即使内存可以满足其中单独一个程序的需求,但总体上看,它们超出了内存大小—交换

甚至,需要运行的程序大到内存无法容纳—覆盖、虚拟内存

虚拟内存

覆盖

把程序分割成许多片段,逻辑上没有调用关系的段可以相互覆盖,称为覆盖段,这些段可以共享内存,覆盖段存放在磁盘上,需要时由操作系统动态地在内存和磁盘间换入换出。

覆盖段换入换出由系统完成,但是覆盖段的分割由程序员负责—增加了程序员的负担,因此,虚拟内存技术出现。

  • 程序段A是根程序
  • 覆盖区0:程序段B、C共享。其大小为B、C中所要求容量大者
  • 覆盖区1:程序段F、D、E共享
  • 该进程正文段所需要的内存空间是:
    • \(A(20K)+B(50K)+C(30K)+D(30K)+E(40K)=190K\)
  • 采用了覆盖技术,实际分配110K的内存空间

虚拟内存

虚拟内存的基本思想是:程序、数据和堆栈的总量可能超过可用的内存的大小。操作系统把程序当前使用的部分保留在内存中,而把其他部分保存在磁盘上。

虚拟存储器也可以工作与多道程序系统,在内存中同时由多个程序的片段。当一个程序等待它的一部分被调入时,它时等待I/O而不能运行,因此,可以把CPU交给另一个进程,就像任何其他多道程序系统中一样。

基于分页的虚拟存储器

  • 程序和内存按固定大小划分
    • 虚拟地址空间—页面
    • 物理内存—页框
  • 程序部分页面在内存,部分在磁盘
  • 访问到在磁盘的页面,操作系统负责钻杆如内存—交换(交换单位:页)

Q:和覆盖相比较,会不会引起频繁的交换?

虚拟内存—局部性原理

程序在执行构成中的一个较短时期,所执行的指令地址和操作数地址分别局限在一定区域内

  • 时间局部性

    一条指令的依次执行和下一次执行,一个数据的一次访问和下次访问都集中在一个较短时期内

  • 空间局部性

    当前指令和邻近的指令,当前访问的数据和邻近访问的数据都集中在一个较小区域内

分页

一些概念

页面程序按固定大小划分等长的页面

页框内存按相同大小划分,称为页框

将程序各页面装入内存空闲页框

不要求程序的所有页面顺序地装在连续的页框中(非连续

分页模式:

  • 程序一次全部装入
  • 程序可以不一次全部装入—虚拟内存

虚拟地址程序产生的地址。它们构成了一个虚拟地址空间

物理地址物理内存地址

页表:每个进程一个页表,记录页面到页框的映射,用于地址映射

内存管理单元(MMU):将虚拟地址映射为物理地址,如下图所示

例子

下图给出了一个说明了该映射时如何工作的简单例子。在这个例子中,有一台可以生成16位地址的计算机,地址范围从0到64K。这些地址是虚拟地址。但是,该计算机只有32KB的物理内存,因此,虽然可以编写64KB的程序,但是却不能将它们整个地载入内存运行。在磁盘上必须有一个64KB的程序内核映像,以保证程序片段在需要时载入内存。

页面大小在本例中是4KB,现有的系统中常用的页大小一般从512字节到64KB,对应与64KB的而虚拟地址空间和32KB的物理内存,它们分别有16个虚拟页面和8个页框。RAM和磁盘之间的传输总是以页为单位的。

分页分配原理

程序载入内存时,不必把所有页面都载入内存。只有部分页面在内存,而其余页面都在磁盘上。

当需要访问磁盘上的页面时,产生缺页中断,由操作系统负责把磁盘上的页面调入内存。

虚拟地址:0~64K-1

物理地址:0~32K-1

页表:页面到页框的映射

地址结构

根据页的大小确定页号和页内偏移。例如页大小是4KB(\(2^{12}\)KB),则需要12比特来表示页内地址,而剩余的高位则是页号。

地址映射

  1. 虚拟地址=页面号+页内偏移

  2. 查页表,页面号→页框号

  3. 页框号+页内偏移=物理地址

例1:MOV REG 0虚拟地址0映射过程

  • 0→MMU

  • \((0)_{10}\)\((0000\quad 0000\quad 0000\quad 0000)_2\)

    其中低12位是页内偏移:0000 0000 0000 0000

    剩余高位是页面号:0000

    虚拟地址=页面号+页内偏移

  • 根据页面号0查找页表,“在/不在”位为1,可直接得出对应于该页的页框号位010(表中的2的二进制)

    查页表,页面号→页框号

  • 页框号+页内偏移→物理地址

    0010 0000 0000 0000即8912

例2:把虚拟地址8912映射为物理地址

  • 8912→MMU

  • \((8912)_{10}\)\((0010\quad0000\quad 0000\quad 0000)_2\)

    其中低12位是页内偏移:0000 0000 0000 0000

    剩余高位是页面号:0010

  • 根据页面号0010查找页表,“在/不在”位为1,可直接得出对应于该页的页框号110(表中的二进制是6)

  • 页框号+业内偏移→物理地址

    0110 0000 0000 0000即24576

例2:把虚拟地址8912映射为物理地址(十进制的方法)

4KB的页面,即4096

  • 8192/4096

    • 商:2—页号
    • 余数:0—页内偏移
  • 通过页号2查页表—页框号110,即6

  • 页框号×页面大小+页内偏移→物理地址

    \(6\times 4096 + 0 = 24576\)

例3:虚拟地址20500映射为物理地址

20500→MMU

  • \((20500)_{10}\)\((0101\quad0000\quad 0001\quad 0100)_2\)

    其中低12位是页内偏移:0000 0001 0100(20)

    剩余高位是页面号:0101(5)

  • 根据页面号101查找页表,“在/不在“位为1,可直接得出该页的页框号011(3)

  • 页框号+业内偏移→物理地址

    0011 000 0001 0100即12308

例4:执行指令MOVE REG 32780

  • 32780→MMU

  • MMU判断32780属于虚页8

    1000 000000000100

  • 通过页面号查找页表,发现虚页8为映射(”在/不在“位为0)

  • 产生一个缺页中断(page fault),由操作系统寻找一个页框将它的内容写入磁盘,并将虚页8的内容取到刚才的页框中,并修改页表中的映射挂你

  • 页框号+业内偏移→物理地址

页表

在最简单的情况下,虚拟地址到物理地址的映射正如前面所描述的。虚拟地址被分为虚页号(高位)和偏移(低位)

虚页号可用作页表的索引,以找到该虚页对应的页表项。从页表项可以找到页框号。页框号被拼接到偏移的高位端,替换掉虚页号,以形成可以发送给内存的物理地址

页表的目的是把虚页映射到页框。从数学角度说,页表是一个函数,虚页号作为参数,物理页框作为结果。使用该函数的结果,可以把虚拟地址中的虚页域替换成页框域,从而形成物理内存地址。

页表项的结构

页面号:作为页表的索引

页框号:最重要的域。用于地址映射。

在/不在位:指出该页允许访问的类型,例如只读、读写等

修改位(脏位):记录页面的使用情况。在写入一页时由硬件自动设置该位

访问位:页面被访问时设置该位

高速缓存禁止位:用于映射到这杯寄存器的页面,通过该位禁止告诉缓存

页表设计

分页系统实现中的两个主要问题

  1. 地址映射的速度,页表的设计应考虑查找速度。每次访存,都需要进行地址映射。所有指令最终都必须来自内存,而且指令可能会访问内存中的操作数,因此每条指令的执行都能你会多次访问页表—TLB
  2. 页表可能非常大,设计算机地址时32位,即地址空间大小4GB,若页大小是4KB,则每个进程页表最多要有\(\frac {4G} {4K}=2^{20}\)个表项(约100万个)。而且每个进程都需要一张页表—多级页表

加速分页过程

最简单的设计是使用由一组快速硬件寄存器组成的单一页表每个虚页一项,按虚页号索引。在一个进程启动时,操作系统将进程的页表装入寄存器,在进程运行期间不必因为页表而访问内存。

该方法的优点是直观并且在映射时不需要访问内存,其缺点是非常昂贵。而且,每次内容切换时都要载入整个页表而损害性能

另一种极端是把页表全部放在内存中。此时,需要的全部硬件只是一个指向页表起始地址的寄存器。该设计使得在上下文切换时,只需重新载入该寄存器就可以改变内存映射。

当然,它的缺点是执行每条指令时都需要一次或多次访问内存以读取页表项。因此,该方法很少以最单纯的方式使用,下面我们将研究一下比它性能要好得多的变种。

加速分页的方法

  • 转换检测缓冲区
  • 软件TLB管理

TLB

该设计在计算机上装备一个小的硬件设备以映射虚拟地址到物理地址,而无需通过页表。该设备称为TLB(Translation Lookaside Buffer,转换检测缓冲区),有时候也称为相连存储器(associative memory)

它通常位于MMU内部,由少数项组成,本例中由8项,不过很少超过64项。

每项都包含一个页面你的信息,包括虚页号、已修改位、保护码(读/写/执行许可)以及该页所对应的物理页框。

另有一位表示该项是否有效(即是否在使用)。

工作原理

性能分析

命中率:通过TLB实现内存访问的比率

设页表访问时间100ns,TLB访问时间20ns,命中率90%,则平均访问时间:

\[100\times10\% + 20 \times 90\%=28ns \]

软件TLB管理

TLB管理以及TLB错误全部由MMU硬件完成。只有当页不在内存中时才激活操作系统陷阱。

有很多策略已被开发用于TLB的软件管理,以提高机器性能。其中一种方法可以同时减少TLB失败以及当TLB失败时的代价(Bala等,1994)。

无论硬件还是软件,处理TLB失败的通常方法时转向页表,并执行索引操作以定位页引用。

针对大内存的页表

分页系统实现中的第二个问题—大页表的处理

  • 多级页表
  • 倒排页表

多级页表

为了避免始终在内存中保存庞大的页表,许多计算机中采用了多级页表。一个简单的例子如下图所示。在图(a)中,32位的虚拟地址被划分为10位的PT1域、10位的PT2域和12位的偏移。

偏移为12位,所以页长是4KB;二级页表的表项由1024个(可表示\(1024 \times 4KB = 4MB\)的地址范围);顶级页表的表项1024个,因此可表示的地址范围:\(1024 \times 4MB = 4GB\)

多级页表的秘诀就是避免把全部页表一直保存在内存中。特别是哪些不需要的页表不应该保留。例:一个需要12MB内存的进程,其最底端是4MB的程序正文段,其后是4MB的数据段,顶端是4MB的堆栈段,在数据段上方和堆栈段下方是大量没有使用的空闲区。则内存中只需要保存该进程的顶层页表一个,第二层页表3个(\(3 \times 4MB = 12MB\))。

倒排页表(inverted page table)

在该设计中,实际内存中的每个页框对应一项,而不是每个虚拟地址空间的页对应一项,而不是每个虚拟地址空间的页对应一项。例如,64位虚拟地址,4KB的页,以及256MB RAM,则虚页有\(\frac {2^{64}}{2^{12}}=2^{52}\)个、页框有\(\frac {2^{28}}{2^{12}}=65536\)个,反向页表以页框号作索引,只需65536项。每项记录哪些(进程、虚页)位于页框中。

在u虚拟地址空间比物理空间大很多的时候,反向页表节省了大量空间,但是它们有一个致命弱点:虚拟到物理的转换非常困难。解决方法就是使用TLB

改进:使用散列索引技术。虚页号根据一个哈希函数生成散列值,此值作为页表的索引,相同散列值的虚页链接在一起。

posted @ 2020-04-27 18:59  我係死肥宅  阅读(485)  评论(0编辑  收藏  举报