虚拟内存和TLB
页表
一说到虚拟内存,第一时间一定要想到页表,它是真正保存着虚拟地址到物理地址映射关系的东西,没有它,一切无从谈起,关于它有两个重要的概念
- 这东西是每个进程一个的,由操作系统维护
- 它保存在内存中
页表里面就是一条一条的页表项,大概像这个样子
+-------+--------+
| valid | number |
+-------+--------+
| valid | number |
+-------+--------+
. .
. .
. .
+-------+--------+
| valid | number |
+-------+--------+
- 有效位(valid):一个bit,指明该虚拟页是否被缓存在物理内存中
- 物理页号(number):虚拟页号对应的物理页号
为什么说大概这个样子呢,因为,可能不是只有一个有效位,还会有一些其他作用的位
翻译
有一个专门的硬件,来做将虚拟地址翻译为物理地址这件事,叫内存管理单元(Memory Management Unit,MMU),这玩意儿是跟cpu封装在一起的,每个核都有一个?翻译的时候,先将虚拟地址和物理地址做这样一个划分
n-1 p p-1 0
+-----+-----+
| VPN | VPO |
+-----+-----+
m-1 p p-1 0
+-----+-----+
| PPN | PPO |
+-----+-----+
- 虚拟地址有
n位,其中p位为虚拟页面偏移量(VPO),剩余(n-p)位为虚拟页号 - 物理地址有
m位,其中p位为物理页面偏移量(VPO),剩余(m-p)位为物理页号
翻译的过程如下
- 一个虚拟地址,先根据VPN找到页表中的某一页表项
- 如果这个页表项的有效位置1,那么就从里面取出物理页的页号
- 因为虚拟页和物理页的页大小是一样的,所以PPO等于VPO
- 至此,PPN和PPO都知道了,物理地址就翻译完成了
TLB
每翻译一个虚拟地址,MMU就要查阅一个页表项,如果页表项在L1,开销大概在1到2个周期,如果在内存,就需要大概几十到几百个周期,为此,在cpu里面又弄了一个缓存,称为翻译后备缓冲器(Translation Lookaside Buffer,TLB),是个SRAM?每个核都有?每一行的块里面保存了一个页表项,为了对TLB进行查找,需要对虚拟地址的VPN进行一些划分
n-1 p+t p+t-1 p p-1 0
+-------+--------+-----+
| TLBT | TLBI | VPO |
+-------+--------+-----+
| VPN |
+-------+--------+
- VPN的低
t位用于索引组 - VPN的剩余位用于
tag匹配
因为每一行就存一个页表项,因此不用偏移,也就不需要偏移位,TLB如果没有命中,就会从页表里面取出相应的页表项缓存到TLB?
多级页表
- 一个32位的系统,假设其虚拟地址和物理地址的位数都是32,页的大小为4KiB,那么VPO和PPO的位数就是12,VPN和PPN的位数就是20,如果就一个页表,那么就需要有\(2^{20}\)即1MiB个页表项用于VPN索引,每个页表项必须占32位?4字节?的空间,ok,一个进程就需要
1MiB x 4 = 4MiB大小物理内存存储页表,64位就需要更大了,显然需要优化一下,大概的思路类似这样- 先使用20位的VPN的前10位去索引页表,由此建立了一级页表,那么这个一级页表就是\(2^{10}\)即1KiB个页表项,每个页表项4字节,那就占4KiB物理内存空间,由一级页表页表项的物理页号翻译出来的物理地址指向的是一个二级页表
- 再使用20位的VPN的后10位去索引这个二级页表,那么一个二级页表也是\(2^{10}\)即1KiB的页表项,每个页表项4字节,那么一个二级页表也是占4KiB的物理内存空间,由二级页表的页表项的物理页号翻译出来的物理地址指向了虚拟地址对应的物理地址
- 即原来的一个VPN被划分为了多个,第
i个VPN对应第i级页表,这样的设计有效减少了页表的内存占用,一个页是4KiB大小,也就是说,一级页表的一个页表项就映射了虚拟地址1KiB x 4KiB = 4MiB大小的空间,如果一个进程工作集小于4MiB,那么,除了一级页表,就只需要再来一个二级页表就好了,现在页表占用的空间只有4KiB + 4KiB = 8KiB大小,相比原来减小了4MiB / 8KiB = 512倍,而一个进程对于4GiB的虚拟地址空间一般大部分都是不会用到的,所以,大部分的二级页表根本不会存在,这样的设计是非常有效的


浙公网安备 33010602011771号