Linux 内核分析 二:虚拟内存

本文章主要对《深入理解计算机系统》第九章内容进行整理。

一、概述

虚拟内存:为了更加有效管理内存并且减少出错,现代操作系统提供一种对主存的抽象概念。

1、虚拟内存三个重要能力

1、将主存看成磁盘高速缓存,主存中只保留活动区域,根据需求在磁盘和主存间传递数据。

2、为每个进程提供一致进程地址空间,从而简化内存管理。

3、保护每个进程的地址空间不被其他进程破坏。

2、理解虚拟内存的重要性

1、虚拟内存是核心的

虚拟内存遍及计算机系统的所有层面,理解虚拟内存有助于更好地理解系统是如何工作的。

2、虚拟内存是强大的

虚拟内存给予应用程序强大的能力,可以创建销毁内存片,将内存片映射到磁盘文件的某个部分,以及与其他进程共享内存。

3、虚拟内存是危险的

每次应用程序引用一个变量、间接引用一个指针,或者调用一个诸如 malloc 这样动态分配程序时,他就会和虚拟内存发生交互。如果虚拟内存使用不当,应用将遇到复杂危险的与内存有关的错误

二、物理和虚拟内存

1、物理寻址

计算机系统的主存被组织成一个由 M 个连续字节大小的单元组成的数组每个字节都有一个唯一的物理地址

CPU访问内存最自然的方式就是使用物理地址,我们把这种方式称为物理寻址
在这里插入图片描述
图 9-1 展示一个物理寻址示例

数字信号处理器嵌入式微控制器仍然使用物理寻址的方式。

2、虚拟寻址

CPU通过生成一个虚拟地址访问主存,这个虚拟地址在被送入内存之前 转换成适当的物理地址

将一个虚拟地址转换成物理地址的任务叫做地址翻译
在这里插入图片描述
图 9-2 展示一个虚拟寻址示例

三、地址空间

地址空间是一个非负整数地址的有序集合

线性地址空间:地址空间中的整数是连续的。

虚拟地址空间:带有虚拟内存的系统中,CPU从一个有 N = 2^n 个地址的地址空间中生成虚拟地址。

物理地址空间:对应于系统中物理内存的字节。

地址空间的概念很重要,因为它清楚地区分数据对象(字节)和它们的属性(地址)。

虚拟内存的基本思想:允许每个数据对象多个独立的地址,其中每个地址都选自一个不同的地址空间

主存中的每个字节都有一个选自虚拟地址空间的虚拟地址和一个选自物理地址空间的物理地址

四、虚拟内存作为缓存的工具

概念上而言,虚拟内存被组织为一个存放在磁盘连续数组(N个字节大小)。每个字节都有一个唯一的虚拟地址,作为数组的索引

磁盘上数组内容被缓存主存中。

VM 系统通过将虚拟内存 分割虚拟页。物理内存被分割成物理页(也称为页帧)。

任何时刻,虚拟页面的集合都分为三个不相交的子集:

  • 未分配的:VM系统还未分配(或创建)的页。未分配的块没有任何数据,因此不占用任何磁盘空间
  • 缓存的:当前已缓存在物理内存中的已分配页。
  • 未缓存的:为缓存在物理内存中的已分配页。
    在这里插入图片描述
    图 9-3 展示一个有8个虚拟页小虚拟内存

1、DRAM缓存的组织结构

SRAM缓存:表示位于CPU主存之间的L1、L2和L3高速缓存。

DRAM缓存:表示虚拟内存系统的缓存,它在主存中缓存虚拟页。

存储器结构中,DRAM缓存的位置对它的组织结构有很大影响。DRAM 比 SRAM 要慢大约 10 倍,磁盘要比 DRAM 慢大约 100 000 多倍。因此,DRAM 缓存中的不命中比 SRAM缓存中的不命中要昂贵的多。

因为从磁盘中缓存数据到内存速度慢,因此为降低不命中处罚,进行如下设计:

  • 虚拟页往往很大,通常是 4KB ~ 2MB。
  • DRAM 缓存是全相联的,即任何虚拟页都可以放置在任何物理页中。
  • 使用更精密的替换算法
  • DRAM 缓存总是使用写回,而不是直写。

2、页表

虚拟内存系统必须有某种方法来判断一个虚拟页是否缓存在 DRAM 中的某个地方。如果,系统还必须确定这个虚拟页放在哪个物理页中。如果不命中,系统必须判断这个虚拟页存放在磁盘哪个位置,在物理内存中选择一个牺牲页,并将虚拟页从磁盘复制到 DRAM 中,替换这个牺牲页。

