超标量处理器设计笔记(5)虚拟存储器、地址转换、page fault
虚拟存储器
- 概述
- 地址转换
- 单级页表
- 多级页表
- 案例
- 最好情况:虚拟地址是连续的
- 最差情况:每个第二级 PT 都装有一项
- 增加级数
- Page Fault
- 程序保护
概述
当程序比物理内存空间更大时,无法全部装在物理内存中,需要对程序进行切片
虚拟存储器优点(需要操作系统调度)
- 将当前使用的部分程序放到物理存储器中,其余部分放在下一级存储器里。不需要切割程序
- 如果同时运行多个程序,不需要限制每个程序在规定的地址空间
- 保护各程序的内容不会互相改写
- 将相同功能的程序可以映射到相同位置
虚拟内存的地址范围
- 32 微处理器 0 ~ 0xFFFF FFFF 4GB
- 64 微处理器 0 ~ 0xFFFF FFFF FFFF FFFF
物理存储器的地址范围
- 32 微处理器 0 ~ 0xFFF FFFF 256MB (通常是 256MB,最大 4GB 和虚拟存储器内存大小一致)
- 64 微处理器 0 ~ 0xFFFF FFFF FFFF FFFF
现在 64 位计算机,既可以用 8GB 、16GB、32GB 内存。
没有使用虚拟存储器的系统:
使用虚拟存储器的系统:
地址转换
虚拟地址空间的划分以 页
为单位,典型大小为 4KB
物理地址的划分以 frame
为单位,典型大小同样为 4KB,
程序开始执行时,每次从硬盘搬运到内存时,搬运单位为页
VA[11:0] 表示页内的位置,page offset
VPN (visual page number):VA 剩余部分用来表示哪个页
PA[11:0] 表示 frame 内的位置,frame offset
PFN (physical frame number):PA 剩余部分用来来表示哪个 Frame
当 页
大小和 frame
大小一样时,page offset 和 frame offset 不需要变化
页面大的优缺点
- 降低页面替换的频率
- 用不到这么大页时,会造成一个页内的很多空间被浪费了
- 替换的速度和成本更高
案例:
16 位处理器,其 Visual Memory Space
为 64K (2^16 = 2^4 * 2^12 = 16 * 4k),16 个页
Physical Memory Space
为 32K (2^3 * 2^12 = 8 * 4K),8 个 Frame
现在有一个程序,大于 32KB,所以其中的 32KB 部分映射到 Physical Memory Space
,剩余部分映射到 Disk
中
例子 1:
Load R2, 5[R1] // 假设R1 = 0
得到的虚拟地址为 R1 + 5= 5,所以在 Visual Memory Space
中是 0~4K,Physical Memory Space
中 12~16K,具体是 12k + 5。
例子 2:
Load R2, 0[R1] // 假设R1 = 32780 32~36K之间
得到的虚拟地址为 R1 = 32780,所以在 Visual Memory Space
中是 32~36K ,Physical Memory Space
中没有,故 MMU 会产生 Page Fault,从 disk 中取出一个 Frame 替代原 Physical Memory Space
最少被使用的。这样就可以取到数据
单级页表
PT (Page Table) 页表:VPN 到 PFN 的转换表
页表存放在物理内存中
- 虚拟地址来寻址,页表寻址的内容是虚拟地址对应的物理地址
- 页表寄存器 (Page table register PTR):指示页表在物理存储器的位置
- 每次操作系统将程序调入到物理存储器时,更新 PRT
通过 VA[31:12] 索引到 Page Table Register 中的对应的项,由此获得 PFN
Page Offset 由于页面大小和 frame 大小一致,所以直接平移
Valid 表示 VPN 对应的内容在物理存储器中
Page Table 只需要 18+1 (valid) = 19 位,但由于物理存储器的数据位宽为 32bits,所以表项也是 32bits,多余的位可以用来表示其他信息,比如说页面的属性信息(可读、可写等)
这样页面大小为 32 bits * 2^20 = 4B * 1M = 4MB,放在物理内存里
程序状态包含:该程序页表、PC、通用寄存器。
该程序通常成为进程,可以保存好信息(页表只需要保存页表对应的 PTR 保存即可,mapping 信息可以用 store 指令完成)后暂停,过段时间再恢复,继续执行。不同进程使用的物理内存不会产生冲突了。
打开一个程序,操作系统会分配物理内存的空间、创建页表和堆栈,。当进程不存在时,物理内存的空间便会得到释放。
[!Note] 程序、进程、线程的关系
进程是操作系统进行资源分配的最小单元,
线程是操作系统进行运算调度的最小单元。
执行一次程序则会产生一个进程,多次多个,一个进程可以包含多个线程。
进程之间不会互相影响,线程之间公用地址空间,会互相干扰和影响。
由于页表空间需要 4MB 的连续地址来存储,一个处理器同时运行上百个进程时,则需要上百个 4MB 的连续地址来存储,非常占用空间。
所以采用多级页表的方式,来减少页表对物理存储空间的占用
多级页表
二级页表需要的空间:
32 位处理器下
- 单级页表:虚拟地址空间为 2^20 * 4B = 4MB
- 二级页表 (如果分成 2^10 等份,则需要 2^10+1 (第二级 pt 个数+第一级 pt) 个连续地址空间,每个空间大小为:2^10 * 4B = 4KB)
- 第一级表项,有 1 项,每项有 2^10 项第二级表项
- 第二级表项,有 2^10 项,每项有 2^10 项
实际上,第一级 PT 不一定填满,第二级 PT 只需要填充足够即可。
有需要时增加第二级 PT,一次增加 2^10 * 4KB = 4MB 的页面
[!Note]
PT 最少也需要 4KB 的连续地址空间,即便只用了其中一项
案例
32 位处理器下,页面大小为 4KB 下,4MB 程序的页表需要占用多大的空间呢?
最好情况:虚拟地址是连续的
一个二级 PT 能存储:2^10 * 4KB = 4MB 的程序
总共需要 1 项一级 PT,1 项二级 PT
页表占用总空间:2 * 4B * 2 ^10 = 8 KB (2 个 PT,每个 PT 占用 4B * 2^10 的空间)
最差情况:每个第二级 PT 都装有一项
一共 2^10 项二级列表,刚好 2^10 * 4KB = 4MB 的空间
页表占用总空间:2^10 * 4B * (2^10+1) = 4MB + 4 KB ( 2^10+1 个 PT,每个 PT 占用 4B * 2^10 = 4KB 的空间)
增加级数
当位数过多时,可以采用增加级数的方式
优点:级数越多,页表对物理空间的占用越少
缺点:需要逐级访问次数越多,时序越紧张
Page Fault
Page fault: 访问 PT 时,valid 位为 0,表示该页面在硬盘里,没有取到内存中
Page fault 通常由操作系统完成
- 发生 Page fault 时,访问硬盘时间很长,即便用软件处理需要几百条指令,但相比访问硬盘时间微乎其微
- 在替换物理内存的 frame 时,软件可以根据实际情况实现灵活替换算法
但是 valid=0 时,此时系统只知道 VA,怎么找对应的硬盘位置呢?
硬盘中会为一个进程的所有页开一个空间,也就是Swap 空间,同时会有一个表格来记录每个页在硬盘的存储位置。
为了处理 Page Fault,处理器在硬件上提供的支持
- 发生 page fault,产生异常,并且跳转到异常处理程序的入口地址
- 写物理地址之后,标记 dirty
- 访问物理地址时,标记 Use,该位会被操作系统周期性清零
程序保护
操作系统需要访问物理内存的所有空间,所以一般不使用页表
物理内存专门有一块给操作系统使用,不允许别的进程访问
比如:
32 位 MIPS 处理器,将 4GB 的虚拟存储空间分为 kseg0\1\2 和 kuseg 四个区域。
Kseg0 区域的属性是 unmapped,不经过页表转换
操作系统的内核指令和数据位于 kseg0 上,用户进程只能使用 kuseg
ARM 处理器会使用二级页表的方法,第二级页表的 PTE 都有一个 AP 部分
Privileged : 可以访问处理器所有资源,操作系统处于该模式下
User: 普通用户程序下
加入程序保护之后的地址转换。第二级页表控制 4KB 的页面权限,第一级控制 4MB 的页面权限