当一系列数据在计算机中存储时是什么形式的?
软件仔:就是一个文件一个文件的
计算机仔:二进制码呗
电子仔:一系列存储器电容或者磁盘或者触发器的一种电位状态
显然这几种说法都是没问题的,只不过说的层面不同罢了。
富士康工厂原材料的收纳
首先想一下富士康工厂是怎么干活的,肯定是工厂有大仓库专门用来存储原材料,还有专门的生产车间,车间还有个小仓库(存了今天要用的东西),车间里面又有很多张桌子架子(存了工人现在所需的手头一点原材料),桌子前有很多工人在用手来生产。具体桌子上是流水线在流动生产这个就先不在这里谈了,我另一篇文章里面讲了流水线,有兴趣可以再看一看。工人手里在组装手机,组装完就从架子上拿半成品,架子空了就取小仓库拿材料,小仓库空了就去大仓库搬,为什么需要这么多大小不同的仓库层级,因为不可能让人们每组装一个手机就去跑20分钟的路程去大仓库拿。工人的手、架子、小仓库、大仓库这些地方需要哪越来越不方便,但是容量越来越大。所以很像计算机的存储。
工厂收纳层次 | 计算机存储层次 |
---|---|
工人的手 | 寄存器 |
桌子上的架子 | 缓存 |
车间小仓库 | 内存 |
工厂大仓库 | 磁盘 |
外地调货的供应商 | 远程存储 |
###·### 为什么是金字塔型的存储结构?
首先计算机中的存储是为了计算,一旦涉及到计算那就涉及到了CPU的执行,既然要与CPU进行交互,一定要求数据提供速度跟上,因为CPU的执行速度非常快。但是一般的存储器提供数据的速度都跟其差几个数量级,其合作效果像是木桶原理那样只能根据存储器的速度一样,严重地限制了CPU的发挥,也只有寄存器这种结构被设计到CPU内部而且其物理结构(触发器的组合)才能勉强跟上运算速度,所以让寄存器与CPU进行数据交互,但是这种结构又存储不了很多东西,于是就需要别的存储器给其提供数据,于是就形成了最靠近CPU的运算速度快,容量小,靠下的存储层级速度快,容量大。就想图中的金字塔型的存储结构。
上面知道了下层存储给寄存器提供数据,那么下层存储是不是也要分层。
磁盘与内存:
首先先看磁盘,磁盘作为数据的大仓库,给上层提供数据,机械硬盘,固态硬盘,这些都是。因为其寻址需要转动盘片,还要找到磁盘盘区号、柱面号,很费时间。于是每次开机就把要用的数据(操作系统)放到内存,就想每天早上把大仓库的里面今天可能要用的东西全部一起搬到车间小仓库里面(这里不是说一次搬完就不再搬了,缺东西的时候自然还是需要去大仓库的,比如说你打开一个应用)。
内存与缓存:
由于很多人在进行生产不可能忙完手头的一个就都去小仓库去,所以每次每个人都搬一堆放在自己的架子上够自己用上一会的,所以需要把现在经常要用的东西搬到自己桌子上的架子上,这就是缓存存在的加之,内存与缓存之间也是需要对应关系的,不可能把自己需要的东西放在别人的架子上,这就是涉及到内存与缓存之间的对应关系。有直接相连映射,全相联映射、组相连映射。 下面分别介绍一下缓存的结构和映射关系
这里我补充的可能有点多,不想看的可以直接跳过这部分看下一部分。
缓存是内存的镜像,其存储的内容是内存空间的子集。内存以一个寻址单元 数据为单位操作,而缓存以一个数据块为单位操作,一个数据块包含一个或多个 寻址单元数据。如图 2-2 所示,一个缓存就是由多个图中所示的缓存单元构成的, 图中的 data 域存储数据,每个缓存单元存储一个数据块。内存通过地址来区分数 据,而缓存无编址,因此为了使得不同缓存单元存储的数据块可以被区分,每个 缓存单元除了存储数据块的数据域,还附带一个用来区分数据块的标志域(2-2 图 中 tag 域),以及一个用来区分该缓存单元中所存的数据块是否有效的有效位(2-2 图中 valid 域)
由于内存要和缓存形成映射关系,故内存中的数据也要按照缓存中的数据块 的大小进行划分。例如,假设一个缓存单元能够存储 4 个字节的数据,内存按照 字节寻址,那么地址为 0、1、2、3 的数据将可能被划分到一个数块当中、地址为 4、5、6、7 的数据将可能被划分到另一个数据块中。 缓存的结构按照其和内存的映射关系,可以分为三类:直接相联、全相联、 组相联。直接相联指的是:内存中的某个数据块只能放到缓存中的某个缓存单元 中,如图 2-3 中子图 a 所示,内存中的数据块 2 只能放到缓存单元 2 中。全相联指 的是:内存中的某个数据块可以放到缓存中的任意缓存单元中,如图 2-3 中子图 b 所示,内存中的数据块 2 可以放到所有的缓存单元 1、2、3、4 中。组相联指的是:
内存中的某个数据块可以放到缓存中的某几个缓存单元中,如图2-3中子图c所示, 内存中的数据块 2 能放到缓存单元 1 和缓存单元 3 中。其中,组相联是常用的 一种缓存结构,直接相联和全相联都是组相联的特例。
处理器通过地址访问缓存。如图 2-4 所示,为了和缓存结构对应,访存地址通 常被切分成三部分:index、tag、offset。
以下分别介绍各部分的用途。
(1) index 用于在所有的缓存单元中寻找可能存储了要访问的数据的缓存单元, 全相联缓存无需 index。 假设缓存一共有 2048 个缓存单元,如果是直接相联缓存,则 index 为 11 位 (211=2048),此时根据 index 可定位到唯一的一个缓存单元;如果是二路组相联缓 存,则 index 为 10 位(210×2=2048),此时根据 index 可定位到两个缓存单元;全 相联不需要 index,每一个缓存单元都可能包含要访问的数据。
(2) tag 用来判断缓存是否命中,即判断由 index 定位的缓存单元是否的确存储 了要访问的数据。 tag 的位数 = 访存地址位数 - offset 位数 - index 位数。
(3) offset 用于缓存块内索引。 假设一个缓存块大小是 32 字节,按字节寻址,则 offset 的位数为 5(25=32)。
处理器访问缓存的过程如下:
(1) 使用 index 定位到可能包含要访问的数据的缓存单元:若是直接相联,根据 index 定位到唯一的一个缓存单元;若是组相联,根据 index 定位到多个缓存单 元;若是全相联,不需要定位缓存单元,每个缓存单元都可能包含要访问的数据。
(2) 使用 tag 判断 index 定位的缓存单元是否命中:若是直接相联,将访存地址的 tag 和 index 所定位的唯一一个缓存单元的 tag 比较,若相同,则命中;若是 组相联,将访问地址的 tag 和 index 所定位的多个缓存单元的 tag 比较,只要有一 个相同,则命中;若是全相联,将访问地址的 tag 和每个缓存单元的 tag 比较,只 要有一个相同,则命中。
(3) 使用 offset 在命中的缓存单元中取要访问的数据:若通过 tag 比较得知 某缓存单元命中,通过 offset 在 data 域取出要访问的数据。
缓存与寄存器
由于为了缓解速度差异,引入了缓存解决了内存与寄存器之间的速度差异,缓存也分了很多层次,其实他们的功能都是一样的,只不过工作不在一个层级,这里主要介绍缓存与寄存器之间的交流,由于缓存与内存使用的是同一套编址空间,所以寄存器每次需要load 或者 store的时候实际上是先访问了缓存,缓存miss之后再去试试下级缓存,直到全部缓存miss才去访问内存。但是注意缓存虽然是存储系统中的结构,但是被集成在了CPU中,内存在外部,所以访问缓存用的是内部总线,访问内存用的是系统总线。
数据整体的访问逻辑:
首先明确几个知识点:
- 缓存之于内存等价于快表之于页表
- 快表与页表存储的是虚拟地址和物理地址之间的转换(按页存储)
- 程序执行用的是虚拟地址(每个进程一个单独的编址空间存储在进程PCB中),但是访问内存或者访问缓存用的就是物理地址了。
地址转换、数据访存图:(用visio把我眼睛都快画瞎了)
<>中的数字代表数据位数,假设虚拟地址48位,物理地址36位。
处理器访问存储层次的 过程述如下:
- 处理器发出一个读写访存请求,将该请求的虚拟地址解析成虚拟页号、页 内偏移两部分。虚拟页号用来访问 TLB 以及内存中的页表。页内偏移用来访问渗 透缓存。
- 虚拟页号被解析成 TLB tag 比较地址和 TLB 索引两部分。通过 TLB 索引 定位到某一个或某几个(组相联)TLB 单元后,将 TLB tag 比较地址和定位到的 TLB 单元的 TLB tag 比较:若相同,则将该 TLB 单元中存储的 TLB 数据取出,该 TLB 数据即是此虚拟地址对应的缓存 tag 比较地址;否则,表明 TLB 缺失,使用 虚拟页号访问内存中的页表,从页表中找到该虚拟地址对应的缓存 tag 比较地址。
3.将(1)中的页内偏移解析成缓存索引和块内偏移两部分。缓存索引被三级渗 透缓存通用,处理器依次访问各级缓存。通过缓存索引定位到某一个或某几个(组 相联)缓存单元后,将(2)中得到的缓存 tag 比较地址和定位到的缓存单元的 tag 比 较:若相同,则表示缓存命中,通过块内偏移在缓存单元中得到处理器需要的数 据;否则,表明该级渗透缓存缺失,继续访问下级缓存。若所有渗透缓存都缺失, 则将(2)中 tag 比较地址和(1)中的页内偏移组合成物理地址,使用物理地址访问内存,得到处理器需要的数据。