虚拟内存-linux快速入门教程
1. 简介
虚拟内存允许进程使用计算机上物理上可用的更多内存。
在本教程中,我们将详细介绍虚拟内存基础知识。我们将介绍两个关键的虚拟内存实现,即暂存和分页。最后,我们将比较它们。
2. 基础知识
虚拟内存将物理内存(随机存取内存,RAM)与逻辑内存分开。它基于一个属性,即在任何时候都必须将进程的一部分放置在计算机的随机存取内存中。具体来说,就是进程实际使用的部分。
使用虚拟内存的系统提高了多任务环境中随机存取内存的利用率。使用虚拟内存的核心优点是:
- 能够在进程之间共享内存
- 通过内存隔离提高安全性
- 可以使用机器上物理上可用的更多内存
虚拟内存会产生一种错觉,即进程正在单个连续的内存区域中工作。然而,物理上它可以被碎片整理、非连续和部分存储在大容量存储设备上。通过将物理内存中的地址映射到逻辑地址来实现。此外,逻辑地址的面积可以大于物理地址。下面,我们可以看到虚拟内存的一般概念:
虚拟内存可以使用两种称为需求分段和需求分页的常见机制来实现。在下一节中,我们将详细讨论它们。
2. 分页虚拟内存
分页虚拟内存是最常用的实现。通常,分页是一种允许从辅助存储存储和检索数据的技术。物理内存被拆分为称为帧的固定大小块。逻辑内存被拆分为称为页的固定大小块。随后,页面和框架的大小相同。
在执行该过程时,如果需要,页面将装载到适当的框架中。因此,该过程称为按需分页:
因此,仅在需要时将页面加载到随机存取存储器中会带来很多好处。它减少了输入/输出操作的数量和 RAM 内存消耗。这样,大型进程的单次执行可能只需要其代码的一小部分。因此,系统的响应时间得到了改善。随后,可以处理更多用户。
当进程引用内存时,可能会发生以下情况:
- 引用无效
- 引用有效且存在所需页面
- 引用有效,所需页面不存在
在第一种情况下,请求被拒绝。在第二种情况下,即成功方案,请求只是得到正确处理。在最后一种情况下,系统必须将所需的页面从磁盘导入内存。
2.2. 验证位
验证位是用于验证页面状态的硬件支持机制。为页列表中的每条记录设置验证位。该位只能采用两个可能的值:零或一。
最初,所有位都设置为零。这意味着该页面不存在于随机存取存储器中或引用无效。另一方面,当位设置为 1 时,引用有效且页面存在。如果在地址转换期间将位设置为 0,则这种情况称为页面错误,处理器会触发相应的机制,我们将在下一小节中介绍。
2.3. 页面错误
当发生页面错误时,处理器将控制权转移到操作系统。首先,系统在磁盘上定位所需的数据。其次,它在随机存取存储器中查找可用帧。然后,它将页面加载到该框架中。之后,它会更新页面表。最后,该过程继续执行。
RAM 中可能没有任何可用帧。因此,有必要释放一些。存在特殊的服务技术,建议使用称为页面替换算法。
2.4. 页面替换
页面替换过程的常规工作流包括以下操作:
- 在磁盘上找到所需的页面
- 识别将从随机存取存储器中删除的帧
- 通过将要删除的帧复制到磁盘来备份要删除的帧(如果还没有副本)
- 通过将删除的框架的引用设置为无效来更新页面列表
- 将所需页面加载到释放的框架中
- 再次更新页面表
页面替换算法主要负责第二点。特定算法的选择可能会影响虚拟内存的性能。最优页面替换算法仅存在于理论上。简而言之,它交换了将来将使用最远的页面。
在实际方案中,不可能实现这样的功能。虽然,还有其他算法或多或少有效地处理它。下面我们简单介绍一下:
- FIFO(先进先出)– 替换最旧的页面
- LRU(最近最少使用)– 替换未使用时间最长的页面
- LFU(最不常用)– 替换最稀有使用的页面
- MFU(最常用) – 替换最常用的页面
3. 分段虚拟内存
第二种流行的实现是分段虚拟内存。分段是将物理内存拆分为称为段的连续块的过程。段可以具有不同的大小。因此,逻辑地址由两个值表示:段号和偏移量。
段编号是段表中的索引。该表中的每条记录都有一个基址,该基址引用物理内存中段的开头。此外,段具有指向物理内存中段末尾的极限值。随后,偏移量是介于 0 和限制之间的值。
系统根据应用程序的请求创建分段。它将段的索引传递给应用程序。因此,进程是指段内的内存区域。因此,他们不知道这些段引用的物理内存中的数据位置。此外,这些进程无法访问其他进程的段。
3.1. 段描述符
段的参数存储在称为段描述符的 8 位长记录中:
描述符包括:
- BA – 基址,从该内存开始的段的物理地址
- G – 粒度,当为空时,限制由字节描述。如果设置,则限制由 4096 字节页定义
- D – 默认操作数大小,设置后,段为 16 位代码,如果注意,段为 32 位
- B – 大,与 D 含义相同
- L – 长,如果设置,则段为 64 位
- AVL – 可用,保留供软件使用
- P – 存在,如果为空,则生成异常
- DPL – 描述符权限级别
- T 型 – 类型
- C – 符合性,定义是否可以从权限较低的级别访问段中的代码
- E – 向下扩展,如果设置,段从最大偏移量向下扩展到极限,如果为空,则段从基址扩展到基数 + 限制
- R – 可读,如果为空,则无法读取该段,只需执行
- W – 可写,如果为空,则段无法写入,只能读取
- A – 已访问。访问分段时设置为 1
段存储在两种类型的表中。其中第一个是GDT(全局描述符表)。系统中只有一个GDT,它存储所有过程的段。第二个是LDT(本地描述符表)。有许多本地描述符表来描述各个流程的段。
3.2. 区段选择器
每个描述符都有一个相应的选择器。段选择器是对特定表(GDT 或 LDT)中描述符的引用。选择器包含以下字段:
- 特定表中段的描述符索引
- 表指示符字段通知在哪个表中定位描述符。它只能保存两个值中的一个:零值表示描述符在 GDT 中,一个值表示 LDT
- 请求者的权限级别字段定义了安全属性,例如,哪些指令可以处理执行,也可以访问它不拥有的数据
因此,当进程想要访问分段内存时,首先,它指向分段注册表中的段选择器。然后,特定选择器引用GDT或LDT表中的相应描述符。最后,描述符告知在何处查找所需的段。