3. 内存管理(Memory Management)

2023-11-10

计算机有几兆字节的非常快速,昂贵,且易变的 cache memory,几千兆字节的中速,中等价格,易变的 main memory,以及几千兆字节缓慢,便宜,非易变的磁盘/固态硬盘存储,不涉及可移除的存储,例如 DVDs 和 USB 存储器。这被称为 memory hierarchy

操作系统管理内存层级的部分被称为 memory manager,它追踪处于使用中的内存,在需要时向进程分配内存,不需要时解分配内存。

3.1 无内存抽象

早期的操作系统没有内存抽象,程序直接使用物理内存,这样多个进程无法同时运行,因为它们可能访问同一物理地址,造成冲突。
在这里插入图片描述
无内存抽象具有以下缺点:

  1. 用户程序可以访问任意物理地址,包括操作系统所在的地址,可能会有意或无意的破坏操作系统。
  2. 难以支持多个进程同时运行,它们可能访问同一物理地址。

3.2 内存抽象:地址空间

3.2.1 地址空间的概念

Address space 是进程用来进行内存寻址的地址集。每个进程都有自己的地址空间,共享内存除外。

Base and Limit Register

该方法使用一个 dynamic relocation 及其简单的版本,即以一种简单的方式将进程的地址空间映射到物理内存中的不同部分。典型的方法是 CPU 中持有两个特殊的硬件寄存器,通常称为 baselimit 寄存器。当这些寄存器被使用时,程序被加载到一段具有足够空间的连续的内存。当进程运行时,base 寄存器使用程序在内存中的起始点的物理地址进行加载,limit 寄存器使用程序的长度进行加载。

每一次进程引用内存,无论是抓取一个指令读写数据字,CPU 硬件在将该地址访问内存总线前自动为进程生成的地址加上 base 的值。类似的,它也检查提供的地址是否等于或大于 limit 寄存器中的值,这种情况下会产生一个错误,访问会被中断。

使用 base 和 limit 寄存器进行重定位的缺点是对于每个内存引用都需要执行一次加法和一次比较。比较能很快完成,但是加法因为 carry-propagation 时间会比较慢,除非使用额外的电路。

Swapping

所有进程所需的 RAM 的总数量通常不能被内存所满足。解决这一问题最简单的方案是 swapping,包括完整地引入每个进程,运行一段时间,将它放回硬盘中。空闲的进程大多存储在硬盘上,所有当它们没有运行时不会占据任何内存 (它们之中有一些被周期性的唤醒,来执行它们的工作)。另一个策略被称为 virtual memory,甚至允许程序只有部分在主存中,仍然能运行。

交换系统的操作如图 3-4 所示。开始时,只有进程 A 在内存中。然后进程 B 和 C 被创建或从硬盘被交换到内存中。在图 3-4(d) 中,A 被交换出硬盘。然后 D 进入 B 被交换出。最终 A 再次进入。因为 A 现在位于不同的位置,包含在其中的地址必须被重定位,要么是在被换入时软件进行重定位,要么 (大概率) 是在程序执行过程中由硬件进行重定位。例如,使用 base 和 limit 寄存器。
在这里插入图片描述
当交换在内存中创建了多个空洞,可能通过尽可能地将进程向下移动将这些空洞结合为一个大地空洞,这一技术被称为 memory compaction。该操作通常不会被执行,因为会耗费大量的 CPU 时间。例如,16-GB 的机器能在 8 nsec 内拷贝 8 个字节,压紧内存将耗费 16 秒。

值得考虑的一点是进程在被创建或被换入时应当被分配多大的内存空间。对于在运行期依然保持使用固定内存大小的进程,分配其固定大小的内存就足够了。对于在运行期可能出现内存增长的进程,比如在堆上分配内存,对其内存的分配也必须是动态的。当进程邻近一个空洞时,可以将空洞的内存分配给该进程,但是当进程邻近另一个进程,则需要将邻近的进程交换到硬盘中,或者将进程移动到满足其增长后的内存大小的空洞中。如果这两者都不能满足,进程将被挂起直到某些空间被释放 (或者可能被杀死)。

