3.1 内存管理概念
程序放入内存才能执行【缓解CPU与硬盘速度差异大的矛盾】
3.1.1 内存管理的基本原理和要求
- 内存管理的主要功能:
- 1.内存分配与回收
- 2.地址转换:逻辑地址转换成物理地址
- 3.内存空间的扩充
- 4.内存共享
- 5.存储保护
- ①设置上下限寄存器
- ②采用重定位寄存器
(基地址寄存器)
和界地址寄存器(限长寄存器)
进行越界检查,若出现问题
就抛出异常。
程序的链接与装入
-
编译:源代码编译成多个目标模块。
-
链接:将多个模块链接成一个完整模块。【形成完整逻辑地址】
- (1) 静态链接:程序运行前就把所有模块和所需库函数链接到一起。
- ①修改相对地址
- ②变换外部调用符号
- (2)装入时动态链接:装入内存时链接。
- (3)运行时动态链接:在运行时仅当需要模块时才加载进来。【可以加快装入过程,节省内存空间】
- (1) 静态链接:程序运行前就把所有模块和所需库函数链接到一起。
-
装入:将程序加载进内存。
将【逻辑地址】(相对地址)
映射到【绝对地址】(物理地址)
-
(1) 绝对装入
解释:知道程序放在哪个位置
,在编译时将地址修改成物理地址
。
适用于:无操作系统时期的弹道程序环境,灵活性低。 -
(2)可重定向装入 【静态重定位】
解释:在程序装入内存时才逻辑地址
改为物理地址
。
适用于:早期多道批处理操作系统。
缺点:装入内存时必须分配全部空间。 -
(3)动态运行时装入 【动态重定位】
解释:装入内存时保持使用逻辑地址。使用重定位寄存器
保存模块起始位置。在CPU执行时才将逻辑地址
和重定位地址
相加获取实际地址
。
适用于:现代计算机系统
优点:不需要分配连续内存,可以仅仅装入部分代码运行,动态申请分配内存。便于程序段的共享。
-
3.1.2 覆盖于交换[新大纲已删除]
3.1.3连续分配管理方式
连续分配方式是指的为一个用户程序分配一个连续的内存空间
。
-
(1)单一连续分配:
解释:内存划分成系统区
【操作系统使用】和用户区
【用户进行独占使用】。一次性只能加载运行一个进程。
优点:简单无外部碎片。无需内存保护。
缺点:只适用于单用户单任务系统,存在内部碎片,利用率低。
-
(2)固定分区分配:
解释:内存划分成若干固定大小
的区域,一个分区
只能装入一个作业
。仅当有空闲分区时才从后备作业队列选择合适大小的作业装入。
优点:简单无外部碎片。
缺点:存在内部碎片,利用率低。
存在问题:程序过大,放不经分区。固定分区过小,也占用完整分区,浪费空间。- 分区大小相同:
分区过大
容易导致浪费
,分区过小
程序无法装入
。 - 分区大小不同:划分
多个
小分区,适量
中等分区,少量
大分区。
- 分区大小相同:
-
(3)动态分区分配:
解释:不会预先分配内存空间,转入时
根据进程大小
动态建立分区。
优点:无内部碎片
缺点:有外部碎片
紧凑技术:通过将进程移动到相邻空间,从而让出更大连续空间。可以解决外部碎片
。
内存分区的分配与回收:
- 分配
- 空闲区
大于
所需空间:修改
空闲分区表的起始位置
和大小
。 - 空闲区
等于
所需空间:删除
对应的分区表元素。
- 空闲区
- 回收
- 回收空间有一边
相邻空闲空间
:将回收的空间与相邻空闲空间合并。修改空闲分区表的值。 - 回收空间两边都有
相邻空闲空间
:合并三个分区,修改其中一个空闲分区表的元素并删除另一个元素 - 前后都无
相邻空闲空间
:新添空闲分区表元素。根据具体算法
排列。
- 回收空间有一边
动态分区的分配策略:
- 首次适应算法
解释:空闲分区以地址递增
的次序链接。从链首顺序查找第一个合适的空闲分区。
评价:综合性能最好,很小概率导致后面的大分区被小进程划分变很小,能装下较大进程。不需要重新排列分区表。碎片容易聚集在低地址。 - 邻近适用
解释:在首次适应算法的基础上
,从上一次查找的位置往后查找。
评价:由于不是从第一个开始查找,很大概率将后面的大分区划分得非常小,导致不能装入大进程【最坏适应算法的缺点】。不需要重新排列分区表。 - 最佳适应
解释:将空闲区按照容量
从小到大排序,然后从链头向后查找。找到第一个满足要求的最小空间
。
评价:容易产生很多外部碎片
。 - 最坏适应
解释:将空闲空间安州容量
从大到小排序,每次适用链头的哪个空间。
评价:不断地使用最大连续空间,大进程可能无法装入。
3.1.4 基本分页存储管理
进程
的块称为页
或者页面
。【逻辑划分】
内存
的块称为页框
或者页帧
。【物理划分】
页(页面)
的大小和页框(页帧)
的大小相等。
每个进程的页表都是私有
,不可共享。
页的逻辑结构:页号+页内偏移量
页表项的结构:页号【不需要保存】+块号
页表寄存器结构:页表起始地址+页表长度
页表会在内存中长期驻留,无论当前是否在运行中。
在进行进程调度时,会将新进程的PCB中的页表起始地址
和页表长度
写入页表寄存器
。
页表访存需要经过2次访存:访问页表,访问数据。
-
页表的访问流程:
- 1.根据
逻辑地址
中的页号
和页表寄存器
中的页表长度
对比。如果页号大于等于页表长度,产生越界中断
。 - 2.根据
页号
和页表起始地址
获取页表项
从而获知数据的物理块号。 - 3.根据
物理块号地址
和页内偏移量
获取实际物理地址。
- 1.根据
-
页式管理是一维地址,只需要一个信息就能获取实际物理位置。
-
使用快表加速地址变换:
- 块表: 是一种
高速缓冲存储器
。全相联存储器【根据内容访问数据】。 - 访问流程:
- 1.使用
逻辑地址
中的页号
查找块表
中的数据。如果没有找到
,接下来流程和无块表
的流程一样。 - 2.找到
块表
内容,将块表中对应表项的块号和页内偏移量
转换成物理地址
。
- 1.使用
- 块表: 是一种
-
多级页表:
- 使用目的: 页式存储是一种非连续的存储方式。如果页表项过多,会导致需要大量连续空间存储页表,与目的相违背。
还有局部性原理
,程序运行不必加载完全部内容才开始运行。 - 使用多级页表基地址寄存器存放的是顶级页表的地址。
- 使用目的: 页式存储是一种非连续的存储方式。如果页表项过多,会导致需要大量连续空间存储页表,与目的相违背。
虚拟存储应用:给页表项
添加一个标志位,判断是否在页面中,不在发生缺页中断
。
3.1.5 基本分段存储管理
根据
逻辑
和和功能
划分。
分段管理满足方便编程
,信息保护
,动态增长,动态链接
的需求。
编译程序时
将各段转化成段号。
段的逻辑结构:段号+页内偏移量
段表项的结构:段号【不需要保存】+段长+段的起始物理地址
段表寄存器结构:段表起始地址+段表长度
在进行进程调度时,会将新进程的PCB中的段表起始地址
和段表长度
写入段表寄存器
。
-
页表的访问流程:
- 1.根据
逻辑地址
中的段号
和段表寄存器
中的页表长度
对比。如果段号大于等于段表长度,产生越界中断
。 - 2.根据
段号
和段表起始地址
获取段表项
从而获知数据的物理块号。 - 3.根据
物理块号地址
和页内偏移量
获取实际物理地址。
- 1.根据
-
段的共享与保护:
- 共享: 让需进程的段表指向相同地址。
- 保护: 只需标记是否允许访问。
-
段式管理是二维地址,只需要一个段号和段内偏移量。
3.1.6 段页式管理
段和页的对比
页 | 段 | |
---|---|---|
大小是否固定 | 是 | 否 |
是否有外部碎片 | 无 | 有 |
是否有内部碎片 | 有 | 无 |
内存利用率 | 高 | 低,段过长,分配连续空间不便 |
管理 | 操作系统管理,对用户透明 | 用户和操作系统共同管理 |
维度 | 一维 | 二维 |
一个进程只有一个段表,一个段有一个页表。因此
段表只能有一个,页表可以有多个。
段页的逻辑结构:段号+页号+页内偏移量
段表项的结构:段号【不需要保存】+页表长+页表起始地址
页表项结构:页号【不需要保存】+块号
段表寄存器结构:段表起始地址+段表长度
- 段页表的访问流程:
- 1.根据逻辑地址获得
段号
和页号
,页内偏移量
。 - 2.根据
段号
找到段表项【页表长,页变块号】
- 3.检查
页号
合法性 - 4.根据
页表
找到页表项
。
- 1.根据逻辑地址获得
补充:
- 重定位寄存器:保存物理地址的起始位置
- 界地址寄存器:保存逻辑的最大值
(上界地址寄存器)
和最小值(下界地址寄存器)