操作系统 - 内存管理

  • 简述

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

    进程地址空间是进程在其代码中引用的一组逻辑地址。例如,当使用 32 位寻址时,地址范围可以从 0 到 0x7fffffff;也就是说,2^31 个可能的数字,总理论大小为 2 GB。
    操作系统在为程序分配内存时负责将逻辑地址映射到物理地址。在分配内存之前和之后,程序中使用了三种类型的地址 -
    序列号 内存地址和描述
    1
    Symbolic addresses 符号地址
    源代码中使用的地址。变量名、常量和指令标签是符号地址空间的基本元素。
    2
    Relative addresses 相对地址
    在编译时,编译器将符号地址转换为相对地址。
    3
    Physical addresses 物理地址
    加载程序在程序加载到主存储器时生成这些地址。
    虚拟地址和物理地址在编译时和加载时地址绑定方案中是相同的。虚拟地址和物理地址在执行时地址绑定方案中有所不同。
    程序生成的所有逻辑地址的集合称为logical address space. 与这些逻辑地址对应的所有物理地址的集合称为physical address space.
    从虚拟地址到物理地址的运行时映射由作为硬件设备的内存管理单元 (MMU) 完成。MMU 使用以下机制将虚拟地址转换为物理地址。
    • 基址寄存器中的值被添加到用户进程生成的每个地址,在发送到内存时被视为偏移量。例如,如果基址寄存器值为 10000,则用户尝试使用地址位置 100 将被动态重新分配到位置 10100。
    • 用户程序处理虚拟地址;它永远不会看到真实的物理地址。
  • 静态与动态加载

    在开发计算机程序时选择静态或动态加载。如果您必须静态加载程序,那么在编译时,将编译和链接完整的程序,而不会留下任何外部程序或模块依赖。链接器将目标程序与其他必要的目标模块组合成一个绝对程序,其中还包括逻辑地址。
    如果您正在编写动态加载的程序,那么您的编译器将编译该程序,并且对于您想要动态包含的所有模块,将仅提供引用,其余工作将在执行时完成。
    在加载时,与static loading,绝对程序(和数据)被加载到内存中以便开始执行。
    如果您正在使用dynamic loading,库的动态例程以可重定位的形式存储在磁盘上,并且仅在程序需要时才加载到内存中。
  • 静态与动态链接

    如上所述,当使用静态链接时,链接器将程序所需的所有其他模块组合成单个可执行程序,以避免任何运行时依赖。
    使用动态链接时,不需要将实际的模块或库与程序链接,而是在编译和链接时提供对动态模块的引用。Windows 中的动态链接库 (DLL) 和 Unix 中的共享对象是动态库的好例子。
  • 交换

    交换是一种机制,其中一个进程可以暂时从主内存(或移动)交换到辅助存储(磁盘),并使该内存可供其他进程使用。在稍后的某个时间,系统将进程从辅助存储器交换回主存储器。
    虽然性能通常会受到交换进程的影响,但它有助于并行运行多个大型进程,这就是原因Swapping is also known as a technique for memory compaction.
    进程交换
    交换进程所花费的总时间包括将整个进程移动到辅助磁盘然后将进程复制回内存所花费的时间,以及进程重新获得主内存所花费的时间。
    让我们假设用户进程的大小为 2048KB,并且在将进行交换的标准硬盘上,数据传输速率约为每秒 1 MB。1000K 进程进出内存的实际传输将花费
    
    2048KB / 1024KB per second
    = 2 seconds
    = 2000 milliseconds
    
    现在考虑进出时间,它将花费完整的 4000 毫秒加上进程竞争重新获得主内存的其他开销。
  • 内存分配

    主存储器通常有两个分区 -
    • Low Memory− 操作系统驻留在此内存中。
    • High Memory− 用户进程保存在高内存中。
    操作系统使用以下内存分配机制。
    序列号 内存分配和描述
    1
    Single-partition allocation
    在这种类型的分配中,重定位寄存器方案用于保护用户进程相互之间以及操作系统代码和数据的更改。重定位寄存器包含最小物理地址的值,而限制寄存器包含逻辑地址范围。每个逻辑地址必须小于限制寄存器。
    2
    Multiple-partition allocation
    在这种类型的分配中,主内存被分成许多固定大小的分区,每个分区应该只包含一个进程。当一个分区空闲时,从输入队列中选择一个进程并加载到空闲分区中。当进程终止时,该分区可用于另一个进程。
  • 碎片化

    随着进程被加载和从内存中删除,可用内存空间被分成小块。有时会发生这种情况,因为考虑到它们的小尺寸并且内存块仍未使用,因此无法将进程分配给内存块。这个问题被称为碎片。
    碎片有两种类型 -
    序列号 碎片化和描述
    1
    External fragmentation
    总内存空间足以满足一个请求或在其中驻留一个进程,但它不是连续的,因此不能使用。
    2
    Internal fragmentation
    分配给进程的内存块更大。内存的某些部分未被使用,因为它不能被另一个进程使用。
    下图显示了碎片如何导致内存浪费,并且可以使用压缩技术从碎片内存中创建更多空闲内存 -
    内存碎片
    可以通过压缩或混洗内存内容以将所有空闲内存放在一个大块中来减少外部碎片。为了使压缩可行,重定位应该是动态的。
    可以通过有效分配最小但足够大的分区来减少内部碎片。
  • 寻呼

    计算机可以寻址比系统上实际安装的数量更多的内存。这个额外的内存实际上被称为虚拟内存,它是硬件的一部分,用于模拟计算机的 RAM。分页技术在实现虚拟内存中起着重要作用。
    分页是一种内存管理技术,其中进程地址空间被分成相同大小的块,称为pages(大小是 2 的幂,介于 512 字节和 8192 字节之间)。进程的大小以页数来衡量。
    类似地,主内存被划分为小的固定大小的(物理)内存块,称为frames帧的大小与页的大小保持一致,以优化主存的利用率,避免外部碎片。
    寻呼

    地址翻译

    页面地址被调用logical address并由page numberoffset.
    
    Logical Address = Page number + page offset
    
    帧地址被调用physical address并由 a 表示frame numberoffset.
    
    Physical Address = Frame number + page offset
    
    一种数据结构称为page map table用于跟踪进程的页面与物理内存中的帧之间的关系。
    页面映射表
    当系统将帧分配给任何页面时,它会将这个逻辑地址转换为物理地址,并在页表中创建条目以在整个程序执行过程中使用。
    当一个进程要被执行时,它的相应页面被加载到任何可用的内存帧中。假设您有一个 8Kb 的程序,但您的内存在给定时间点只能容纳 5Kb,那么分页概念就会出现。当计算机的 RAM 用完时,操作系统 (OS) 会将空闲或不需要的内存页面移动到辅助内存中,以便为其他进程释放 RAM,并在程序需要时将它们带回来。
    该过程在程序的整个执行过程中继续进行,其中操作系统不断从主存储器中删除空闲页面并将它们写入辅助存储器并在程序需要时将它们带回。

    分页的优缺点

    以下是分页的优缺点列表 -
    • 分页减少了外部碎片,但仍然受到内部碎片的影响。
    • 分页很容易实现,并被认为是一种有效的内存管理技术。
    • 由于页面和框架的大小相同,交换变得非常容易。
    • 页表需要额外的内存空间,因此可能不适合具有小 RAM 的系统。
  • 分割

    分段是一种内存管理技术,其中每个作业被分成几个不同大小的段,每个模块包含执行相关功能的片段。每个段实际上是程序的不同逻辑地址空间。
    当要执行一个进程时,尽管每个段都被加载到一个连续的可用内存块中,但它的相应分段被加载到非连续内存中。
    分段内存管理的工作方式与分页非常相似,但这里的段是可变长度的,而分页页面是固定大小的。
    程序段包含程序的主函数、实用函数、数据结构等。操作系统维护一个段映射表对于每个进程和空闲内存块列表以及段号、它们的大小和主内存中的相应内存位置。对于每个段,该表存储段的起始地址和段的长度。对内存位置的引用包括标识段和偏移量的值。
    段映射表