首页 > 代码库 > MMU(TLB)与Cache的工作方式
MMU(TLB)与Cache的工作方式
MMU中TLB的作用:
从虚拟地址到物理地址的转换过程可知:使用一级页表进行地址转换时,每次读/写数据需要访问两次内存,第一次访问一级页表获得物理地址,第二次才是真正的读/写数据;使用两级页表时,每次读/写数据需要访问三次内存,访问两次页表(一级页表和二级页表)获得物理地址,第三次才是真正的读/写数据。
上述的地址转换过程打打降低了CPU的性能,有没有办法改进呢?程序执行过程中,所用到的指令、数据的地址往往集中在一个很小的范围内,其中的地址、数据经常多次使用,这称为程序访问的局部性。由此,通过使用一个高速、容量相对较小的存储器来存储近期用到的页表条目(段/大页/小页/极小页描述符),以避免每次地址转换时都到主存去查找,这样可以大幅度地提高性能。这个存储器用来帮助快速地进行地址转换,称为“转译查找缓存”(TLB)。
当CPU发出一个虚拟地址时,MMU首先访问TLB,如果TLB中含有能转换这个虚拟地址的描述符,则直接利用此描述符进行地址转换和权限检查;否则MMU访问页表找到描述符后再进行地址转换和权限检查,并将这个描述符填入TLB中(如果TLB已满,则利用round-robin算法找到一个条目,然后覆盖它),下次再使用这个虚拟地址时就可以直接使用TLB中的地址描述符了。
Cache和MMU:
按照工作原理来分,cache有physical index physical tagged, virtual index virtual tagged, physical index virtual tagged等几种工作方式。
Physical index physical tagged是一种最容易理解的操作方式,cache针对物理地址进行操作,简单粗暴,而且不会有歧义。但是这种方式的缺陷也很明显,在多进程操作系统中,每个进程拥有自己独立的地址空间,指令和代码都是以虚拟地址的方式存在,cpu发出的memory access的指令都是以虚拟地址的方式发出,这样的话,对于每一个memory access的操作,都要先等待MMU将虚拟地址翻译为物理地址,这是一种串行的方式,效率较低。
Virtual index virtual tagged是纯粹用虚拟地址来寻址,这种方式带来了更多的问题,每一行数据在原有tag的基础上都要将进程标识加上以区分多个进程之间的相同地址,而在处理共享内存时也比较麻烦,共享内存在不同的进程中的虚拟地址不相同,如何同步是个问题。
virtual index physical tagged方式现在使用的比较多,virtual index的含义是当cpu发出一个地址请求之后,低位地址去和cache中的index匹配(因为低位一般都是页内偏移地址,不影响页的选择), physical tagged是指虚拟地址的高位地址去和mmu中的页表匹配以拿到页的物理地址,这样保证了Cache和MMU并行工作。然后用从mmu中取到的页物理地址作为tag(或者tag的一部分)去和cache line的tag位匹配,这样既保证了同一地址在cache中的唯一性(有个例外,cache alias)又能将mmu和cache并行工作,提高了效率。这种方式带来的唯一问题就是cache alias,当cache alias在cache大小同内存页框大小不一致时,比如说每路cache的大小是8k,而现在较为常用的页框大小是4k,这两个数字说明的问题分别是这样的:
页框大小为4k意味着mmu在划分虚拟空间时是以4k为粒度,每一个4k对齐的内存区域作为内存分配的最小单位,于是就有了这样的结果,虚拟地址和物理地址的低12位是相同的,因为低12位地址是作为其在4k页框内的偏移,不管它的虚拟地址是什么,它在4k页面内的偏移是一定的。
Cache大小为8k,意味着cache index是用依据13位地址来运算的,而如果以虚拟地址来寻址cache,低13位中就包含了一位虚拟地址,所以这种方式称为virtual index。问题出现了,一个物理地址当它被不同进程使用时,由于mmu分页机制仅能保证其低12位相同,那么第13位很有可能是不同的,这样就造成了一个物理地址在cache中有两个副本,可能会造成同步问题。
针对于cache alias问题,目前的方案是由操作系统来保证,对于同一物理地址在不同进程空间的虚拟地址,他们的虚拟地址的差一定是cache大小的整数倍,也就是说他们的第13位一定是相同的。同时已经有些cpu厂商在开发监视模块,试图在硬件层面解决类似的同步问题。
MMU(TLB)与Cache的工作方式