内存管理¶
内存管理的概念¶
- 作用:提高主存的利用率,将尽可能多的作业同时加载到主存中
- 层次:
- 寄存器
- 主存
- 辅助存储器
- 需求:
- 重定位:进程装入内存中的地址变化 (不固定)
- 保护:防止进程越界访问
- 共享:对共享区域的受控访问
- 逻辑组织:逻辑地址的组织更符合程序的构造
- 物理组织:管理主存、辅存等分级存储方式
存储管理技术¶
- 单一连续区(不分区)
- 固定分区
- 大小一致
- 大小不一致
- 动态可变分区
- 不会产生内部碎片
- 单纯分页/分段
- 虚拟存储系统
- 分页
- 分段
- 段页式
地址重定位¶
- 固定定位
- 静态重定位
- 动态重定位
- 将逻辑地址变换成物理地址由硬件自动完成
- 优点:
- 运行期间可以换进换出内存:换出阻塞的进程
- 可以在内存中移动进程:搜集内存中的外部碎片
- 空间不必连续
- 便于信息共享
- 是内存虚拟管理的基础
动态可变分区分配算法¶
- 首次适配(First):空闲分区链表按地址排序,分配快,回收效率高,小碎片多
- 临近适配(Next):从上次分配的地址开始查找,减少搜索时间
- 最佳适配(Best):空闲分区链表按块从小到大排序,选择最小的足够大的空闲分区,小碎片多
- 最差适配(Worst):空闲分区链表按块从大到小排序,选择最大的空闲分区,多中等碎片
- 算法对比
- 复杂度:最佳(2+2)> 最差(1+2)>首次(1+1)>循环(1+1)
- 小碎片产生的可能性:最佳 >首次 > 循环 > 最差
- 后继大作业分配成功的可能性:最佳 >首次 > 循环 > 最差
内存扩充技术¶
- 主辅存交换
- 覆盖技术:
- 用于一个作业的内部
- 同一程序按程序的逻辑结构分段,不会同时运行的程序段分在一组内,该组称为覆盖段
- 极端情况下覆盖段在主存中只保留一个段,其他段在辅存中
- 应用程序不透明,需要程序员干预
- 交换技术(虚拟存储技术):
- 用于不同的作业,任一时刻主存中只保留一个完整的用户作业
- 对应用程序而言是透明的,无需程序员干预
- 覆盖技术:
虚拟存储技术¶
- 简单分页——页表(page table)
- 逻辑地址到物理地址的转换:
- 逻辑地址 = 页号 + 页内偏移
- 物理地址 = 帧号 + 页内偏移
- 逻辑地址到物理地址的转换:
- 系统抖动:频繁换入换出页面
- 虚拟存储器的大小限制:
- 存放程序指令和数据的外存区域称为交换区。
- 虚拟存储器大小 = 交换区大小 + 内存大小
- 虚拟地址空间大小:
- 计算机地址结构的限制(例如,指令地址字长度等)
- 地址映射
- 将进程中程序的虚拟(逻辑)地址转化为物理地址
- 维护地址映射表
- 物理内存的管理
- 物理内存的回收、分配
- 缺页异常的处理
- 分配内存
- 将需要的内容从磁盘 swap 区加载到内存
- 页大小
- 页越大,内零头越大;
- 页越小,需要的页越多,页表就越大
逻辑地址到物理地址的转换¶
-
页表(page table)
- 逻辑地址 = 页号 + 页内偏移
- 物理地址 = 帧号 + 页内偏移

-
快表(TLB:Translation Lookaside Buffer)
- 页表在 Cache 或寄存器中的副本
- 用于加速地址转换

-
多级页表
- 把整个页表进行分页,分成一张张小页表,每个小页表的大小与页框相同。
- 对小页表顺序编号,允许小页表分散存放在不连续的页框中。
- 为了进行索引查找,应该为这些小页表建一张页目录表(一级页表),其表项指出小页表(二级页表)所在页框号及相关信息。
- 逻辑地址结构有三部分组成:页目录号、页号和位移。

