Chinaunix首页 | 论坛 | 博客
  • 博客访问: 234891
  • 博文数量: 19
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1182
  • 用 户 组: 普通用户
  • 注册时间: 2013-02-20 23:47
个人简介

如果人生是一条隐含马尔科夫模型,那维特比算法告诉我已经偏离最优路线了,但如果起点是现在呢?

文章分类

全部博文(19)

文章存档

2020年(2)

2014年(3)

2013年(14)

分类: 服务器与存储

2014-02-26 23:05:15

    虚拟内存无处不在:搞偏底层一点语言的同学可能经常碰到segment fault这类异常,这反映的是vm对物理地址进行保护;而使用java这样对内存使用挥金如土的语言的同学,又会碰到频繁swap的问题,这反映的是vm把物理内存当cache用,总之样样都有它的影子;本文主要讲虚拟内存如何把主存当做磁盘上地址空间的快取,以及虚拟内存上的地址到实际物理地址的转换

一.虚拟内存用作高速缓存

    以32位系统为例,那么虚拟地址空间是4G;从高速缓存的角度上讲,硬盘上的空间+内存条上的空间最大应可以增加到4G,假设每页大小是4KB,则该虚拟内存总共有1M个页面,于是我们可以得出下图的结构:


1.左边那个常驻内存的叫页表,总共有1M项,每项包含一个bitvalid位,和页面地址——指向内存的or指向硬盘的or此页尚未分配

2.右下边的图描述的是uncached状态的页面,页面储存在硬盘上

3.右上角的描述的是cache状态的页面,页面储存在内存上


  1. 缓存命中:

    如上图所示,我们需要页面2VP2),于是在页表中查找PTE2,发现其valid1,缓存命中,根据页面地址在内存中定位到页面

  2. 缓存miss

    如上图所示,我们需要页面VP3, 于是在页表中查看PTE3, 发现其valid0,于是要的页面在磁盘上躺着,为了彰显局部性,我们得把VP3整块的读取出来,这个过程叫page in,而内存只有那么大,为了给VP3腾地儿我们选择将VP4拷贝回硬盘,这叫swap out

一些误解:

1.书上说,虚拟内存是组织在硬盘上的一串连续的byte数组,因此硬盘空间小于4G系统将无法分配足够的虚拟内存

答:只要硬盘上的加上内存上的有4G即可,会有这种想法的同学主要是还没理解页表的功能,PTE保存的是指向内存or硬盘的地址,只要两者加起来够虚拟内存就可以了;书上那么说是从“把内存当做硬盘的cache”的角度出发的,硬盘上那4G并不是客观存在的,真正要使用虚拟地址时也是从页表上查找

二.虚拟-物理地址转换

高速缓存只是虚拟内存宏观上的一个功能,更细节一点的是地址转换:跑在OS上的应用程序都是使用的虚拟地址,而硬件只认物理地址,这就涉及到很复杂的逻辑了。

一级页表地址转换:

结构:假设虚拟地址32位,物理地址是31位(即内存条有2G);把虚拟地址分成低12位(页面内部偏移VPO),高20位(页面编号VPN;把物理地址分成低12位(页面内部偏移PPO),高19位(页面编号PPN;页表总共有1M项,每个页表项(PTE)由1valid19PPN组成

转换过程:

  1. 处理器生成32位虚拟地址,并传送给MMUcpu里面的内存管理单元)

  2. MMU截取虚拟地址中20位的VPN,并据此从页表中获取PTE

  3. MMUPTE中获取19位的PPN,与12VPOPPO)拼接在一起得到最终的物理地址

在得到物理地址后,就能从cache体系中读取到虚拟地址存放的字了,请注意虚拟页面跟物理页面是相等的,因此VPO等于PPO


如图所示,这里的n=32,p=12m=31


使用TLB加速地址转换:

在上文转换过程的第2步,MMU还要从主存中获取页表,为了加快速度,很多硬件厂商直接在MMU增加了一个针对页表的cache——translation lookaside buffer

tlb是相连度较高的的组相连高速缓存,其中每行只有一个元素,所以不存在偏移的说法(关于高速缓存请参阅http://blog.chinaunix.net/uid-26726125-id-4118381.html


如图,我们将VPN分成两部分,低位TLBI用作组索引,高位TLBT作为tag位,通过这两部分到tlb高速缓存中获取PTE

多级页表地址转换:

    在上面的一级页表转换中,单个PTE大约3byte,总数量共有1M个,因此一个页表就占了3MB连续的地址空间,而且更恶心的是,这个页表你还不能把它放在比较低levelcache中,因为地址转换随时要用到它,慢谁也不能慢它。。。

    用多级页表就能解决这个问题,我们将上例中20位的VPN分为相等的两个部分VPN1VPN2VPN1用于在一级页表中查找PTEVPN2用于在二级页表中查找,于是一级页表就只需要保存1KPTE即可,相应的大小也不会超过4KB,很容易就塞进L1里面,而二级页表根据实际需要创建,最多创建1K个,每个也是保存1KPTE;转换的时候,先根据VPN1在一级页表的找到对应的PTE,而这个PTE保存的是一个二级页表的地址,再用VPN2到这个二级页表中查找PTE,这个保存的就是物理页的地址了,再拼接上虚拟地址中的VPO,就能得到最终的物理地址

实战:端到端的地址翻译

说了这么多理论知识,我们来走个全流程:将一个虚拟地址转换成物理地址,并从cache中读取一个字(假设为1byte

设虚拟地址为14位,页面大小64byte,物理地址12位,TLB是一个44组的组相连高速cacheL1是一个16组直接映射的高速cache

于是得出如下结构

页面大小64可得出VPO6,而且PPO=VPO

tlb4组,于是可得知TLBI2,进而剩下TLBT6

L1快取每组4字节,共16组,与之对应:物理地址的CO2位,CI4,剩下的CT6

现在已知虚拟地址0x03d4CPU需要读取在这个地址上的字


分拆虚拟地址查找物理地址

根据TLBITLBTtbl缓存里查找,发现命中PTE,而且valid位为1,于是PPN0D,进而完成虚拟-物理地址转换,得到物理地址0x354

分拆物理地址查找缓存

根据CICOL1缓存里查找,发现命中,于是返回字0x36


上面需要注意的有两点,

  1. 如果tlb未能命中,则需要从主存中的页表中获取PPN,速度会大打折扣,也就是我们常说的TLB miss
  2. CI+CO恰好等于PPO这种情况,被很多CPU厂商加以利用,用做CPU并行读取

  • 由于L1的结构已知,可以先取VPO算出CICO,进而锁定cache中的候选字(还缺一个tag,不能算选中了)

  • 同时并发的根据VPN获取PPN:从TLB中或者多级页表中,等于最后得到就是CT了(因为CT长度恰好等于PPN长度),CT与候选字的tag进行比较,发现相等,结束

阅读(8131) | 评论(1) | 转发(1) |
给主人留下些什么吧!~~