操作系统 - 内存管理


内存管理是操作系统的功能,它处理或管理主内存并在执行期间在主内存和磁盘之间来回移动进程。内存管理跟踪每个内存位置,无论它是分配给某个进程还是空闲的。它检查要分配给进程的内存量。它决定哪个进程在什么时间获得内存。当某些内存被释放或未分配时,它会进行跟踪,并相应地更新状态。

本教程将教您与内存管理相关的基本概念。

进程地址空间

进程地址空间是进程在其代码中引用的逻辑地址集。例如,当使用32位寻址时,地址范围可以是0到0x7fffffff;也就是说,2^31 个可能的数字,理论总大小为 2 GB。

操作系统在向程序分配内存时负责将逻辑地址映射到物理地址。在分配内存之前和之后,程序中使用三种类型的地址 -

序列号 内存地址和描述
1

符号地址

源代码中使用的地址。变量名、常量和指令标签是符号地址空间的基本元素。

2

相对地址

在编译时,编译器将符号地址转换为相对地址。

3

物理地址

当程序加载到主存储器时,加载器生成这些地址。

虚拟地址和物理地址在编译时和加载时地址绑定方案中是相同的。虚拟地址和物理地址在执行时地址绑定方案上有所不同。

程序生成的所有逻辑地址的集合称为逻辑地址空间。这些逻辑地址对应的所有物理地址的集合称为物理地址空间。

从虚拟地址到物理地址的运行时映射是由硬件设备内存管理单元(MMU)完成的。MMU 使用以下机制将虚拟地址转换为物理地址。

  • 基址寄存器中的值被添加到用户进程生成的每个地址上,该地址在发送到内存时被视为偏移量。例如,如果基址寄存器值为 10000,则用户尝试使用地址位置 100 将被动态重新分配到位置 10100。

  • 用户程序处理虚拟地址;它永远看不到真正的物理地址。

静态加载与动态加载

静态加载或动态加载之间的选择应在开发计算机程序时做出。如果您必须静态加载程序,那么在编译时,将编译和链接完整的程序,而不留下任何外部程序或模块依赖项。链接器将目标程序与其他必要的目标模块组合成绝对程序,其中还包括逻辑地址。

如果您正在编写动态加载的程序,那么您的编译器将编译该程序,并且对于您想要动态包含的所有模块,将仅提供引用,其余工作将在执行时完成。

在加载时,通过静态加载,将绝对程序(和数据)加载到内存中以便开始执行。

如果您使用动态加载,则库的动态例程将以可重定位的形式存储在磁盘上,并且仅在程序需要时才加载到内存中。

静态链接与动态链接

如上所述,当使用静态链接时,链接器将程序所需的所有其他模块组合成单个可执行程序,以避免任何运行时依赖性。

当使用动态链接时,不需要将实际的模块或库与程序链接,而是在编译和链接时提供对动态模块的引用。Windows 中的动态链接库 (DLL) 和 Unix 中的共享对象都是动态库的很好的例子。

交换

交换是一种机制,在该机制中,进程可以暂时从主内存交换(或移动)到辅助存储(磁盘),并使该内存可供其他进程使用。稍后,系统将进程从辅助存储交换回主内存。

虽然性能通常受到交换进程的影响,但它有助于并行运行多个大型进程,这就是交换也被称为内存压缩技术的原因。

进程交换

交换进程所花费的总时间包括将整个进程移动到辅助磁盘然后将进程复制回内存所花费的时间,以及进程重新获得主内存所花费的时间。

我们假设用户进程的大小为 2048KB,并且在将进行交换的标准硬盘上,数据传输速率约为每秒 1 MB。1000K 进程与内存之间的实际传输将花费

2048KB / 1024KB per second
= 2 seconds
= 2000 milliseconds

现在考虑进出时间,总共需要 4000 毫秒,加上进程竞争重新获得主内存的其他开销。

内存分配

主存储器通常有两个分区 -

  • 低内存- 操作系统驻留在该内存中。

  • 高内存- 用户进程保存在高内存中。

操作系统使用以下内存分配机制。

序列号 内存分配和描述
1

单分区分配

