Lec 05 内存地址翻译
Lec 05 内存地址翻译
(参考来源:上海交通大学并行与分布式系统研究所+操作系统课程ppt)
Creative Commons Attribution 4.0 License
Contents
1. 内存管理

1.1 物理内存
- 常说的“内存条”就是指物理内存
- 数据从磁盘中加载到物理内存后,才能被CPU访问
-- 操作系统的代码和数据
-- 应用程序的代码和数据
1.2 早期系统
- 硬件
-- 物理内存容量小 - 软件
-- 单个应用程序 + (简单)操作系统
-- 直接面对物理内存编程
-- 各自使用物理内存的一部分

1.3 多重编程时代
-
多用户多程序
-- “发生在共享单车前的共享计算机” -
分时复用CPU资源
-- 保存恢复寄存器速度很快 -
如何共享物理内存资源?
1.分时复用物理内存资源
-- 将全部内存写入磁盘开销太高
2.同时使用、各占一部分物理内存
-- 缺乏安全性/隔离性
-- 如何不被物理内存容量限制?

在编译语言中,编译器会对每一行指令,生成一个地址编码

1.4 虚拟地址空间易于程序开发
- 编译器面临的问题
-- 如果某个地址的物理内存被别人占用了怎么办?- 例如:0x400000
-- 如果物理内存大小不够怎么办?
- 例如:0x400000
- 解决:编译器假设应用运行时,会独占所有内存,且内存足够大
-- 内存大小:\(2^{32}\) Byte,或\(2^{64}\) Byte,称为“虚拟内存空间”
-- 编译器基于该假设进行内存布局,并生成指令 - 谁来实现这个假设?CPU+操作系统
-- 思路:地址映射(虚拟地址翻译到物理地址)
-- 由CPU将虚拟地址翻译到物理地址,由操作系统来配置如何翻译
1.5 物理地址(physical address, pa)
- 物理内存可以看成由连续字节组成的数组
-- 每个字节都有唯一的物理地址

1.6 虚拟地址(virtual address, va)
- Memory Management Unit (MMU)
-- 按照规则将虚拟地址翻译成物理地址

1.7 主流翻译规则:分页机制
- 分页机制
-- 虚拟地址空间划分成连续的、等长的虚拟页
-- 物理内存也被划分成连续的、等长的物理页
-- 虚拟页和物理页的页长相等
-- 虚拟地址分为:虚拟页号 + 页内偏移 - 使用页表记录虚拟页号到物理页号的映射
-- 页表:Page Table
1.8 页表:分页机制的核心数据结构

1.9 分页机制的特点
-
物理内存离散分配
-- 任意虚拟页可以映射到任意物理页
-- 大大降低对物理内存连续性的要求 -
主存资源易于管理,利用率更高
-- 按照固定页大小分配物理内存
-- 能大大降低外部碎片和内部碎片 -
被现代处理器和操作系统广泛采用
1.10 基于分页的地址翻译

页内偏移不会因为翻译而改变,只会由页面大小决定。

1.11 通过页表进行地址翻译

页表:
- 存储在屋里内存中。由OS进行维护。
- 起始地址存放在页表基地址寄存器中。
1.12 内存地址翻译示例
- 假定一种地址格式
-- 14 位虚拟地址
-- 12 位物理地址
-- 页大小 = 64 字节 (6位)
- 确定我们的虚拟地址(虚拟页号+虚拟页内偏移)以及物理地址(物理页号+物理页内偏移)



我们有虚拟地址0x03D4.
虚拟地址
00 0011 1101 0100
页大小64字节,6位,因此虚拟页号为0000 1111
查看我们的页表,有物理页号是0D.
因此我们的物理地址为
0011 0101 0100
也就是0x354。
2. 多级页表
2.1 单级页表存在的问题
对于有14位的虚拟地址,12位的物理地址,页表本身将会有:
- 假设32位的地址空间,页大小为4K,页表项则为4字节。
- 假设64位的地址空间,页大小为4K,页表项则为8字节。
- 对于32位的地址空间
-- \(2^{32}/4K * 4=4MB\)
-- \(2^{64}/4K * 8=33,554,432GB\) !
单级页表会导致占有的空间过大!
2.2 多级页表
- 多级页表能够有效压缩页表的大小。
- 原因:允许页表出现空洞
-- 若某个页表页中的某个页表项为空,那么其对应的下一级页表页就无需存在。
-- 应用程序的虚拟地址空间大部分都未分配
2.3 AArch64 体系结构下4级页表



