Loading...

文章背景图

内存管理

2025-12-19
27
-
- 分钟
|

内存管理的概念

内存管理主要实现的是:

  1. 内存空间的分配与回收

  2. 内存空间的扩充(实现虚拟性)

  3. 地址转换(实现虚拟地址到物理地址的转换)

  4. 存储保护(保证各进程在自己的内存空间内运行,不会越界访问)

其中地址转换包括三种方式:

  • 绝对装入:编译器负责地址转换(程序编译好后就无法改变,因此适用于早期的单道程序处理)

  • 可重定位装入:装入程序负责地址转换(在装入时由装入程序一次性完成地址转换。程序一旦装入内存,其物理地址就固定了,在运行期间不能移动。这支持多道程序,但不支持进程在内存中的移动和交换)

  • 动态运行时装入:运行时才进行地址转换(只有当运行该指令时才会根据重定位寄存器的值对应到正确的地址,这使得进程在运行时可以被换出、换入到不同的物理位置,是实现虚拟内存的基础)

存储保护的两种方式:

  • 设置上下限寄存器

  • 利用重定位寄存器和界地址寄存器确定

进程的内存映像

注:

  • .text:用于存放代码段

  • .data:用于存放已经初始化的全局/静态变量

  • .bss:用于存放未初始化的全局/静态变量

内存空间的扩充

覆盖技术

思想:将程序分为多个段(多个模块)。常用的段常驻内存,不常用的段在需要的时候调入内存。内存中分为一个固定区和多个覆盖区,需要常驻内存的段放在固定区,调入内存后不再调出;不常用的段放在覆盖区,需要时调入内存,不需要时调出内存。

要想完成覆盖,必须要求程序员事先声明覆盖结构,操作系统自动完成覆盖。

交换技术

思想:在内存空间紧张时,系统将内存中的某些进程暂时调出外存,把某些具备执行条件的进程从外存调入内存(中级调度:内存调度)

注:

  • 低级调度(进程调度):将内存中的进程调入或调出处理机

  • 中级调度(内存调度):将进程调入或调出内存

  • 高级调度(作业调度):创建一个进程

暂时调出内存的进程状态称为挂起态,根据进程调出内存前的状态,又分为就绪挂起和阻塞挂起。因此有了进程的七状态模型。

虚拟存储技术

见后文

内存空间的分配与回收

连续分配管理方式

指为用户分配的进程空间必须是连续的

单一连续分配

在单一连续分配中,内存被分为系统区和用户区,用户区用于存放用户进程相关数据,同一时刻内存中只能有一个用户程序,用户程序独占整个用户区。

优点:实现简单;无外部碎片;可采用覆盖技术扩充内存;

缺点:只能用于单用户、单任务操作系统;有内部碎片;存储器利用率极低;

固定分区分配

在固定分区分配中。内存的用户区被分为一个个固定大小的分区,在每个分区中只装入一个作业。操作系统需要建立一个分区说明表,来实现各个分区的分配与回收。固定分区分陪又分为分区大小相等、分区大小不等。

分区大小相等:缺乏灵活性,适合相同的多个作业同时在处理机上运行

分区大小不等:增加灵活性,可以按照进程大小不同分配到不同的分区

优点:无外部碎片;实现简单;

缺点:会产生内部碎片;

动态分区分配

动态分区分配又称可变分区分配,这种分配方式不会预先划分内存分区,而是在进程装入内存之后,根据进程的大小,动态地创建分区

优点:无内部碎片;

缺点:会产生外部碎片;

外部碎片可以用“紧凑”技术来解决

动态分区分配算法

非连续分配管理方式

基本分页管理方式

逻辑地址结构

逻辑地址由两部分组成:页号 + 页内偏移量。

偏移量的位数决定了页面大小(例如,偏移量12位,则页面大小为 2^12=4KB)。

页表

操作系统为每个进程维护一个页表,存储在内存中。页表的索引是逻辑页号,其内容是该页对应的物理块号 。

计算物理地址

公式:物理地址 = (物理块号 × 页面大小) + 页内偏移量

思想

通过进程给出的逻辑地址所对应的页面,在页表中找到该页面对应的物理块号,然后通过物理块号和逻辑地址中的偏移量计算出物理地址

基本地址变换机构

用于实现从逻辑地址到物理地址的硬件

快表

又称联想寄存器,是一种访问速度比内存快很多的高速缓存(TLB不是内存也不是Cache),用来存放最近访问的页表项的副本,可以加速地址变换的速度,与此对应,内存中的页表常称为慢表

多级页表

页表的套娃,用于解决进程太大导致的页表过长问题,即将过长的页表分为多个页存储,并为每个页表页创建一个页表项,通过进程的逻辑地址的找到顶级页表对应的页号以及该页号对应的物理块号,找到次级页表在内存中的位置,再通过较高位的逻辑地址找到次级页表对应的页号以及该页号对应的物理块号,找到下一级页表在内存中的位置,依次类推,知道找到最低级页表对应的物理块号,通过该物理块号与逻辑地址偏移量计算出物理地址

基本分段管理方式

逻辑地址结构

逻辑地址由两部分组成:段号 + 段内偏移量。

