一、非连续内存分配概述
连续内存分配的缺点:
- 分配给一个程序的物理内存是连续的
- 内存利用率低
- 有内、外碎片问题
非连续分配的优点:
- 可以更好的内存利用和管理
- 允许共享代码与数据
- 支持动态加载和动态链接
非连续分配的缺点:
- 如何建立虚拟地址和物理地址之间的转换(硬件方案:分段/分页)
分段需要考虑的问题:
- 分段后,地址空间如何寻址
- 如何实现分段寻址方案
二、分段
优点:更好的分离和共享
应用程序运行时,使用的是连续的逻辑地址,通过分段后,可以映射为分散的地址空间,并分离起来,有利于共享与隔离
分段映射机制:
段:内存块
段寻址方式:将一维的地址映射为二元组,分别代表段号与段内偏移
硬件实现方案:
- cpu寻址时,将逻辑地址转换为两部分,前半部分为段号,后半部分为段内偏移
- 硬件中存在段表,将逻辑地址的段号映射到物理地址的段号;每个段大小不一样,段表需要存储段的长度。因此,段表需要存储段的起始地址与段的长度,段表的索引项为逻辑段号
- 通过逻辑段号便可找到段起始物理地址,通过段偏移与段大小的比对,可以知晓内存访问是否有问题,若访问合法,则将段物理起始地址+段偏移,得到物理地址
三、分页
1. 概述
与分段的区别:分页划分的是固定大小的帧
分页的特点:
- 划分物理地址空间为固定大小的帧 (Frame, 大小是2的幂, 512/4096/8192)
- 划分逻辑地址空间为与物理页相同大小的页(Page)
建立逻辑页与物理页的映射关系:
- 页表
- MMU/TLB
2. 页帧
定义:物理内存被分割成的大小相同的帧
组成:页帧号,页内偏移
若一个物理地址有N位,页帧号F位,偏移S位,则有页帧个数为 2的F次方,页大小为 2的S次方
假设一个内存物理地址为(f,o),物理地址计算方法:2^S * f + o (2的S次方为页大小)
3. 页
4. 地址转换
转换流程:
- 使用逻辑页号与页表基地址查找页表(由操作系统建立),获取物理页号
- 综合页偏移计算出物理地址
注意:
- 页映射到帧
- 页是连续的虚拟内存
- 帧是非连续的物理内存
- 不是所有的页都有对应的帧
5. 页表
a. 页表概述
页表结构:每个运行的程序都有一个页表,属于程序运行状态,会动态变化
PTBR:页表基址寄存器
页表项内容:
标志位:
dirty:是否脏数据
resident:页对应的物理页是否存在
clock/reference:页是否读过/写过
帧号f
b. 地址转换例子
问题:
- 访问一次内存单元需要2次内存访问(一次用于获取页表项,一次用于访问数据)
- 页表可能很大,64位机器如果每页1024字节,那么页表大小为 2的54次方项
c. 转换后备缓存区(TLB)
目标:解决访问内存单元,需要访问两次内存的问题
TLB定义:缓冲最近访问的页表,查询速度快,支持并发查找,但容量有限。TLB的key为逻辑页号,val为物理页帧。TLB miss时,会去内存查页表,并将查到的表项缓冲到TLB表中
d. 二级/多级 页表
目标:解决页表过大问题
流程:
- 使用p1作为索引,查找一级页表,此时,一级页表存的是二级页表的起始地址
- 根据1获得二级页表起始地址之后,便可获得二级页表,根据p2作为二级页表索引,获得二级页表项。此时,二级页表项存的是页帧
- 根据页帧与偏移量,获取真实的物理地址
问题:
访问一次内存单元需要访问3次内存,一次查找一级页表,第二次查找二级页表,第三次获取内存单元(可以通过TLB缓解)
优点:
使得某一些不存在映射关系的页表项,没必要占用内存。若页表项被打满,相对于一级页表,不存在优化效果
e. 反向页表
目标:使得页表大小与逻辑地址长度解耦
方案:
基于页寄存器方案:
特点:以页帧号为索引
优点:占用存储小
问题:如何将逻辑地址映射为物理地址
基于关联内存方法:
基于哈希查找的方案:
实现方案:
- 根据逻辑地址页号计算hash值,获取页表index
- 根据页表index获取对应页表项,判断pid号与页表项中的pid号是否相符,不符则通过静态链表查找到符合的物理地址