最近在学习虚拟内存,每天学一点点整理一点点,内容可能有点多,可以收藏慢慢看。
1. 存储器
什么是存储器?存储器就是存放数据的容器,常见的有RAM、ROM等。有个问题,为什么它们叫随机访问存储器?是因为访问一个数据的时间与数据在存储器的位置无关。常见的cache就是用的SRAM,内存用的是DRAM,它们都是断电丢失的,断电不丢失的叫ROM,比如存放我们装机用的BIOS,又或者基于EEPROM的SSD硬盘。
这些存储器的区别是什么?为什么分这么多?我们都知道CPU处理指令的速度是非常快的,访问寄存器0个周期就可以完成,访问缓存需要几个到几十个时钟周期就能完成,但是访问内存的话就需要几百个时钟周期来完成,而访问磁盘的话就需要几千万个周期,这就造成了处理差异,即使你CPU运算再快,需要的数据没有送到也无济于事啊!所以就有了计算机存储器层次结构,如下图。
另外,现在多核CPU的话,每个核内有单独的L1 cache(L1 data cache和L1 instruction cache)、L2 cache以及所有核共享L3 cache。
2. DRAM寻址
假如有一个 16X8 的内存(16表示有16个存储单元,8表示每个存储单元可以存放8个bit),在我们人脑中,我们一般将内存看成是一个连续的数组,如图所示(假设CPU每次取一个字节),假设我们取13位置的字节。
![]() |
![]() |
3. cache缓存
我们以Core i7为例,介绍一下是如何缓存的(先不考虑虚拟地址),下图是L1缓存。
先了解一下下列英文单词释义:
PPN:Physical Page Number | 物理页号 |
---|---|
PPO: Physical Page Offset | 物理页偏移地址 |
CT: Cache Tag | 缓存标记 |
CI: Cache Index | 缓存组索引 |
CO: Cache Offset | 缓存块偏移 |
高速缓存是通过一个三元组(CT,CI,CO)来索引的,如图所示,我们先根据CI找到组索引,然后根据标记CT来找到所在的行,最后根据块内偏移CO找到对应字节,这种情况称为cache hit(缓存命中),否则为cache miss(缓存不命中)。注意,每行都有一个状态位state,只有状态位标志位有效该行才有意义。
缓存都是以块为单位工作的,数据在各级缓存之间都是来回复制块个字节。另外,组内的行数是硬件做好的,不是由地址信息决定的。在Core i7中,L1 cache是由8行组相联的。
顺便说一下,在我们64位的系统中,虚拟地址是由64位组成的,但在目前的实现中,这些地址的高16位全部为0,所以一个虚拟地址的有效位是48位,能够访问的内存空间是256TB。实际的物理地址会比虚拟地址大一点,也就是52位(CT+CI+CO=40+6+6),后面我们会讲它们是如何转换的。
之前是读,写的情况就复杂了。对于写命中,分为两种,一种是直写:立即将缓存块写回到低一层的缓存中;另一种是写回:只有替换算法要驱逐这个更新过的块时才写到低一层缓存中。直接总是会占用IO总线,写回会增加复杂性(比如,对于L3共享缓存,一个核还没有写更新,另一个核就要读取,导致了不一致的问题)。对于写不命中,也是分为两种,一种是写分配:加载低一层的的块到高速缓存上,然后更新;另一种是写不分配:直接写到低一层的缓存中(不命中的话继续往下一层搜索)。
举个栗子,以CASPP练习题6.13 ~ 6.15为例:
假设内存是字节寻址的,且访问的是1字节的字,地址长度设定为13位,下图是某个2路组相联高速缓存图
6-13,引用地址0x0E34处的字节
6.14,引用地址0x0DD5处的字节
6.15,引用地址0x1FE4处的字节
看到这里大家应该对缓存的工作原理不默笙了吧,继续往下看吧!