如果大部分的进程在运行时其内存都会增长,在创建或交换时多分配一些额外的内存将会降低在内存增长时移动进程或交换其他进程的开销。然而,在交换进程到硬盘时,只会交进程实际占据的内存,交换额外分配的内存是对硬盘资源的浪费,在被换入时重新分配额外空间即可。图 3-5(a) 展示了增长的内存已经被分配了的内存配置。
在这里插入图片描述
如果进程有两个增长的段 – 例如,数据段作为堆以动态分配和释放某些变量,以及用于普通局部变量和返回地址栈段。图 3-5(b) 是一种可选的安排,在其被分配的内存的顶部有一个栈,它向下增长,程序 .text 段之上有一个数据段向上增长。两个段之间的内存能被用于两者中的任何一个。如果它被耗尽,进程将被移入一个有足够空间的空洞,或换出其他进程的内存以创建足够大的空洞,或者被 killed。

3.2.3 管理未使用的内存

当内存被动态分配时,操作系统必须管理它。一般来说,有两种追踪内存使用的方法:位图未使用内存链表

使用位图管理内存

使用位图,内存能以分配单元被分割,小到几个字,大到几千字节。位图中每个分配单元都对应一位,当分配单位为被使用时其值为 0,被使用时其值为 1。图 3-6 展现内存的一部分以及对应的位图。

分配单元的大小是一个重要的设计问题。分配单元越小,位图越大。然而,即使分配单元为 4 字节,32 位的内存在位图中仅需要 1 位。32n 位的内存将使用 n 个位图中的位,所以位图只会占据 1/32 的内存。如果分配单位越大,位图将越小,但是如果进程的大小不是分配单元的整数倍,进程的最后一个单元中的内存可能会被浪费。

位图提供了一种简单的方法以追踪固定大小内存中按分配单元分配的内存分配情况,位图的大小依赖内存的大小以及分配单元的大小。位图的主要问题时,当准备位 n 个分配单元的进程分配内存时,内存管理器必须搜索位图,寻找连续的 n 个值为 0 的位,这一搜索过程是一个缓慢的操作。

使用链表管理内存

管理内存的另一方式是使用元素为允许的或未使用的内存段的链表,链表中的内存段要么是一个进程,要么是两个进程间的空洞。图 3-6(a) 中的内存如果以链表表示则如图 3-6© 所示,其中 H 表示空洞P 表示进程,后跟起始物理地址,以及内存段的长度,最后是指向下一项的指针

本例中,内存段列表按地址排序,这有助于内存段链表的更新。当进程终止或被交换到硬盘上时,会出现 4 种情况,如图 3-7 所示。
在这里插入图片描述
(a) 将 P 替换为 H;
(b) 将原分配给进程 X 的内存段与相邻的空洞合并,更新地址和长度,链表移除 X 对应的内存段项;
(c) 同上;
(d) 同上,但链表移除 X 对应的内存段项以及 X 之后的空洞内存段项。

当进程和空洞按地址顺序链接在链表上,内存管理器可以使用一些算法来搜索合适的空洞,将其分配给新创建的进程会从硬盘中被换入的进程。最简单的算法是 first fit。内存管理器沿着内存段的链表扫描,找到第一个空间足够大的空洞,将其空间一分为二,满足进程内存大小的哪部分分配给进程,另一部分则是新的空洞,除非空洞的大小正好等于进程所需的内存大小。first fit 算法是一个快速算法,因为它执行尽可能少的搜索。

first fit 的一个最小的变体是 next fit。它与 first fit 的工作方式相同,除了它记录上次分配的空洞的位置,下一个的搜索将从上次分配的空洞处开始。

另一个为人熟知且广泛使用的算法是 best fit。Best fit 搜索整个列表,从开始到结束,选择最小的满足要求的空洞。不是对一个大的空洞进行分割,best fit 尝试寻找最接近实际需要的大小的空洞。Best fit 慢于 first fit,因为它需要遍历整个内存段链表。Best fit 还会造成更多的内存浪费,因为会产生很多小的空洞,这些小的空洞很难分配给其他程序。

