文章目录
1. 为什么需要非连续内存分配
1.1 连续内存分配的不足
- 分配给一个程序的物理内存是连续的
- 内存利用率低
- 有外碎片、内碎片的问题
1.2 非连续内存分配的优点
- 一个程序的物理地址空间是非连续的
- 更好的内存利用和管理
- 允许共享代码与数据(共享库等…)
- 支持动态加载和动态链接
1.3 非连续分配分配的缺点
如何建立虚拟地址和物理地址的转换:
- 软件方案(开销很大)
- 硬件方案(两种方案:分段、分页)
2. 分段:更好的分离和管理
2.1 程序分段地址空间
在分段技术支持下,应用程序如下图所示:
通过分段之后有效的隔离开来
段地址空间的逻辑视图:
2.2 分段寻址方案
- 新概念:一个段:一个内存“块”
一个逻辑地址空间 - 程序访问内存地址需要:一个2维的二元组(s, addr)
s:段号
addr:段内偏移
2.3 段访问的硬件实现
3. 分页
段机制用的比较少,主要还是分页机制
3.1 分页地址空间
- 划分物理内存至固定大小的帧(Frame):大小为 2 的兵幂,512 / 4096 / 8192
- 划分逻辑地址空间至相同大小的页(Page)大小为 2 的幂,512 / 4096 / 8192
- 建立方案 → 转换逻辑地址为物理地址(pages to frames):
① 页表
② MMU / TLB
3.1.1 帧(Frame)
-
物理内存被分割为大小相等的帧
-
一个内存物理地址是一个二元组(f, o) → (帧号, 帧内偏移):
帧号 : F位, 共有2^F个帧
帧内偏移 : S位, 每帧有2^S个字节 -
物理地址 = 2^S * f + o
分页和分段的最大区别 : 这里的 S 是一个固定的数, 而分段中的长度限制不定
例 : 16-bit地址空间, 9-bit(512 byte) 大小的页帧
- 物理地址 = (3,6)
- 物理地址 = 2^9 * 3 + 6 = 1542
物理地址 = 2S*f + o
F=7 S=9 f=3 o=6
实际物理地址 =2^9 *3+ 6=1536+6=1542
3.1.2 页(Page)
- 一个程序的逻辑地址空间被划分为大小相等的页.
- 页内偏移的大小 = 帧内偏移的大小
- 页号大小 <> 帧号大小
- 一个逻辑地址是一个二元组(p, o) → (页号, 页内偏移)
页号 : P位, 共有2^P个页
页内偏移 : S位, 每页有2^S个字节
虚拟地址 = 2^S * p + o
3.2 页寻址方案
操作系统维护一张页表, 页表保存了逻辑地址——物理地址之间的映射关系,存储 :页号, 帧号
- 逻辑地址空间应当大于物理内存空间
- 页映射到帧
- 页是连续的虚拟内存
- 帧是非连续的物理内存(有助于减少碎片的产生)
- 不是所有的页都有对应的帧
4. 页表
4.1 页表概述
页表转换实例,res位0表示物质地址不存在,1表示存在
分页机制性能问题
- 访问一个内存单元需要2次内存访问
① 一次用于获取页表项
② 一次用于访问数据 - 页表可能非常大
① 64位机器如果每页1024字节, 那么一个页表的大小会是多少?(2^64 / 2^10 = 2^54 存放不下)
② 每一个运行的程序都需要有一个页表 - 如何处理?
① 缓存(Caching)
② 间接(Indirection)访问
4.2 转换后备缓冲区(TLB)
快表(Translation Look-aside Buffer, TLB)
写出的程序尽量具有局部性,减少TLB访问miss
4.3 二级/多级 页表
- 分级机制之下,res为0的对应空间不需要保留
- 页表级数越多,访问次数越多,访问需要的时间越长,以时间换取空间
- 时间的开销再通过TLB进行缓解
4.4 反向页表
解决大地址空间问题
目的 : 根据帧号获得页号
反向页表只需要存在一张即可
- 有大地址空间(64-bits), 前向映射页表变得繁琐. 比如 : 使用了5级页表
- 不是让页表与逻辑地址空间的大小相对应, 而是当页表与物理地址空间的大小相对应. 逻辑地址空间增长速度快于物理地址空间
4.4.1 基于页寄存器(Page Registers)的方案
存储 (帧号, 页号) 使得表大小与物理内存大小相关, 而与逻辑内存关联减小.
每一个帧和一个寄存器关联, 寄存器内容包括 :
- resident bit : 此帧是否被占用
- occupier : 对应的页号 p
- protection bits : 保护位
实例 :
- 物理内存大小是 : 4096 * 4096 = 4K * 4KB = 16 MB
- 页面大小是 : 4096 bytes = 4 KB
- 页帧数 : 4096 = 4 K
- 页寄存器使用的空间(假设8 bytes / register) : 8 * 4096 = 32 Kbytes
- 页寄存器带来的额外开销 : 32K / 16M = 0.2%
- 虚拟内存大小 : 任意
优势 :
- 转换表的大小相对于物理内存来说很小
- 转换表的大小跟逻辑地址空间的大小无关
劣势 :
- 需要的信息对调了, 即根据帧号可以找到页号
- 如何转换回来? (如何根据页号找到帧号)
- 在需要在反向页表中搜索想要的页号
4.4.2 基于关联内存(associative memory)的方案
硬件设计复杂, 容量不大, 需要放置在CPU中
- 如果帧数较少, 页寄存器可以被放置在关联内存中
- 在关联内存中查找逻辑页号
成功 : 帧号被提取
失败 : 页错误异常 (page fault) - 限制因素:
大量的关联内存非常昂贵(难以在单个时钟周期内完成 ; 耗电)
4.4.3 基于哈希(hash)的方案
哈希函数 : h(PID, p) 从 PID 标号获得页号
在反向页表中通过哈希算法来搜索一个页对应的帧号
- 对页号做哈希计算, 为了在帧表中获取对应的帧号
- 页 i 被放置在表 f(i) 位置, 其中 f 是设定的哈希函数
- 为了查找页 i , 执行下列操作 :
① 计算哈希函数 f(i) 并且使用它作为页寄存器表的索引, 获取对应的页寄存器
② 检查寄存器标签是否包含 i, 如果包含, 则代表成功, 否则失败