在这种类型的分配中,重定位寄存器方案用于保护用户进程彼此之间以及操作系统代码和数据的更改。重定位寄存器包含最小物理地址的值,而限制寄存器包含逻辑地址的范围。每个逻辑地址必须小于限制寄存器。

2

多分区分配

在这种类型的分配中,主内存被分为许多固定大小的分区,其中每个分区应仅包含一个进程。当分区空闲时,从输入队列中选择一个进程并将其加载到空闲分区中。当进程终止时,该分区可供另一个进程使用。

碎片化

当进程从内存中加载和删除时,可用内存空间被分成小块。有时会发生由于进程尺寸较小而无法将其分配给内存块并且内存块仍然未使用的情况。这个问题称为碎片。

碎片有两种类型 -

序列号 碎片和描述
1

外部碎片

总内存空间足以满足请求或在其中驻留进程,但它不是连续的,因此无法使用。

2

内部碎片

分配给进程的内存块更大。内存的某些部分未被使用,因为它不能被其他进程使用。

下图显示了碎片如何导致内存浪费,并且可以使用压缩技术从碎片内存中创建更多可用内存 -

内存碎片

可以通过压缩或混洗内存内容将所有空闲内存放在一个大块中来减少外部碎片。为了使压缩可行,重新定位应该是动态的。

可以通过有效地分配最小的分区但足够大的进程来减少内部碎片。

寻呼

计算机可以寻址的内存多于系统上物理安装的内存量。这种额外的内存实际上称为虚拟内存,它是硬盘的一部分,用于模拟计算机的 RAM。分页技术在虚拟内存的实现中发挥着重要作用。

分页是一种内存管理技术,其中进程地址空间被分成相同大小的块,称为(大小是 2 的幂,在 512 字节到 8192 字节之间)。进程的大小以页数来衡量。

类似地,主存储器被划分为称为帧的固定大小的(物理)存储器小块,并且帧的大小保持与页面的大小相同,以最佳地利用主存储器并避免外部碎片。

寻呼

地址翻译

页地址称为逻辑地址,由页号偏移量表示。

Logical Address = Page number + page offset

帧地址称为物理地址,由帧号偏移量表示。

Physical Address = Frame number + page offset

称为页映射表的数据结构用于跟踪进程的页与物理内存中的帧之间的关系。

页映射表

当系统将帧分配给任何页面时,它会将该逻辑地址转换为物理地址,并在页表中创建条目以在程序执行过程中使用。

当一个进程要执行时,其相应的页面被加载到任何可用的内存帧中。假设您有一个 8Kb 的程序,但在给定时间点您的内存只能容纳 5Kb,那么分页概念就会出现。当计算机耗尽 RAM 时,操作系统 (OS) 会将空闲或不需要的内存页面移动到辅助内存,以释放 RAM 用于其他进程,并在程序需要时将其带回。

这个过程在程序的整个执行过程中持续进行,操作系统不断从主内存中删除空闲页面,并将它们写入辅助内存,并在程序需要时将它们带回来。

分页的优点和缺点

以下是分页的优点和缺点的列表 -

  • 分页减少了外部碎片,但仍然受到内部碎片的影响。

  • 分页实现起来很简单,并且被认为是一种有效的内存管理技术。

  • 由于页面和框架的大小相同,交换变得非常容易。

  • 页表需要额外的内存空间,因此可能不适合 RAM 较小的系统。

分割

分段是一种内存管理技术,其中每个作业被分为多个不同大小的段,每个模块对应一个包含执行相关功能的片段。每个段实际上是程序的不同逻辑地址空间。

当一个进程要执行时,尽管每个段都被加载到连续的可用内存块中,但其相应的分段被加载到非连续的内存中。

分段内存管理的工作原理与分页非常相似,但这里的段是可变长度的,而分页中的页面是固定大小的。

程序段包含程序的主函数、实用函数、数据结构等。操作系统为每个进程维护一个段映射表和一个空闲内存块列表以及段号、它们的大小和主内存中相应的内存位置。对于每个段,该表存储该段的起始地址和该段的长度。对存储器位置的引用包括标识段的值和偏移量。

线段映射表