页表占用16K,虚拟地址范围?
- 我们有:
- 一个页表项8Byte,64位
- 一张页表页有\(2^9\)个页表项,\(2^{12}Byte=4KB\)
- 根据四级页表结构,我们就有:一张0级页表(一个页表项),一张一级页表(一个页表项),一张二级页表(一个页表项),一张三级页表(可以全满),也就是\(2^{9}个\)页表项。
- 那么,每个三级页表项可以寻找到\(2^{12}\)个地址。因为是按字节寻址,因此一个地址为1个Byte,也就是\(2^{12}Byte\).
- 那么这样,我们总共有寻址空间:\(2^9\cdot 2^{12}=2^{21}Byte=2MB\).
因此虚拟地址范围为2MB。
2.4 多级页表节省内存
假设进程只用到0,1,\(2^{36}-1\)三个虚拟页
- 单级页表,需要\(2^{36}\)个页表项,占用\(2^{39}Byte\).
- 四级页表,需要一个0级页表(2个页表项),两个一级页表(每个一个页表项),两个二级页表(每个一个页表项),两个三级页表(三个页表项2+1)。因此总共为2+2+2+1=7,也就是28KB。
? 1.多级页表一定比单级页表占用的少?
不一定。如果应用占用了大量的虚拟空间(例如占用了\(0~2^9-1\)的所有空间,此时单级页表将要比多级页表少占用空间。多级页表的优势在于当应用程序占用跨度大但是不多的虚拟空间时,可以节省存储空间。
? 2.虚拟地址0xFFF8080604FFF对应的各级页表的索引?
分为虚拟页号+页内偏移。
我们有
1111_111111111_000000010_000000011_000000100_111111111111
因此0级页表索引第511项,1级页表索引第2项,2级页表索引第3项,3级页表得到真实物理页号为4,页内偏移为511.
? 3. 若在页表中填写\(0\thicksim16M\)的映射,页表需要占用?
- 我们有:\(16MB=2^{4}\cdot 2^{20}B\)个映射。
- 这样我们有:\(24=12+9+3\)这样我们需要8张三级页表(满表),1张二级页表(8项),1张一级页表(1项),1张0级页表(1项)
- 这样空间占用则为: 44KB。
2.5 页表基地址寄存器
- AARCH64
-- 两个页表基地址寄存器:TTBR0_EL1 & TTBR1_EL1- MMU根据虚拟地址第63位选择使用哪一个
-- 以Linux为例 - 应用程序(地址首位为0):使用TTBR0_EL1
- 操作系统(地址首位为1):使用TTBR1_EL1
- MMU根据虚拟地址第63位选择使用哪一个
- X86_64
-- 一个寄存器:CR3(Control Register 3)
2.6 页表使能
- 机器上电会先进入物理寻址模式
-- 系统软件配置控制寄存器使能页表进入虚拟寻址模式 - aarch64
-- SCTLR_EL1,System Control Register, EL1.
-- 第0位(M位)置1,即在EL0和EL1权限级使能页表 - X86_64
-- CR4,第31位(PG位)置1,即使能页表!
操作系统运行过程中使用虚拟地址。实际执行时通过页表等翻译成物理地址。

3 页表项
- 每级页表有若干离散的页表页
-- 每个页表页占用一个物理页 - 第 0 级(顶层)页表有且仅有一个页表页
-- 页表基地址寄存器存储的就是该页的物理地址 - 每个页表页中有 512 个页表项
-- 每项为 8 个字节(64位),用于存储物理地址和权限

- V(Valid):当访问时V=0,则触发缺页异常
- UXN(Unprivileged eXecute Never):用户态不可执行(例如栈)
- PXN(Privileged eXecute Never):内核态不可执行(防止内核执行用户代码)
- AF(Access Flag):当访问时,MMU标记该位
- AP(Access Permissions)
- DBM (Dirty Bit): 51位,ARMv8.1-TTHM特性支持



- 有效的0-2级页表项
- 第1位为0表示PFN指向大页
- 第1位为1表示PFN指向下一级页表
4 TLB:加速地址翻译,缓存页表项
- Tradeoff是计算机中经典而永恒的话题
- 多级页表的设计是典型的用时间换空间的设计
-- 优点:压缩页表大小
-- 缺点:增加了访存次数(逐级查询)- 1次内存访问,变成了5次内存访问
如何降低地址翻译的开销?

- TLB 位于CPU内部,是页表的缓存
-- Translation Lookaside Buffer
-- 缓存了虚拟页号到物理页号的映射关系
-- 有限数目的TLB缓存项 - 在地址翻译过程中,MMU首先查询TLB
-- TLB命中,则不再查询页表 (fast path)
-- TLB未命中,再查询页表


4.1 地址翻译
- 虚拟地址(VA)构成
-- VPO(Virtual page offset),虚拟页偏移
-- VPN(Virtual page number),虚拟页号- TLBI(TLB index)
- TLBT(TLB tag)
- 物理地址(PA)构成
-- PPO(Physical page offset),物理页偏移
-- PPN(Physical page number),物理页号


4.2 TLB刷新
-
TLB 使用虚拟地址索引
-- 当OS切换进程页表时需要全部刷新 -
AARCH64上内核和应用程序使用不同的页表
-- 分别存在TTBR0_EL1和TTBR1_EL1
-- 使用的虚拟地址范围不同
-- 系统调用过程不用切换 -
刷新TLB的相关指令
-- 清空全部TLBI VMALLEL1IS
-- 清空指定ASID相关TLBI ASIDE1IS
-- 清空指定虚拟地址TLBI VAE1IS
4.3 TLB刷新导致的开销降低
- 硬件特性ASID(AARCH64): Address Space ID
-- OS为不同进程分配8位或16位 ASID- ASID的位数由TCR_EL1的第36位(AS位)决定
- OS负责将ASID填写在TTBR0_EL1的高8位或高16位
-- TLB的每一项也会缓存ASID - 地址翻译时,硬件会将TLB项的ASID与TTBR0_EL1的ASID对比
- 若不匹配,则TLB miss
- 使用了ASID之后
-- 切换页表(即切换进程)后,不再需要刷新TLB,提高性能
-- 修改页表映射后,仍需刷新TLB(为什么?)
需要对地址映射进行更新否则会导致页表错误
4.4 页表和多核
- OS修改页表后,需要刷新其它核的TLB吗?
-- 需要,因为一个进程可能在多个核上运行 - OS如何知道需要刷新哪些核的TLB?
-- 操作系统知道进程调度信息 - OS如何刷新其他核的TLB?
-- x86_64: 发送IPI中断某个核,通知它主动刷新
-- AARCH64: 可在local CPU上刷新其它核TLB
调用的ARM指令:TLBI ASIDE1IS
4.5 多级页表的优势
-
高效使用物理内存
-- 使用 DRAM 作为虚拟地址空间的缓存 -
简化内存管理
-- 每个进程看到的是统一的线性地址空间 -
更强的隔离与更细的权限控制
-- 一个进程不能访问属于其他进程的内存
-- 用户程序不能够访问特权更高的内核信息
-- 不同内存页的读、写、执行权限可以不同
每个进程拥有其独立的内存空间
- 不同进程互不干扰
-- 仿佛独占所有内存 - 绝大部分地址段均可用
-- 除了顶部的内核地址区域

灵活的虚拟内存-物理内存映射
- 每个虚拟页都可以被映射到任意物理页
- 一个虚拟页可以在不同的时刻存储在不同的物理页中


可在不同进程之间共享内存
- 不同虚拟地址空间的虚拟内存页可映射到相同的物理页

基于虚拟内存实现内存保护
- 不同的进程对相同的物理页拥有不同的权限
-- 通过页表项中的权限位来控制
总结


浙公网安备 33010602011771号