# 内存管理之一
# 内存管理功能
# 存储器功能要求
- 容量足够大
- 速度足够快
- 信息永久保存
- 多道程序并行
# 多道并行的问题
- 共享:代码和数据共享,节省内存
- 保护:不允许内存中的程序相互非法访问
# 存储体系
- 三级存储体系
- 组成
- cache:快、小、贵
- 内存:适中
- 辅存:慢、大、廉价
- 基本原理
- 内存不够用时,用辅存来支援内存
- 暂时不运行的模块切换到辅存上,必要时再切回内存
# 存储管理的功能
# 地址映射
将程序中的地址(虚拟地址、逻辑地址)变换成内存中的真实地址(实地址、物理地址)。
# 三种地址映射方式
- 固定地址映射:编译或编程时确定逻辑地址和物理地址的映射关系,比如编程时就直接制定物理地址。
- 静态地址映射:程序装入的时候,由操作系统完成逻辑地址到物理地址映射,比如双击exe的时候,程序装入内存,操作系统进行地址映射。
例子:有一段程序,其虚拟地址空间为
在程序装入的时候,将这块虚拟地址空间整体移动到真实物理内存中,起始位置是BA(基址,Base Addr.),如下图所示:
此时,(物理地址) = (基址) + (虚拟地址)
- 动态地址映射:在程序执行过程中完成地址映射。
例如:
MOV AX,[500] //访问500单元时执行地址映射
这个过程中,如果程序有移动,BA可能发生改变,需要自动计算新的MA,程序占用的内存空间可以动态变化,这样程序不要求连续的内存空间,只要每段放置的基址能够知道。
# 虚拟存储
解决的问题是,当程序过大或者过多的时候,内存不够,无法运行;多个程序并发时地址冲突,不能运行。
虚拟内存是面向用户的虚拟封闭存储空间,是一个线性的地址空间,程序员进行编程时都是使用线性的虚拟地址。
# 内存分配
需要解决的问题:
- 放置策略:程序调入内存时将其放置在哪个内存区
- 调入策略:何时把要运行的代码和要访问的数据调入内存
- 淘汰策略:内存空间不够时,迁出/淘汰哪些代码或数据以腾出内存空间
# 存储保护
保证内存的多道程序只在给定的存储区内活动并互不干扰。
# 物理内存管理
# 分区内存管理
- 单一区存储管理(不分区存储管理):用户区不分区,完全被一个程序占用,例如DOS
- 分区存储管理
- 固定分区:内存固定划分为大小不等的区域,有个分区表进行维护
- 动态分区:程序装入的时候创建分区,使得分区的大小刚好与程序的大小相等,有一些很小的空间无法利用,成为内存碎片
这是一个固定分区的例子:
上图代表内存空间,下图是内存分区表
区号 | 大小 | 起址 | 标志 |
---|---|---|---|
1 | 16K | 20K | 已分配 |
2 | 32K | 36K | 已分配 |
3 | 64K | 68K | 已分配 |
4 | 124K | 132K | 未分配 |
# 分区放置策略
首先有一个空闲区表的数据结构,来记录内存的大小和位置,以下是一个空闲区表的结构。
位置 | 大小 |
---|---|
30K | 20K |
66K | 24K |
118K | 12K |
分配过程(请求一个s大小的空间):
- 从空闲区表的第1个区开始,寻找大于等于s的空闲区。
- 找到后从分区中分割出s供用户使用。
- 将剩余部分依然作为空闲区登记在空闲区表内。
由于需要遍历空闲区表,因此需要对空闲区表进行合理的排序,称为放置策略,可以按照首地址大小排序、空闲区大小排序等待
当内存使用完后需要进行分区回收,分区回收有回收算法,要考虑释放区与现有空闲区是否相邻,如果释放区与现有空闲区不相邻,则直接插入空闲区表,如果相邻,则进行合并
# 内存覆盖技术(Overlay)
在较小的内存空间中,运行较大的程序。
- 内存分区:
- 常驻区:被某段程序单独且固定地占用,可划分多个
- 覆盖区:能被多段程序共用(覆盖),可划分多个
覆盖的缺点就是程序员需要划分程序模块并且确定覆盖关系。
# 内存交换技术(Swapping)
内存不够时,把进程写到磁盘上;当进程要运行的时候,重新写回内存。
换出与换入的地址重定位示意:
# 内存碎片
动态分区容易产生内存碎片:内存反复分配和分割
最佳适应法最容易产生碎片(按内存大小分片)。
# 解决办法
- 规定门限:分割空闲区时,如果某一部分小于门限,则空闲区不进行分割,而是全部分配给用户。
- 内存拼接技术:将所有的空闲区集中在一起构成一个大的空闲区
- 解除程序占用连续内存才能运行的限制