操作系统-cache高速缓存

问题

  • 在cache 中访问的内存地址为何会带有 cache 相关的信息 ,动机是什么?

前言

平时只知道cpu 到内存之间还有一层 cache , CPU 要去主存找一个数据 ,第一反应肯定是到先到 cache 中找 ,如果找不到再去主存中去找, 要是找到了,直接就返回了 . 上面的过程实际就是通过 主存地址 这个东西来判断数据是否存在cache 中 . 其实主存地址在不同的地方是长不一样的, 比如在 cache 里面为了去找一下 cache 有没有 ,那么是长这样的, 假如是去主存找 ,那么我首先得到页表找 , 那么主存地址又是长另外一个样子 , 也就是说通过 主存地址 我们可以达到不同的目的 , 这一点需要记住 !

cache 在哪

下图可以看到 cache 在寄存器和内存的中间 ,起到缓存的作用. 对内存进行缓存
1297993-20220410221408383-1437738747.png

1297993-20220410221732987-721157845.png

1297993-20220410221811991-1184201858.png

高速缓存如何工作

既然是对内存进行缓存, cache 的空间小, 内存的容量大, 可以看到缓存的单位是 Block (内存块) , 内存块内部其实还可以继续细分 . cache 与内存之间的映射方法有三种

1297993-20220410221854066-1563792640.png

第一种方式 : 直接映射

我们首先对内存块进行编号, 0号内存块( 0 块) , 1号内存块( 1 块 ), 2号内存块, 3号内存块 ...cache的记录空间称为条数(行或者槽) ,如下图 , 对 16 取余数, 1块 17块 33块 .., 2块 18块 34块... 分到另外一个槽 . 分配过程假如冲突了就会发生替代, 例如我们的槽中原本放着 1号内存块, 后来给 17号内存块替代了.

1297993-20220410222911455-165372003.png

那我们看到 Cache 中这个表格的 0 号槽到底有没有放数据啊 ,如果放了数据那么放的是内存的第几块内存呢?? 所以这一定有两个标识 :

  • 有无标识 v : 是否cache 里面放了数据没有的标识
  • tag : 标识槽位放的是第几个块群的数据 , 例如 cache的 1号槽位 , 放有数据 ,并且tag 是 1 那么我们就知道了 , 1号槽放的是内存第 17块内存

搞懂了上面的内存的块是如何放到 cache 里面去的了. 我们再来看一下 CPU 发过来的主存地址是如何先去找 cache , 然后看看是否命中的 , CPU 发过来的地址有 20位 ,这 20位包括了
主存标识 + Cache 槽号 + 块内地址 ,其中 :

  • 主存标识 : 就是哪一个块群

  • Cache 槽号 : Cache 哪一个槽号的

  • 块内地址 : 内存块中还再细分的

    例如我要找的地址是 0220CH , 变成二进制就是 0000 0010 0010 0000 1100B , 我首先到 0001(Cache 槽号) 槽位看一下是否存在数据, 假如是第一次 , cache 肯定是没数据的 , cache 没数据肯定需要将数据加载到内存中去 , 然后内存的数据再copy 到 cache 中去 , 那么是内存的第几块内存啊 ? 看一下前 7位 --- 0000 001第一块群 , 第一块群放在 cache 的 1号槽 ,那只能是17块内存啦 !

    经过了这么一顿操作 , 内存的 17块内存已经被放在内存和 cache 中去了 ,第二次 ,我同样访问 地址是 0220CH, 同样我先看Cache 槽号 , 里面已经有数据了 ! (v标识表示有数据 ), 再比对一下是哪个块群 , 是 cache 的 1号槽 的第一块群 ( tag 也比中了!! ), 于是我就不再前往内存中拿数据了 , 因为 cache 中有我想要的数据了

直接映射下的Cache 的标志位

这里的 tag 和 v 就是我们前面所说的标志位

1297993-20220410224100401-1399537025.png

第一个位表示是否存在cache 中, 有效无效 , tag 则是当前 cache 里的 data 取自哪个块群的 (因为有可能来自不同的块群)

直接映射的另外一个例子

对比的时候先拿内存地址中的Cache 槽号 找到对应的 Cache记录, 然后再对比该记录中的 tag 是不是自己的块群, 要是是的话那么继续比对是否有效有效标识, 要是这都能对上说明内存块存在 Cache 中呀!

1297993-20220410231939132-1864850891.png

直接映射的特点

我们前面也看到了每个块对应于 cache 哪个位置是固定的, 那假如有几个块主存电脑用的比较频繁, 但是都是同一个槽号的,比如 0号槽位的 0 ,16,32块内存 , 那岂不是得频繁的换进换出 ?? 是的 !!
img

第二种方式 : 全相联映射Cache

全相联映射的映射是这样的, 只要有空的位置就往里缓存 , 哈哈哈 , 反正有位置就放就完事了 ,没位置就根据一定的规则把某些放太久的换出来,可以想象得到这肯定也有问题 ,比如

  • CPU 给个主存地址 ,我也不知道在不在 cache 槽里, 那么我就只能一个个对面,直到对比中了
  • 使用频繁的块内存肯定老是在槽里 ,那么使用频率低的肯定都给挤出槽了

1297993-20220411163051233-744551371.png

这种方式就有意思了, CPU给过来的主存地址就只有两部分的组成了

  • 标记/主存块号
  • 块内地址

比如CPU 传过来 01E0CH , 转化为二进制就是 0000 0001 1110 0000 1100B , 前 11位表示的是15块主存 , 我就那个 15 去 cache 对比一下 tag , 看一下 tag 里面有没有 15 ,有的话并且数据标识表示存在数据 ,那么就是比中了 ,反之没比中 !

第三种方式 : 组相联映射

组相联映射结合直接映射全相联映射的特点 , 你看我们上面用全相联映射的缺点是他喵的, 所有的主存块乱放, 我他喵一个个对比 ,比到什么时候嘛 , 于是组相联映射 先将 cache 的容量进行分组 , 对应的内存块只能放到对应的组呢 ,然后一组又有很多个空间, 这时候内存块就可以随便放 , 找的时候也是先找到对应的是哪一个组的,再在对应的组内进行比对

1297993-20220411163807086-1843804557.png

1297993-20220411165106235-1629057350.png

这个方法的主存地址, 第一部分,标记放的是位于内存中哪个块群, Cache索引是位于Cache哪个cache组 , 块内地址 这个就不用解释了

缺失率和关联度

1297993-20220411170657791-1033362932.png

1297993-20220411170708293-2106172882.png

关联度有点像查找命中的过程中扫描的条数

其他

关于虚拟地址 (重要)

之前以为虚拟地址是一成不变的,其实这就是一个误区, 这篇文章 cache 算是CPU 访问数据的开端 , 认真想想, 对于内存来说, cache 是内存的缓存, 而对于磁盘来说 ,主存又是
磁盘的缓存, 我们学习这篇文章的时候 , 会发现内存地址放着关于 cache 目的就是访问的时候,先到 cache 去找 ,我们后面还会学到页表和 TLB , TLB 是页表的缓存, 所以可想而知访问页表的内存地址也会有关于TLB 相关的信息 . 最后放上一张关于访问内存的流转图 ! (重要)

1297993-20220411231735273-250349725.png

同样的道理我们到时候也会看到在不同阶段 ,内存地址会不一样.

参考

  • <袁春风-操作系统>
posted @ 2022-12-30 16:42  float123  阅读(361)  评论(0编辑  收藏  举报