段号的位数决定了操作系统最多可以为一个进程分配多少个段,段内偏移量的位数决定了一个段的大小

段表

操作系统会为每个进程维护一个段表,存储在内存中,段表的索引是逻辑段号,内容是表长和基址

计算物理地址

由于进程的每个段是不等长的,因此需要先计算目标段在段表当中的物理地址,方法如下:

  1. 确定段表的起始地址M,段表项长度L,

  2. 第k段表项地址 = M + k*L

得到该段表项在段表的物理地址之后,根据段表项给出的基址 + 逻辑地址偏移量 = 物理地址

思想

通过进程给出的逻辑地址所对应的段号和段表的起始地址,计算出该段表项在段表中的地址,在段表中找到该段表项对应的基址,然后通过基址和逻辑地址中的偏移量计算出物理地址

段页式管理方式

分页、分段管理的优缺点

优点

缺点

分页管理

内存空间利用率高,不会产生外部碎片,只有少量页内碎片

不方便按照逻辑模块实现信息的共享和保护

分段管理

很方便按照逻辑模块实现信息的共享和保护

如果段长过大,为其分配很大的连续空间会很不方便。

另外,段式管理会产生外部碎片

逻辑地址结构

逻辑地址由三部分组成:段号 + 页号 + 页内偏移量。

其中页号 + 页内偏移量就是分段管理方式中将段内偏移量拆分的结果

段号的位数决定了操作系统最多可以为一个进程分配多少个段,页号决定了一个段最多能被分配多少页,页内偏移量决定了页面和内存块的大小

段表、页表

段页式管理方式既有段表也有页表(一个进程会对应一个段表,一个段表可能会对应多个页表),都存储在内存中

段表:段表的索引是逻辑段号,内容是页表长度和页表存放块号(与分段管理的段表内容不同)

页表:页表的索引是逻辑页号,内容是对应的内存块号(与分页管理相似)

计算物理地址

方式类似分页外套分段:

根据段号和段表起始地址计算出目标段表项的地址 = 段表起始地址 + 段号 * 段表项长度

根据段表项找到页表存放块号

根据逻辑地址中的页号,确定内存块号

物理地址 = 内存块号 + 页内偏移量

思想

分页管理套分段

虚拟存储技术

传统存储的特点

一次性:进程运行时会一次性全部装入内存

驻留性:装入后会一直驻留在内存中,知道运行结束

虚拟内存的特点

多次性:作业运行可以多次装入内存(与传统存储的一次性对应)

对换性:允许作业运行时换进、换出内存(与传统存储的驻留性对应)

虚拟性:从了逻辑上扩充了内存容量

虚拟存储的实现

需要OS提供请求调页功能和页面置换功能

请求分页管理方式

页表

页号

内存块号

状态位

访问字段

修改位

外存地址

状态位:记录了是否在内存中

访问字段:记录了该页被访问了几次(可以为页面置换算法的选择提供参考)

修改位:记录了该页被调入内存后数据是否被修改

缺页中断机构

找到页表项后检查该页是否在内存中,若没在内存中,则产生缺页中断

缺页中断处理,需要把目标页面调入内存,当内存中没有空闲的内存块时,还需要按照页面置换算法调出某些内存

地址变换机构

页面置换算法

最佳置换算法(OPT)

规则:优先淘汰在未来最长时间不会被访问的页面

特点:性能最好,但无法实现

先进先出算法(FIFO)

规则:按照先进先出原则,优先淘汰最早调入的页面

特点:规则简单,但性能差,会出现belady异常(随着页面增加,缺页率不降反增)

当前最久未使用算法(LRU)

规则:优先淘汰当前时刻之前,最久没有被访问的页面

特点:性能很好,但是算法开销大

时钟置换算法(CLOCK)

规则:需要增加一个访问位(访问位为1,表示最近访问过;访问位为0,表示最近没有被访问过),循环扫描各页面,第一轮淘汰访问位为0的,并将扫描过的页面访问位置为0,若第一轮没选中,则进行第二轮扫描

特点:实现简单,算法开销小,但未考虑页面是否被修改

改进型时钟置换算法

规则:用二元组(访问位,修改位)的形式表示:

  1. 第一轮:淘汰(0,0)

  2. 第二轮:淘汰(0,1),并将扫描过的页面访问位置为0

  3. 第三轮:淘汰(0,0)

  4. 第四轮:淘汰(0,1)

特点:性能不错,算法开销小

页面分配策略

一些概念

驻留集:给进程分配的内存块页框的集合

工作集:某时间段内,访问页面的集合

抖动:刚调入内存的页面又被调出内存,刚调出内存的页面又被调入内存

分配置换策略

按照驻留集是否可变分为:

  1. 固定分配

  2. 可变分配

按照可置换范围分为:

  1. 局部置换

  2. 全局置换

固定

可变

局部

全局

其中固定分配的全局置换无法实现,可变分配的局部置换最优

何时调入页面

预调页

请求调页

何处调入页面

swap

内存映射文件

内存映射文件是操作系统向上层程序员提供的功能(系统调用)

  • 方便程序员访问文件数据

  • 方便多个进程共享一个数据

评论交流

文章目录