为了解决将几乎完全匹配的空洞分割为进程使用的内存和另一个小的空洞,worst fit 算法被提出来,该算法总是选择最大的可用空洞,产生的新的空洞将足够大能够被分配给其他进程。模拟显示出 worst fit 还不是一个合适的内存分配算法。

上述 4 种算法都能通过分别维护进程和空洞的内存段列表进行加速。使用该方法,它们将致力于检查空洞,而非包括进程。对应的代价是额外的复杂度和解分配内存变慢,因为未使用的内存段必须从进程列表种移除,并插入到空洞列表中。

当空洞保存在一个单独的列表中时,可以采用一个小的优化。不必使用一组单独的数据结构维护空洞列表,信息能被直接存储在空洞中。每个空洞的第一个字将是空洞的大小,第二个字指向下一个条目。空洞所在的地址和 H 标志位不再需要了。

还有另一种分配算法,称为 quick fit,它位一些更常见的请求大小维护一个列表。例如,它可能具有一个 n 个条目的表,第一个条目是指向 4 KB 空洞链表的头的指针,第二个条目是指向 8 KB 空洞链表的指针,第三个条目指向 12 KB 的空洞。21 KB 的空洞能被放入 20 KB 空洞的列表中,或者放入一个奇数大小空洞的特殊列表中。

使用 quick fit,找到所需大小的空洞将很快,但是它也有所有使用空洞大小排序的方案共有的缺陷,当进程终止或被换出时,找到它的邻居以确定是否需要合并变得十分昂贵。如果没有执行合并,内存将被快速分割为大量的小空洞,不能满足任何进程。

3.3 虚拟内存

虽然 base 和 limit 寄存器能被用来创建地址空间的抽象,但是还有另一个问题需要解决:软件的所占据的内存随着软件的发展在快速增长,出现了程序运行时需要占据的内存无法被满足的程序的需求,此外系统还需要支持多个进程同时运行,它们中的每一个所需的内存都能被满足,但是所有进程所需的内存之后超过了现有内存的大小。交换进入硬盘并不是一个合适的选项,因为典型的 SATA 磁盘的峰值传输率是几百 MB/sec,这意味着换出或换入 1-GB 的程序将耗费数秒。

Virtual memory 被提出来用于解决软件所需内存的大小大于现有内存这一问题,其基本概念是每个进程都有自己的地址空间,地址空间被划分成块,称为 pages。每一页都是连续的地址范围。这些页被映射到物理内存中,但是并不是所有的页在程序运行时都必须存在于内存中。当进程访问其地址空间中的某一部分时,如果该部分存在于物理内存中,硬件则会执行必要的映射以获取正确的物理内存地址;如果该部分不在物理内存中,则会提醒操作系统加载该部分到物理内存中,然后重新执行失败的指令。

某种意义上说,虚拟内存时 base-and-limit-register 概念的泛化。使用虚拟内存,可以将进程的地址空间以相当小的单元映射到物理内存中。

虚拟内存在多程序系统中依然工作的很好,内存中能同时存在多个程序的页。当进程等待它自己的页被读入到物理内存时,CPU 可以被其他进程使用

3.3.1 分页

大部分的虚拟内存使用一种称为 paging 的技术。在任何计算机上,程序应用一组内存地址。当程序执行某个指令例如:

MOV REG, 1000

它拷贝内存地址为 1000 的数据到 REG 中 (或者反过来,取决于操作系统)。地址可能使用 indexing,base register,segment register,和其他方式生成。
在这里插入图片描述
程序生成的地址被称为 virtual address,它们组合在一起形成了 virtual address space。在没有虚拟内存的计算机上,虚拟地址被直接传输到内存总线上,将其作为物理内存地址进行读写。在使用虚拟内存的计算机上,虚拟地址通过内存管理单元 (MMU) 映射到对应的物理内存地址上,将转换后的地址发送到内存总线上,作为访问的物理内存地址,如图 3-8 所示。
在这里插入图片描述
图 3-9 展示了虚拟地址如何被映射为物理地址的一个例子。如图 3-9 所示,虚拟地址为 16 位,虚拟地址空间范围从 0 到 64K-1,支持 64 KB 的程序运行,但是实际的物理地址空间范围为 0 到 32 KB,为虚拟地址空间的一半,这意味着 64 KB 的程序不能被完全加载到物理内存中,仅能加载部分进程的虚拟内存到物理内存中,其他的虚拟内存数据必须存储在硬盘上,这就要求程序的完整映像必须存储在硬盘中,以便随时按需加载入物理内存。