-
反向页表(Inverted Page Table)
- 虚拟地址的页号使用散列函数映射到哈希表中。
- 把 \(n\) 位页号映射到 \(m\) 位帧号(\(n > m\))
- 大小与物理内存成正比

空闲内存页的管理¶
- 位图方式:
- 每个 Bit 表示一块的使用状态。0 表示空闲,1 表示已分配。
- 表示能力:32MB 主存,页大小为 4K,1KB 的空间就足够表示。
- 效率高:只要修改对应 bit 就可以
- 空闲链表方式:
- 用链结构表示空闲页。
物理页框回收¶
- 全局淘汰策略:从所有作业所占用的帧中选择。
- 局部淘汰策略:从本作业所占用的帧中选择
淘汰算法¶
- 最优淘汰算法(OPT-Optimal)
- 淘汰将来最长时间不使用的页面。
- 需要预知未来的页面访问情况,实际不可行。
- 作为理论上的评价标准,用以鉴别其他淘汰算法的优劣
- 先进先出淘汰算法(FIFO)
- 淘汰最先进入内存的页面。
- 实现简单。
- 可能导致系统抖动(频繁换入换出页面)。
- 最近最少未使用算法(LFU-Least Frequently Used)
- 淘汰在一定时间内未被访问的页面。
- 为每页面设置访问计数器,通过比较所有页的计数器值来确定淘汰的页面。
- 需要定期对计数器清零,以淘汰过期页
- 过于复杂
- 最久不使用淘汰算法(NUR-Not Used Recently),即 Clock 算法
- 结合了 FIFO 和 LFU 的思想。
- 1 个访问位
- 每个页面有一个访问位,表示最近是否被访问过。
- 使用一个指针指向当前检查的页面,按顺序检查页面。
- 如果访问位为 1,则清零并继续检查下一个页面;如果为 0,则淘汰该页面。
- 1 个访问位 + 1 个修改位
- 每个页面有一个访问位和一个修改位。
- 访问位表示最近是否被访问过,修改位表示页面是否被修改过。
- 使用一个指针指向当前检查的页面,按顺序检查页面。
- 如果访问位为 1,则清零并继续检查下一个页面;如果为 0,则淘汰该页面。
- 适用于大多数实际情况,性能较好。
段页式虚拟存储管理¶
- 虚拟分段的优点:
- 简化不断增长的数据结构处理方式
- 允许分块编译
- 有助于进程间的共享
- 有助于实现保护机制
-
段页式地址翻译
- 段号 \(s\) + 页号 \(p\) + 页内偏移 \(d\)
- 为了进行地址变换,系统为每一个作业建立一张段表,再为每一段建立一张页表。同样,也有一个段表控制寄存器,存放当前作业段表的长度和始址。

-
读取策略
- 请求式分页
- 预约式分页
- 放置策略
- 最佳适配
- 首次适配
- 近邻适配
- 最差适配
- 替换策略
- 算法
- Opt
- FIFO
- LRU
- Clock(NRU)
- 页缓冲
- 算法
- 清除策略(回写)
- 请求式清除
- 预约式清除
物理主存储器的分配和管理¶
-
伙伴系统(Buddy system)
- 将内存分成大小为 \(2^n\) 的块。
- 分配时,寻找最小的满足要求的块。
- 回收时,将相邻的块合并成更大的块。
- 优点:减少碎片,提高内存利用率。
Void get_hole( int i) { If ( i == ( u+1) ) failure; If ( <i_list empty> ) { get_hole( i+1); <split hole into buddies>; <put buddies on i_list>; } <take first hole on i_list>; }
-
Slab 系统
- 将内存分成多个大小相同的块(slab)。
- 每个 slab 包含多个对象,每个对象大小相同。
- 对象分配和回收时,直接在 slab 中进行,不需要频繁的内存分配和释放。
- 优点:减少碎片,提高内存利用率。

-
SLUB:在 SLAB 的基础上简化设计,提高性能。更适合多处理器系统使用。是目前 Linux 版本的默认配置。
- SLOB:为嵌入式系统提供极简的内存分配方案。