这些功能由软硬件联合提供的,包括操作系统软件MMU(内存管理单元)中的地址翻译硬件和一个物理内存中叫做页表的数据结构,页表将虚拟页映射到物理页

总结:页表是一个数据结构,存放在内存中,负责将虚拟页映射到物理页。

地址翻译硬件将一个虚拟地址转换为物理地址时,都会读取页表

操作系统负责维护页表的内容,以及在磁盘与DRAM之间来回传送页。
在这里插入图片描述
图 9-4 展示一个页表的基本组织结构。

页表就是一个页表条目的数组

假设每个页表条目由一个有效位和一个地址字段组成。有效位表明该虚拟页当前是否被缓存在 DRAM 中。

如果设置有效位地址字段指向 DRAM 中相应的物理页的起始位置,这个物理页缓存了该虚拟页。如果没有设置有效位,表示虚拟页还未被分配,地址字段指向虚拟页在磁盘上的起始地址

3、页命中

在这里插入图片描述
当 CPU 想要读包含在 VP2 中虚拟内存的一个字节时会发生什么,VP2被缓存在 DRAM 中。

1、地址翻译硬件将虚拟地址作为一个索引来定位 PTE2,并从内存中读取它。

2、因为设置有效位,地址翻译硬件就知道 VP2 是缓存在内存中了。

3、地址翻译硬件使用页表条目中起始地址,构造出要读取字节地址。

4、缺页

在虚拟内存的习惯说法中,DRAM 缓存不命中称为缺页。
在这里插入图片描述
图 9-6 展示了在缺页之前的页表示例状态。

CPU引用 VP3 中的一个字,过程如下:

1、地址翻译硬件从内存中读取 PTE3,从有效位推断出 VP3 未被缓存,并触发一个缺页异常

2、缺页异常调用内核中缺页异常处理程序,选择一个牺牲页(VP4)。

3、如果牺牲页已经被修改,内核将它复制回磁盘。

4、内核修改牺牲页(VP4)的页表条目,反映 VP4 不再缓存在主存中这一事实。

5、内核复制 VP3 到内存PP3中,并更新 PTE3。

6、重新启动导致缺页的指令,该指令会把导致缺页的的虚拟地址重新发送到地址翻译硬件。

7、地址翻译硬件正常处理。
在这里插入图片描述
图 9-7 展示了在缺页之后的页表示例状态。

5、分配页面

在这里插入图片描述
图 9-8 展示了当操作系统分配一个新的虚拟内存页时页表的影响。

在这个示例中,VP5 的分配过程是在磁盘上创建空间并更新 PTE5,使它指向磁盘上这个新创建的页面。

6、局部性

尽管整个运行过程中程序引用的不同页面的总数可能超出物理内存总的大小,但是局部性原则保证了在任意时刻,程序将趋向于在一个较小的活动页面集合上工作,这个集合叫工作集常驻集合。在初始开销,也就是将工作集页面调度到内存中之后,接下来对于这个工作集的引用将命中,而不会产生额外的磁盘流量。

抖动:工作集大小超出物理内存大小,页面将不断换进换出。

空间局部性:指程序倾向于访问在最近访问过的内存地址附近的内存。

时间局部性:指程序倾向于在不久的将来再次访问最近刚访问过的内存地址。

五、虚拟内存作为内存管理的工具

虚拟内存大大简化了内存管理,并提供了一种自然的保护内存的方法。

操作系统为每个进程提供一个独立的页表,因此每个进程有一个独立的虚拟地址空间
在这里插入图片描述
图 9-9 展示了基本思想。

注意:多个虚拟页面可以映射到同一个物理页面上。

按需页面调度和独立的虚拟地址空间的结合,对系统中内存的使用和管理造成了深远的影响。特别的,VM系统简化了链接和加载、代码和数据共享,以及应用程序的内存分配。

  • 简化链接:独立的地址空间允许每个进程的内存映像使用相同的基本格式,而不用管代码和数据实际存放在物理内存的何处
  • 简化加载:虚拟内存还使得容易向内存中加载可执行文件和共享对象文件。
  • 简化共享独立地址空间操作系统提供了一个管理用户进程和操作系统自身之间共享的一种机制
  • 简化内存分配:虚拟内存为向用户进程提供一个简单的分配额外内存的机制。

六、虚拟内存作为内存保护的工具

任何现代计算机系统必须为操作系统提供手段控制对内存系统的访问