虚拟内存空间的组成单元被称为 pages物理内存空间的组成单元被称为 page frames。页和页帧的大小通常是相同的,本例中使用的大小是 4KB。在实际的系统中,页和页帧的大小支持从 512 字节到 1 GB。RAM 与硬盘通常以页帧作为单位进行交换。许多处理器支持多个页的大小,可以按照操作系统的需求选取甚至混合使用。比如 x86-64 架构支持 4-KB,2-MB 和 1-GB 的页,所以我们可以对用户应用程序使用 4-KB 的页,对内核应用程序使用 1-GB 的页。

我们来看看虚拟内存地址如何被映射到物理内存地址,假设有下述指令:

MOV REG, 0

其中,0 表示虚拟内存地址为 0,它位于虚拟内存地址范围为 0 - 4095 的页中,该页映射物理页帧 2,所以其物理内存地址为 (8192 + 0),该转换后的地址被发往内存总线作为访问的物理内存地址。内存对 MMU 的存在一无所知,它唯一知道的就是传入的物理内存地址。

MMU 将虚拟内存地址映射为物理内存地址,并没有解决软件所需内存大于实际内存的问题,MMU 仅能将 16 个虚拟内存页中的 8 个映射到 8 个物理内存页帧上,其他 8 个则处于未被映射的状态,在实际的硬件中,我们使用 Present/absent bit 追踪已映射和未被映射的虚拟内存页。当 MMU 发现进程尝试访问未被映射的页,会致使 CPU 将此情况上报操作系统,这被称为 page fault。操作系统随后选择一个不常使用的页帧,将其内容存入硬盘,然后将发送页错误的指令所引用的页从硬盘中读入刚刚释放的页帧中,并修改映射关系,然后重新执行失败的指令。

那么 MMU 如何将虚拟内存地址映射为物理内存地址呢?16 位的虚拟内存地址被划分为两部分,高 4 位表示 16 个页其中之一的页编号,低 12 位表示在该页中的偏移量,至多为 4095,即页上的最后一个地址。页编号作为 page table 中的索引使用,依据该索引可以得到页所对应的页帧的编号。该页帧的编号作为输出寄存器的高 3 位,剩下的低 12 直接使用上述的页的偏移量,它们一起组成 15 位的物理内存地址,传入内存总线中。

3.3.2 页表

在简单的实现,虚拟内存地址如上述被划分为 2 部分:高位部分表示虚拟页编号低位部分表示虚拟内存地址在该页中的偏移。虚拟页编号用于在页表中查找对应的虚拟页条目。从虚拟页条目中,能得到对应的页帧编号,将页帧编号作为高位与页偏移进行结合,替换原来的页编号,就得到了实际需要访问的物理内存地址。因此,页表的作用就是映射虚拟页到对应的页帧。
在这里插入图片描述

页表条目的结构

页表条目的大小和布局因系统而言,但其包含的内容大致相同,典型的页表条目如图 3-11 所示:
在这里插入图片描述
其中最重要的字段是 Page frame number

与之相邻的是 Present/absent 位,如果该位被置为 1,则该条目合法并被使用,如果为 0,则表示该条目所对应的虚拟页当前没有加载到物理内存中,对其进行访问会导致页错误。

Protection 位表示对该页允许那种类型的访问。最简单的形式下该字段只包含 1 位,0 表示允许读写,1 表示只读。成熟的设计则包含 3 位,读写和执行各占一位。

ModifiedReferenced 位追踪页的使用情况。当页被写入时,硬件自动设置 Modified 位。当操作系统决定回收某个页时,如果该位被设置,则表示该页有修改,是 “脏” 的,需要被写回硬盘;如果没有设置该位,则表示该页没有修改,是 “干净” 的,不需要写回硬盘,直接丢弃即可。该位有时被称为 dirty bit,因为它反映了页的状态。

