cache,中译名高速缓冲存储器,其作用是为了更好的利用局部性原理,减少CPU访问主存的次数。简单地说,CPU正在访问的指令和数据,其可能会被以后多次访问到,或者是该指令和数据附近的内存区域,也可能会被多次访问。因此,第一次访问这一块区域时,将其复制到cache中,以后访问该区域的指令或者数据时,就不用再从主存中取出。
注意:这里的cache一般是SRAM,主存一般是DRAM,CPU指CPU寄存器,所以整个过程是CPU寄存器——SRAM——DRAM
cache对于程序员是不可见的,它完全是由硬件控制的
在以前,CPU的主频比较慢,CPU和内存DRAM之间速度差别不是很大,存储数据或者指令还OK。但是CPU的飞速发展,CPU大哥速度已经飞快,而内存速度却跟不上大哥的步伐,所以大哥每次要读取或者写入内存的时候都要等一等小弟,这个时候怎么办。cache就出来了,它类似与一个第三方。位于内存和CPU之间,速度非常快,所以CPU就把数据直接写入cache,然后CPU就可以干其他的了,剩下的事情就交给cache这个跑腿的,cache在合适的时机可以慢慢的把数据写入内存,也就是相当于解了CPU的燃眉之急。
说白了,CPU要读数据首先是在cache中读,如果cache命中,也叫cache hit,CPU就可以极快的得到该地址处的值。如果cache miss 也就是没有命中,它就会通过总线在内存中去读,并把连续的一块单元加载到cache中,下次好使用。
cache大多是SRAM(静态RAM),而内存大多是DRAM(动态随即存储)或者DDR(双倍动态随机存储)。
cache容量一般非常小,因为价格贵,所以cache小是有道理的。
一级cache一般就几KB,cache 的单位又分成cache line ,它是从内存单元加载到cache中的最小单元,
一般为几个字大小,32字节或者64字节偏多。
(因为时间局部性和空间局部性所以加载一次是以一个cache单元为最小单位)
写回(Write-back)和写通(Write-through)的对象都是内存
简单介绍:写通也就是当CPU写入cache的时候,将数据再从cache 中写到内存中,这两个过程要都结束后,CPU的写入操作才算完成,也就是时刻保持内存和缓存的同步,这显然是很耗时的,因为写到内存比较耗时。
写回也就是当CPU写入cache中的时候,数据不会马上从cache中写到内存里面,而是等待时机成熟后写入(比如 发生cache miss,其他内存要占用该cache line的时候将该单元写回到内存中,或者一定周期后写入到内存中 ,或者其它地核需要读取该内存的时候)。
一级cache 有指令cache和数据cache之分,这使整个系统更加高效,因为1Lcache 容量小,所以有了多级cache ,比如二级cache ,他容量大,但是速度就要比1Lcache 慢些,但比内存快多了。三级cache就更一些了。
其实cache就是高速缓存,高速缓存不是一个特指的东西,高速缓存是相对于速度慢的存储而言。 存储器层次结构的主要思想是上一层的存储器作为低一层存储器的高速缓存。因此,寄存器文件就是Ll 的高速缓存, Ll 是L2 的高速缓存, L2 是L3 的高速缓存, L3 是主存的高速缓存,而主存又是磁盘的高速缓存。在某些具有分布式文件系统的网络系统中,本地磁盘就是存储在其他系统中磁盘上的数据的高速缓存。
几个关键的层次访问速度:
除了本文主角CPU高速缓存外,计算机系统还有很多利用“缓存”的地方:
甚至还有浏览器缓存:
缓存(cache)大小是CPU的重要指标之一,其结构与大小对CPU速度的影响非常大。简单地讲,缓存就是用来存储一些常用或即将用到的数据或指令,当需要这些数据或指令的时候直接从缓存中读取,这样比到内存甚至硬盘中读取要快得多,能够大幅度提升cpu的处理速度。
CPU与cache之间的数据交换是以”字”为单位,而cache与主存之间的数据交换是以”块”为单位,一个块由若干字组成,是定长的,以体现”保存下级存储器刚才被存取过的数据及其邻近小范围的数据”这一概念。
CPU进行存储器读操作时,根据主存地址可分成命中和未命中两种情况。对于前者,从Cache中可直接读到所需的数据;对于后者,需访问主存,并将访问单元所在的整个块从内存中全部调入Cache,接着要修改Cache标记。若Cache已满,需按一定的替换算法,替换掉一个旧块。
一级缓存中还分数据缓存(data cache,d-cache)和指令缓存(instruction cache,i-cache)。二者分别用来存放数据和执行这些数据的指令,而且两者可以同时被cpu访问,减少了争用cache所造成的冲突,提高了处理器效能。
采用分立Cache技术,也就是将指令和数据分开,分别存放在指令Cache 和数据Cache中。这种分立Cache技术有利于CPU采用流水线方式执行指令。在流水线中,往往会发生在同一个操作周期同时需要预取一条指令和执行另一条指令的取数据操作的情况。若采用指令和数据统一的Cache,则这种情况会造成取指令和取数据的访存冲突,冲突的结果就是使得流水线产生断流的情况发生,从而严重影响流水线的效率。采用分立Cache技术,因为取指令和取数据分别在不同的Cache中同时进行,因而不会产生冲突,有利于流水线的实现
二级缓存(L2 CACHE)出现是为了协调一级缓存与内存之间的速度。最初缓存只有一级,后来处理器速度又提升了,一级缓存不够用了,于是就添加了二级缓存。二级缓存是比一级缓存速度更慢,容量更大的内存,主要就是做一级缓存和内存之间数据临时交换的地方用。“L1级Cache-L2级Cache-主存”这种层次从工作原理上讲与前述的Cache工作原理是完全相同的,即CPU首先访L1级Cache,若不命中,再访问L2级Cache和主存。
当CPU试图读取主存一个字时,发出此字内存地址同时到达cache和主存,此时cache控制逻辑依据地址的标记部分进行判断此字当前是否在cache中。若是(命中),此字立即递交给CPU,若否(未命中),则要用主存读取周期把这个字从主存读出送到CPU,与此同时把含有这个字的整个数据块从主存读出送到cache中。由于程序的存储器访问具有局部性,当为满足一次访问需求而取来一个数据块时,下面的多次访问很可能是读取此块中的其它字。
细心的朋友到这里会发现,怎么又有一个cache,刚才说cache是CPU高速缓存,怎么这里又叫页高速缓存,一个类型?
其实不然,两个同名,但是意思不同。
CPU高速缓存是CPU——SRAM(cache)——DRAM(主存)
页高速缓存是内核读写——DRAM(主存)——ROM(磁盘),页高速缓存cache在主存里
页高速缓存(cache)是Linux内核实现磁盘缓存。磁盘高速缓存是一种软件机制,**它允许系统把通常存放在磁盘上的一些数据保留在 RAM 中,以便对那些数据的进一步访问不用再访问磁盘而能尽快得到满足。**它主要用来减少对磁盘I/O操作。是通过把磁盘中的数据缓存到 物理内存中,把对磁盘的访问变为对物理内存的访问。
注:页高速缓存叫cache,也叫page cache
页高速缓存(cache)和CPU高速缓存cache的工作模式相似
当内核从磁盘中读取数据时,内核试图先从高速缓冲中读。如果数据已经在该高速缓冲中,则内核可以不必从磁盘上读。如果数据不在该高速缓冲中,则内核从磁盘上读数据,并将其缓冲起来。
写操作与之类似,要往磁盘上写的数据也被暂存于高速缓冲中,以便如果内核随后又试图读它时,它能在高速缓冲中。内核也通过判定是否数据必须真的需要存储到磁盘上,或数据是否是将要很快被重写的暂时性数据,来减少磁盘写操作的频率。
几乎所有的文件读和写操作都依赖于页高速缓存。只有在O_DIRECT标志被置位而进程打开文件的情况下才会出现例外:此时,IO数据绕过了页高速缓存,而使用了进程用户态地址空间的缓冲区;少数数据库应用软件为了能采用自己的磁盘高速缓存算法而使用O_DIRECT标志。
O_DIRECT:
一般如果在Linux内核中读写一个文件,其IO流程都需要经过Kernel内的page cache层次,
若想要使用自己开发的缓存系统,那么就可以在打开这个文件的时候,对该文件加以O_DIRECT的标志位,
这样一来就可以让程序对该文件的IO直接在磁盘上进行,从而避开了Kernel的page cache,
进而对IO流程里的块数据进行拦截,让其流入到自己开发的缓存系统内。
页高速缓存中的信息单位是一个完整的页。
一个页包含的磁盘块在物理上不一定相邻,所以不能用设备号和块号标识,而是通过页的所有者和所有者数据中的索引来识别。