提供独立的地址空间使得区分不同进程的私有内存变得容易。但是,地址翻译机制可以以一种自然方式扩展到提供更好的访问控制。因为每次 CPU 生成一个地址时,地址翻译硬件都会读一个 PTE,所以通过在 PTE 上添加一些额外的许可位来**控制 ** 对一个虚拟页面内容的访问十分简单。
在这里插入图片描述
SUP:表示进程必须运行在内核模式下才能访问该页。

READ:允许对页进行读。

WRITE:允许对页进行写。

如果一条指令违反了这些许可条件, 那么 CPU 就触发一个一般保护故障,将控制传递给一个内核中的异常处理程序。

七、地址翻译

在这里插入图片描述
图 9-11 概括了使用的所有符号。

地址翻译是完成虚拟地址空间中的元素物理地址空间中元素之间的映射
在这里插入图片描述
图 9-12 展示了 MMU 如何利用页表来实现这种映射。

CPU 中的一个控制寄存器,页表基址寄存器指向当前页表。

n 位虚拟地址包含两个部分:

  • 一个 p 位的虚拟页面偏移
  • 一个 n-p 位的虚拟页号

MMU 利用 VPN选择适当的 PTE,将页表条目中的物理页号虚拟地址中的 VPO 串联起来,就得到相应的物理地址
在这里插入图片描述
图 9-13a 展示了当前页面命中时,CPU 硬件执行的步骤:

  • 第一步:处理器生成一个虚拟地址,并把它传递给 MMU。
  • 第二部:MMU 生成 PTE 地址,并从高速缓存 / 主存请求得到它。
  • 第三步:高速缓存 / 主存向MMU 返回 PTE。
  • 第四步:MMU 构造物理地址,并把它传递给高速缓存 / 主存。
  • 第五步:高速缓存 / 主存返回所请求的数据给处理器。

图 9-13b 展示当前页面不命中时,CPU 硬件执行步骤:

  • 第一步到第三步:和 9-13a 中相同。
  • 第四步:PTE 中有效位为零,MMU 触发一次异常,传递 CPU 中的控制到操作系统内核中缺页异常处理程序。
  • 第五步:缺页处理程序选择牺牲页,如果牺牲页被修改,则把他换出到磁盘。
  • 第六步:缺页处理程序调入新的页面,并更新内存中的 PTE。
  • 第七步:缺页处理程序返回原来的进程,再次执行导致缺页的指令。

注:页面命中完全是由硬件来处理页面缺失要求硬件操作系统内核协作完成。

1、结合高速缓存和虚拟内存

在这里插入图片描述
大多数系统使用 SRAM 高速缓存选择物理寻址。使用物理寻址,多个进程同时在高速缓存中有存储块和共享来自相同虚拟页面的块成为很简单的事。而且,高速缓存无需处理保护问题,因为访问权限的检查是地址翻译的一部分

2、利用 TLB 加速地址翻译

每次 CPU 产生一个虚拟地址,MMU 就必须查阅一个 PTE,以便将虚拟地址翻译为物理地址。在最糟糕的情况下,这会要求从内存多取一次数据,代价是几十到几百个周期。如果 PTE 恰巧在 L1 缓存中,那么开销就下降到 1 个或 2个周期。

许多系统试图消除这样的开销,它们在 MMU 中包括了一个关于 PTE 的小的缓存,称为翻译后备缓冲器(TLB)。

TLB是一个小的虚拟地址的缓存,其中每一行都保存着一个由单个 PTE 组成的块。
在这里插入图片描述
虚拟页号(VPN)分为 TLB 标记和 TLB 索引
在这里插入图片描述
图 9-16 展示了 TLB 命中的步骤:

  • 第一步:CPU 产生一个虚拟地址。
  • 第二步和第三步:MMU 从 TLB 中取出相应的 PTE。
  • 第四步:MMU 将虚拟地址翻译成物理地址,并将他发送给高速缓存 / 主存。
  • 第五步:高速缓存 / 主存将所请求的数据返回给CPU。

关键所有地址翻译步骤都在芯片的 MMU 中执行的,所以非常快

3、多级页表

多级页表主要用来压缩页表,减少页表对内存的占用
在这里插入图片描述
图 9-17 展示了我们如何为这个虚拟地址空间构造一个两级的页表层次结构。

这种方法从两个方面减少了内存要求

1、如果一级页表中的一个 PTE 是空的,那么相应的二级页表根本不会存在。

2、只有一级页表才需要才需要总是在主存中,二级页表根据需要缓存到主存。
在这里插入图片描述
图 9-18 描述了使用 k 级页表层次结构的地址翻译。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值