Referenced 位在页被引用的时候被设置,无论是读或者写。该值被用来帮助操作系统在发生页错误选择被逐出的页。未被使用的页相较被使用的页是更好的候选人,该位在几种页替换算法中扮演者重要的角色。

最后一位允许该页的缓存被禁用。该特性对于映射到设备寄存器而非内存中的页十分重要。如果操作系统正在一个紧密的循环中等待一些 I/O 设备对器刚刚给出的命令进行响应,那么硬件持续抓取来自设备的字,而不是使用旧的缓存拷贝就十分必要了。使用该位,缓存则会被关闭。有单独的 I/O 空间不使用内存映射的 I/O 的机器不需要该位。

注意,用于保存不在内存中的页的硬盘地址不是页表的一部分。理由很简单,页表仅保存硬件将虚拟内存地址翻译位物理内存地址所需的信息。操作系统在处理页错误时所需的信息被保存在操作系统的软件表中。硬件并不需要它。

在进一步讨论实现相关的问题前,值得再次指出虚拟内存本质上创建了一个抽象,一个地址空间,是物理地址的抽象,正如进程是物理处理器的抽象一样。虚拟内存能通过将虚拟地址划分位页,并将其映射到物理内存的某些页帧中,或者让其暂时未被映射。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

3. 内存管理(Memory Management) 的相关文章

