操作系统内存管理

Aki 发布于 2023-03-13 232 次阅读


内存管理的基本原理和要求、

计算机不可能将所有用户进程和系统所需要的全部程序和数据放入主存,因此操作系统必须对内存空间进行合理的划分和有效的动态分配。内存管理的概念就是操作系统对内存的划分和动态分配。

内存管理功能:

  • 内存空间的分配与回收:由操作系统完成主存储器空间的分配和管理,是程序员摆脱存储分配的麻烦,提高编程效率。
  • 地址转换:将逻辑地址转换成相应的物理地址。
  • 内存空间的扩充:利用虚拟存储技术或自动覆盖技术,从逻辑上扩充主存。
  • 存储保护:保证各道作业在各自的存储空间内运行,互不干扰。

创建进程首先要将程序和数据装入内存。将用户源程序变为可在内存中执行的程序,通常需要以下几个步骤:

  1. 编译:由编译程序将用户源代码编译成若干目标模块(把高级语言翻译成机器语言)
  2. 链接:由链接程序将编译后形成的一组目标模块及所需的库函数连接在一起,形成一个完整的装入模块(由目标模块生成装入模块,链接后形成完整的逻辑地址)
  3. 装入:由装入程序将装入模块装入内存运行,装入后形成物理地址

程序的链接有以下三种方式:

  1. 静态链接:在程序运行之前,先将各目标模块及它们所需的库函数连接成一个完整的可执行文件(装入模块),之后不再拆开。
  2. 装入时动态链接:将各目标模块装入内存时,边装入边链接的链接方式。
  3. 运行时动态链接:在程序执行中需要该目标模块时,才对它进行链接。其优点是便于修改和更新,便于实现对目标模块的共享。

内存的装入模块在装入内存时,有以下三种方式:

重定位:根据内存的当前情况,将装入模块装入内存的适当位置,装入时对目标程序中的指令和数据的修改过程称为重定位。

  • 静态重定位:地址的变换通常是在装入时一次完成的。一个作业装入内存时,必须给它分配要求的全部内存空间,若没有足够的内存,则不能装入该作业。此外,作业一旦装入内存,整个运行期间就不能在内存中移动,也不能再申请内存空间。
  • 动态重定位:需要重定位寄存器的支持。可以将程序分配到不连续的存储区中;在程序运行之前可以只装入它的部分代码即可投入运行,然后在程序运行期间,根据需要动态申请分配内存。

内存分配前,需要保护操作系统不受用户进程的影响,同时保护用户进程不受其他用户进程的影响。内存保护可采取如下两种方法:

  1. 在CPU中设置一对上、下限寄存器,存放用户作业在主存中的上限和下限地址,每当CPU要访问一个地址时,分别和两个寄存器的值相比,判断有无越界。
  2. 采用重定位寄存器(或基址寄存器)和界地址寄存器(又称限长存储器)来实现这种保护。重定位寄存器包含最小的物理地址值,界地址寄存器含逻辑地址的最大值。每个逻辑地址值必须小于界地址寄存器;内存管理机构动态得将逻辑地址与界地址寄存器进行比较,若未发生地址越界,则加上重定位寄存器的值后映射成物理地址,再送交内存单元。例如基址寄存器存储的首地址是1000,界地址寄存器存储的是5000,假如我要访问一个虚拟地址3500,MMU会计算3500 <= (1000 + 5000) && (3500 >= 1000) ,如果这个表达式为真的话就会继续执行,假的话就会出错造成地址越界。

覆盖与交换、

覆盖与交换技术是在多道程序环境下用来扩充内存的两种方法,目的是减少程序占用的主存空间来扩充内存。覆盖是在同一个程序或进程中的,交换是在不同进程之间的。

覆盖技术的基本思想:将程序分为多个段,常用的段常驻内存,不常用的段在需要时调入内存。特点:打破了必须将一个进程的全部信息装入主存后才能运行的限制,解决了程序大小超过物理内存总和的问题。但对用户不透明,增加了编程的负担。首先,由于需要手动管理程序的内存使用,因此增加了编程的复杂性和负担。其次,覆盖技术可能导致程序的执行效率降低,因为每次加载模块都需要进行磁盘IO操作,这会增加程序的响应时间。最后,覆盖技术可能会使程序的调试和维护更加困难,因为程序的执行可能会跨越多个模块和内存区域。

交换技术的基本思想:内存空间紧张时,系统将内存中的某些进程暂时换出外存,把外存中某些已具备运行条件的进程换入内存。交换的时机选择的策略:

  1. 基于进程的优先级选择交换时机,将优先级较低的进程交换出去,以保证优先级高的进程能够及时得到执行。
  2. 基于页面的局部性原理选择交换时机,将最近不常访问的页面交换出去,以保留那些频繁被访问的页面,从而提高系统的性能。

换出的程序通常是保存在操作系统维护的交换分区中,也被称为交换文件或者交换区。交换分区是指操作系统预留出的一部分磁盘空间,用于存放被交换出的进程或页面数据。在需要将进程或页面换出到磁盘上时,操作系统会将进程或页面的数据保存到交换分区中,然后释放内存空间,以便让其他进程或页面使用。

当需要将进程或页面调入内存时,操作系统会将保存在交换分区中的数据读取到内存中,然后重新开始执行。这种操作虽然会增加一定的磁盘IO开销,但是通过合理的交换策略和内存管理方式,可以保证系统的性能和稳定性。

连续分配管理方式、

连续分配方式是指为一个用户程序分配一个连续的内存空间。主要包括单一连续分配、固定分区分配和动态分区分配。

内部碎片是指在内存分配时,由于申请的内存大小与内存管理单位的大小不匹配,导致分配的内存中有一部分无法被有效利用,而浪费掉的内存空间就叫做内部碎片。

举个例子,如果一个进程申请了100字节的内存,而内存管理单位的大小为4字节,那么实际上该进程会被分配104字节的内存。其中,有4字节的内存空间被浪费掉了,因为这个内存无法被有效利用,这就是内部碎片。

外部碎片是指在内存分配时,由于已分配内存与未分配内存之间的空间无法被有效利用,导致剩余的空间无法分配给需要内存的进程而浪费的内存空间,这就叫做外部碎片。

举个例子,如果一个进程需要分配一块1000字节的内存,但由于内存中已分配的空间和未分配的空间之间有很多零散的空闲块,这些空闲块的总和足够分配给该进程,但是由于它们不连续,无法被合并利用,导致进程无法获得足够的内存,这就是外部碎片。

内部碎片和外部碎片都会导致内存的浪费,降低系统的内存利用效率。为了尽可能减少内部碎片和外部碎片,内存管理器通常会采用一些算法和策略,如分区分配、伙伴系统等。

现代操作系统的内存分配方式--动态分区分配(没有内部碎片,但有外部碎片)

动态分区分配不预先分配内存,而是在进程装入内存时,根据进程的大小动态地建立分区,并使分区的大小正好适合进程的需要。系统中分区的大小和数目是可变的。动态分区分配会产生外部碎片,克服外部碎片可以采用紧凑技术来解决,即操作系统不时地对进程进行移动和整理。但这需要重定位寄存器的支持,且相对费时。

动态分区分配的策略有以下几种算法:

  1. 首次适应算法:按地址从小到大为序,分配第一个符合条件的分区。
  2. 最佳适应算法:按空间从小到大为序,分配第一个符合条件的分区。
  3. 最坏适应算法:按空间从大到小为序,分配第一个符合条件的分区。
  4. 邻近适应算法:与首次适应相似,从上次查完的结束位置开始查找。