操作系统中的内存管理
术语内存可以定义为特定格式的数据集合。它用于存储指令和处理过的数据。存储器由一个大数组或一组字或字节组成,每个字或字节都有自己的位置。计算机系统的主要动机是执行程序。这些程序以及它们访问的信息在执行期间应该在主内存中。 CPU根据程序计数器的值从内存中取指令。
为了实现一定程度的多道程序设计和正确利用内存,内存管理很重要。存在多种内存管理方法,反映了各种方法,每种算法的有效性取决于具体情况。
Here, we will cover the following memory management topics:
- What is Main Memory
- What is Memory Management
- Why memory Management is required
- Logical address space and Physical address space
- Static and dynamic loading
- Static and dynamic linking
- Swapping
- Contiguous Memory allocation
- Memory Allocation
- First Fit
- Best Fit
- Worst Fit
- Fragmentation
- Internal Fragmentation
- External Fragmentation
- Paging
- Memory Allocation
之前,我们开始内存管理让我们知道什么是主内存。
什么是主内存:
主存储器是现代计算机操作的核心。主存储器是一个大的字或字节数组,大小从数十万到数十亿不等。主内存是 CPU 和 I/O 设备共享的快速可用信息的存储库。主存储器是处理器有效利用程序和信息时保存程序和信息的地方。主存储器与处理器相关联,因此将指令和信息移入和移出处理器的速度非常快。主存储器也称为 RAM(随机存取存储器)。该存储器是易失性存储器。RAM 在发生电源中断时丢失其数据。
什么是内存管理:
在多道程序计算机中,操作系统驻留在内存的一部分中,其余部分由多个进程使用。在不同进程之间细分内存的任务称为内存管理。内存管理是操作系统中在进程执行过程中管理主存和磁盘之间操作的一种方法。内存管理的主要目的是实现内存的高效利用。
为什么需要内存管理:
- 在进程执行之前和之后分配和取消分配内存。
- 跟踪进程使用的内存空间。
- 尽量减少碎片问题。
- 适当利用主存。
- 在执行过程时保持数据完整性。
现在我们正在讨论逻辑地址空间和物理地址空间的概念:
逻辑和物理地址空间:
逻辑地址空间: CPU 生成的地址称为“逻辑地址”。它也称为虚拟地址。逻辑地址空间可以定义为进程的大小。可以更改逻辑地址。
物理地址空间:内存单元看到的地址(即加载到内存的内存地址寄存器中的地址)通常称为“物理地址”。物理地址也称为实地址。与这些逻辑地址对应的所有物理地址的集合称为物理地址空间。物理地址由 MMU 计算。从虚拟地址到物理地址的运行时映射由硬件设备内存管理单元 (MMU) 完成。物理地址始终保持不变。
静态和动态加载:
将进程加载到主内存是由加载程序完成的。有两种不同类型的加载:
- 静态加载:- 在静态加载中,将整个程序加载到一个固定地址中。它需要更多的内存空间。
- 动态加载:- 整个程序和进程的所有数据必须在物理内存中才能执行。因此,进程的大小受限于物理内存的大小。为了获得适当的内存利用率,使用动态加载。在动态加载中,一个例程在被调用之前不会被加载。所有例程都以可重定位的加载格式驻留在磁盘上。动态加载的优点之一是从未加载未使用的例程。当需要大量代码来有效地处理它时,这种加载很有用。
静态和动态链接:
要执行链接任务,需要使用链接器。链接器是一种程序,它接受编译器生成的一个或多个目标文件,并将它们组合成一个可执行文件。
- 静态链接:在静态链接中,链接器将所有必需的程序模块组合成一个可执行程序。所以没有运行时依赖。某些操作系统仅支持静态链接,其中系统语言库被视为任何其他对象模块。
- 动态链接:动态链接的基本概念类似于动态加载。在动态链接中,每个适当的库例程引用都包含“存根”。存根是一小段代码。当存根被执行时,它会检查所需的例程是否已经在内存中。如果不可用,则程序将例程加载到内存中。
交换:
当一个进程被执行时,它必须驻留在内存中。交换是将进程从主内存临时交换到二级内存中的过程,与二级内存相比速度更快。交换允许运行更多进程,并且可以一次装入内存。交换的主要部分是传输时间,总时间与交换的内存量成正比。交换也称为转出、转入,因为如果有更高优先级的进程到达并需要服务,内存管理器可以将低优先级进程换出,然后加载并执行更高优先级的进程。在完成较高优先级的工作后,较低优先级的进程交换回内存并继续执行进程。
连续内存分配:
主内存应该同时负责操作系统和不同的客户端进程。因此,内存的分配成为操作系统中的一项重要任务。内存通常分为两个分区:一个用于常驻操作系统,一个用于用户进程。我们通常需要多个用户进程同时驻留在内存中。因此,我们需要考虑如何为输入队列中等待被引入内存的进程分配可用内存。在相邻内存分配中,每个进程都包含在一个连续的内存段中。
内存分配:
为了获得适当的内存利用率,必须以高效的方式分配内存。分配内存最简单的方法之一是将内存分成几个固定大小的分区,每个分区只包含一个进程。因此,多道程序的程度由分区数获得。
多分区分配:在这种方法中,从输入队列中选择一个进程并加载到空闲分区中。当进程终止时,该分区可用于其他进程。
固定分区分配:在这种方法中,操作系统维护一个表,指示哪些部分内存可用,哪些部分被进程占用。最初,所有内存都可用于用户进程,并被视为一大块可用内存。此可用内存称为“孔”。当进程到达并需要内存时,我们会寻找一个足够大的洞来存储这个进程。如果满足要求,则我们分配内存以进行处理,否则保留其余内存以满足未来的请求。在分配内存时,有时会出现动态存储分配问题,这涉及如何从空闲空洞列表中满足大小为 n 的请求。这个问题有一些解决方案:
第一次适合:-
在第一次配合中,第一个可用的空闲孔满足分配的工艺要求。
在这里,在此图中,40 KB 内存块是第一个可以存储进程 A(大小为 25 KB)的可用空闲孔,因为前两个块没有足够的内存空间。
最合适:-
在最佳配合中,分配足够大的最小孔以满足加工要求。为此,我们搜索整个列表,除非列表按大小排序。
在这个例子中,首先,我们遍历整个列表,找到最后一个洞 25KB 是最适合进程 A(大小 25KB)的洞。
在这种方法中,与其他内存分配技术相比,内存利用率最高。
最差配合:-在最差配合中,分配最大的可用孔进行加工。这种方法产生最大的剩余孔。
在此示例中,进程 A(大小 25 KB)分配给最大的可用内存块,即 60 KB。低效的内存利用率是最坏情况下的一个主要问题。
碎片化:
碎片被定义为当进程从内存中加载和删除后,它会创建一个小的空闲孔。这些空洞不能分配给新进程,因为空洞没有组合或不满足进程的内存要求。要实现一定程度的多道程序,必须减少内存浪费或碎片问题。在操作系统中,有两种类型的碎片:
内部碎片:
当分配给进程的内存块超过其请求的大小时,就会发生内部碎片。由于这个原因,一些未使用的空间会被剩余并产生内部碎片问题。
示例:假设有一个固定的分区用于内存分配和不同大小的块 3MB、6MB 和 7MB 的内存空间。现在一个大小为 2MB 的新进程 p4 来了,需要内存块。它获得了 3MB 的内存块,但是 1MB 的块内存是一种浪费,并且也不能分配给其他进程。这称为内部碎片。
外部碎片:
在外部碎片中,我们有一个空闲的内存块,但是我们不能将它分配给进程,因为块不是连续的。
示例:假设(考虑上面的示例)三个进程 p1、p2、p3 的大小分别为 2MB、4MB 和 7MB。现在它们分别分配了 3MB、6MB 和 7MB 大小的内存块。分配进程后,p1 进程和 p2 进程分别剩下 1MB 和 2MB。假设一个新进程 p4 来了,需要 3MB 的内存块,这是可用的,但我们不能分配它,因为可用内存空间不是连续的。这称为外部碎片。
受外部碎片影响的内存分配的第一个适合和最适合的系统。为了克服外部碎片问题,使用了 Compaction。在压缩技术中,所有空闲内存空间合并并形成一个大块。所以,这个空间可以被其他进程有效地使用。
外部碎片的另一种可能解决方案是允许进程的逻辑地址空间不连续,从而允许进程分配物理内存,只要后者可用。
分页:
分页是一种内存管理方案,无需连续分配物理内存。该方案允许进程的物理地址空间不连续。
- 逻辑地址或虚拟地址(以位表示):由 CPU 生成的地址
- 逻辑地址空间或虚拟地址空间(以字或字节表示):程序生成的所有逻辑地址的集合
- 物理地址(以位表示):内存单元上实际可用的地址
- 物理地址空间(以字或字节表示):与逻辑地址对应的所有物理地址的集合
例子:
- 如果逻辑地址 = 31 位,则逻辑地址空间 = 2 31字 = 2 G 字 (1 G = 2 30 )
- 如果逻辑地址空间 = 128 M 字 = 2 7 * 2 20字,则逻辑地址 = log 2 2 27 = 27 位
- 如果物理地址 = 22 位,则物理地址空间 = 2 22字 = 4 M 字 (1 M = 2 20 )
- 如果物理地址空间 = 16 M 字 = 2 4 * 2 20字,则物理地址 = log 2 2 24 = 24 位
从虚拟地址到物理地址的映射是由作为硬件设备的内存管理单元 (MMU) 完成的,这种映射被称为分页技术。
- 物理地址空间在概念上分为几个固定大小的块,称为帧。
- 逻辑地址空间也被分成固定大小的块,称为pages 。
- 页面大小 = 帧大小
让我们考虑一个例子:
- 物理地址 = 12 位,然后物理地址空间 = 4 K 字
- 逻辑地址 = 13 位,然后逻辑地址空间 = 8 K 字
- 页大小 = 帧大小 = 1 K 字(假设)
CPU产生的地址分为
- 页码(p):表示逻辑地址空间或页码中的页所需的位数
- 页偏移量(d):表示逻辑地址空间的页或页大小中的特定字或页或页偏移的字数所需的位数。
物理地址分为
- 帧号(f):表示物理地址空间帧或帧号帧所需的位数
- 帧偏移(d):表示帧中特定字所需的位数或物理地址空间的帧大小或帧或帧偏移的字数。
页表的硬件实现可以通过使用专用寄存器来完成。但是页表寄存器的使用只有在页表很小的情况下才能令人满意。如果页表包含大量条目,那么我们可以使用 TLB(translation Look-aside buffer),一种特殊的、小型的、快速查找的硬件缓存。
- TLB 是一种关联的高速存储器。
- TLB 中的每个条目由两部分组成:标签和值。
- 使用此内存时,项目会同时与所有标签进行比较。如果找到该项目,则返回相应的值。
Main memory access time = m
If page table are kept in main memory,
Effective access time = m(for page table) + m(for particular page in page table)
更多详情,必读操作系统中的分页