随机推荐

  • 【QT 网络云盘客户端】——实现文件属性窗口

    目录 文件属性对话框 设置字体样式 获取文件的信息 显示文件属性对话框 当我们点击文件中的属性 则会弹出一个属性对话框 实现过程 0 设置 属性 菜单项的槽函数 1 鼠获取鼠标选中的QListWidgetItem 它包含 图标和文件名 2
  • 代码重构与单元测试——重构1的单元测试(四)

    四 重构1的vb net教程单元测c 教程试 程序开发过程中 写代码是为了实现需求 当我们的代码通过了编译 只是说明它的语法正确 功能能否实现则不能保证 因此 当我们的某些功能代码完成后 为了检验其是否满足程序的需求 可以通过编写测试代码
  • java自动化测试语言高级之多线程编程

    java自动化测试语言高级之多线程编程 Java 多线程编程 Java 给多线程编程提供了内置的支持 一条线程指的是进程中一个单一顺序的控制流 一个进程中可以并发多个线程 每条线程并行执行不同的任务 多线程是多任务的一种特别的形式 但多线程
  • Fiddler工具使用汇总

    Fiddler工作原理 fiddler作为一个代理服务器 跟浏览器建立连接之后 浏览器像目标服务器发送的请求都会经过fiddler代理 所以fiddler可以捕获到http s 请求 从而可以解释 分析 甚至重写发出去的http s 请求
  • Conda、pip下载包:PackagesNotFoundError: The following packages are not available from current channels:

    1 问题 安装包的时报下面错误 安装包之前查一下当前环境对应的包的版本 conda search 包名 2 解决方法1 报错原因是当前镜像中不存在这个包 解决方法如下 直接去官网https anaconda org 搜包名 找到对应的版本点
  • ESXI虚拟机 - 使用vmdk虚拟机转换为OVF模板,导入ESXI

    目录 一 前提条件 二 转换为OVF模板 三 导入ESXI系统 四 安装时可能会出现的问题 一 前提条件 已安装VMware Workstation 并且创建了一个的虚拟机 此处以win8 1为例 已存在ESXI系统 二 转换为OVF模板
  • 包装类Integer判断“==”相等

    今日小编在复习Java基本数据操作类是发现的遗忘问题 是Integer的 比较问题 与大家进行分享 示例代码如下 public class IntegerComparison public static void main String a
  • 四因素三水平正交试验表_最简单的正交试验教程,一次性搞懂它

    大家好 今天要分享的是正交试验设计与结果检验过程 正交试验设计时试验优化的常用技术 它可以通过科学合理地设计 达到用较少的试验次数 取得较为准确可靠的结果 正交试验设计一般包括以下几步 确定研究因素和指标水平 制作成正交试验表格 实施试验
  • seaborn简明教程(一)

    1 Seaborn简介 seaborn是基于matplotlib的数据可视化库 它在matplotlib的基础上 进行了更高级的API封装 从而使得绘图更加容易 不需要经过大量的调整 就能使图形变得精致 seaborn的几个鲜明特点如下 绘
  • 使用docker部署fastdfs集群版

    一 前言 本文档说明在node01和node02两台主机上安装部署FastDFS双节点 node01 ip 198 168 1 121 安装tracker1 storage1 node02 ip 198 168 1 122 安装tracke
  • 2020年,给你7个程序员接私活必备网站!

    2020互联网圈不好混 不是每个公司都能像蚂蚁金服一样这么大气 不少公司今年因为疫情已经开始裁员 不要抱怨 加油干就完事了 今天给大家推荐几个赚钱养家的好渠道 一起来看看吧 1 程序员客栈 程序员的经纪人 https www proginn
  • Python人员信息管理系统(简直期末人福音)

    1 涉及模块 datetime os random sys PyQt5 2 运行效果 支持功能 添加信息 修改信息 删除信息 查询信息 文件存储数据 每次运行都会加载显示之前的信息 3 部分源码 创建字体对象 用来对要显示的文字进行设定fo
  • IIS 网站安装SSL证书

    步骤一 申请SSL证书 申请免费证书步骤 阿里云申请免费证书步骤 申请完成后 等待证书签发 签发后下载到本地 解压缩后会得到如下两个文件 一个证书文件 一个密码文件 步骤二 将文件复制到服务器上 双击证书文件安装 安装选计算机 安装过程中要
  • Graph Stacked Hourglass Networks for 3D Human Pose Estimation

    方法重复使用编码器 解码器 图形结构特征在三种不同尺度的骨骼中表示 获取局部和全局特征 使用不同深度中间特征的多层次特征学习方法 目前的基于GCN的方法有一些局限性 图卷积利用所有关节点信息 可以看做是所有特征仅在 一个尺度 上处理 很难获
  • 安全类常用网站

    目录 Burp Suite Burpsuite学院 安全测试常用的几个工具 Burp Suite Burp Suite Application Security Testing Software PortSwiggerGet Burp Su
  • UniswapV2核心合约学习(3)——UniswapV2Pair.sol

    记得朋友圈看到过一句话 如果Defi是以太坊的皇冠 那么Uniswap就是这顶皇冠中的明珠 Uniswap目前已经是V2版本 相对V1 它的功能更加全面优化 然而其合约源码却并不复杂 本文为个人学习UniswapV2核心合约源码的系列文章的
  • k8s指南-DNS与服务发现

    目录 1 k8s指南 概述 2 k8s指南 架构 3 k8s指南 工作负载 1 4 k8s指南 工作负载 2 5 k8s指南 工作负载 3 6 k8s指南 工作负载 4 7 k8s指南 Service 8 k8s指南 Ingress 9 k
  • Apache APISIX信息泄露漏洞(CVE-2022-29266)

    目录 漏洞概述 漏洞复现 环境搭建 攻击复现 漏洞概述 在2 13 1版本之前的APache APISIX中 攻击者可以通过向受 jwt auth 插件保护的路由发送不正确的 JSON Web 令牌来通过错误消息响应获取插件配置的机密 依赖
  • 百度、德勤管理咨询联合发布《知识中台白皮书》,聚焦企业知识赋能高效创新...

    近日 十九届五中全会审议通过的十四五规划36次提及科技 其中人工智能成为最高优先级 引领新一轮科技革命和产业革命的战略性技术 在十四五规划中发挥着关键作用 百度作为国内人工智能的头雁企业 致力于发挥 AI 技术领域多年积累的优势 以云计算为
  • 3. 内存管理(Memory Management)

    计算机有几兆字节的非常快速 昂贵 且易变的 cache memory 几千兆字节的中速 中等价格 易变的 main memory 以及几千兆字节缓慢 便宜 非易变的磁盘 固态硬盘存储 不涉及可移除的存储 例如 DVDs 和 USB 存储器