- https://zhuanlan.zhihu.com/p/107096130
- 假设Cache大小8KB,CacheLine大小256B,32行CacheLine,CPU是32位的。4KB的页。
- 32位虚拟地址 = 20位虚拟页号+12位页内偏移
- VIVT
- 虚拟地址作为索引以及tag域
- 32位 = Vaddr: tag(19位) + index(5位) + offset(8位)
- 歧义问题
- 两个进程相同的虚拟地址,映射到了不同的物理地址,但是由于使用的虚拟地址作为索引以及tag域,所以映射到了相同的CacheLine
- 比如P1虚拟地址为v1: 00000100000000000000 00001 00000001以及P2的虚拟地址v2: 00000100000000000000 00001 00000001
- P1(进程1)的虚拟地址V1与进程2的虚拟地址相同,所以索引的是相同的CacheLine,但是由于相同的虚拟页号在不同的进程中映射到不同的物理页号。导致了相同的虚拟地址映射到了不同的物理地址。
- 注意tag域是19位,而虚拟页号是20位。物理页号加上低12位为物理地址。
P1: |
VN(20位) |
PN |
P2: |
VN(20位) |
PN |
|
0x4000 |
0x2000 |
|
0x4000 |
0x3000 |
- 别名问题
- 两个进程不同的虚拟地址,映射到了相同的物理地址,这一个物理地址映射到了不同的CacheLine。
- 比如P1虚拟地址为v1: 00000100000000000000 00001 00000001以及P2的虚拟地址v2: 00000100000000000000 10001 00000001
- P1(进程1)的虚拟地址V1与进程2的虚拟地址中的offset相同,index只有最高位不同(保证两个虚拟地址的低12位,页内偏移相同),由于index不同,所以索引的是不同的CacheLine,但是由于不同的虚拟页号在不同的进程中可以映射到相同的物理页号。导致了不同的虚拟地址映射到了相同的物理地址。
P1: |
VN(20位) |
PN |
P2: |
VN(20位) |
PN |
|
0x4000 |
0x2000 |
|
0x4001 |
0x2000 |
- VIPT
- 用虚拟作为索引,用物理地址作为tag域。
- 32位 = Vaddr: 19位 + index(5位) + offset(8位)。继续使用虚拟地址的index作为CacheLine的索引,但是使用20位的虚拟页号转换成物理页号,然后用物理页号号作为tag域。
- 能够避免歧义。
- 比如P1虚拟地址为v1: 00000100000000000000 00001 00000001以及P2的虚拟地址v2: 00000100000000000000 00001 00000001
- 相同的物理地址,由于依然采用的是虚拟地址的索引,所以对应着相同的CacheLine,如果两个进程相同的虚拟页号对应着不同的物理页号,那么tag域就不相同,避免了VIVT中相同的虚拟地址对应着不同的物理地址。
- 依然存在别名的问题。
- 比如P1虚拟地址为v1: 00000100000000000000 00001 00000001以及P2的虚拟地址v2: 00000100000000000000 10001 00000001
P1: |
VN(20位) |
PN |
P2: |
VN(20位) |
PN |
|
0x4000 |
0x2000 |
|
0x4001 |
0x2000 |
- 和VIVT一样。
- PIPT
- 物理地址作为索引,物理地址作为tag,既不存在别名问题,也不存在歧义问题。但是每次都需要将虚拟地址转换成物理地址之后在进行查找Cache。为了加快MMU翻译虚拟地址的速度,硬件上也会加入一块cache,作用是缓存虚拟地址和物理地址的映射关系,这块cache称之为TLB。
- PIVT
- PIVT没有任何优点,却包含以上的所有缺点。你想想,PIVT方式首先要通过MMU转换成物理地址,然后才能根据物理地址index域查找cache。这在速度上没有任何优势,而且还存在歧义和别名问题。