1.简介
处理器中的虚拟内存子系统为每个进程提供了虚拟地址空间。这使得每个进程认为它自己是独立的。虚拟地址有很多优点,此处不表。这里讲它的实现细节。
这个虚拟地址空间是由MMU(memory management unit)实现,MMU就是虚拟内存子系统。MMU是cpu中的东西。作用就是完成逻辑地址到线性地址(虚拟地址)再到物理地址的转换。逻辑地址到线程地址(虚拟地址)由MMU中的段机制实现转换,线性地址到物理地址由MMU中的页机制实现转换。在LINUX kernel中,段机制只是为了应和cpu(intel)中段机制,实际上段机制转换后,逻辑地址和线性地址在数值上相等,统一叫虚拟地址,后续的分页机制才是主角。
2.最简单的地址转换
最有意思的部分就是虚拟地址到物理地址的转换。MMU完成这个地址的映射转换。
一级页表地址转换。虚拟地址的offset等于物理地址的offset,不需转换。进行转换的是前面的部分。一级页表有一个问题,那就是要表示所有的页框,需要的页表项非常多,检索起来很费时间。例如,一个大小为4M的页,在32位cpu中,这个4M的页一共有pow(2,22)个页表项,这检索起来简直要命。
于是进行分层(级),有了多级页表。
不同的U中,页表的级数也不同。
在这多级页表中,是怎么样一级一级走的。
首先,cr3里放着level4的首地址,指向level4 directory。level4 index指向第几个。最后找到的entry是下一个level的首地址,依次类推。
3.页表访问优化
主要角色:TLB
一,由来
os可以建立和更新与页表有关的数据结构,这些都存在于内存中。一旦有进程创建或者页表变化,cpu将会收到通知(os进行通知)。页表用来实现虚拟地址到物理地址的转换。为了加快转换速度,我们假想把这些页表目录缓存到cpu cache中,但是这样还是慢,性能很差。我们有下面这个更好的方法。
我们不缓存页表目录了,我们缓存虚拟地址到物理地址的映射(更确切地說是××地址不包含offset的部分,因为offset不变,没必要算来算去)。这样因为没有了offset,缓存的量一下就减小了,当然速度就快了。
这个存放虚拟地址(excluding offset)到物理地址(excluding offset)映射的缓冲区我们叫TLB。TLB小而快。因为小,放不了太多虚拟到物理地址的映射,如果TLB中找不到这个映射,就得按页表一级一级找了,找到后加入TLB。
TLB也是缓存,故可多级。在L1层,TLB也分为数据和指令。
二,警示
TLB是处理器级别的资源,就是说每个cpu有它们独自的TLB.在一个cpu核中,所有的线程和进程使用相同的TLB(它只有一个),每个进程有各自的页表。如果一个进程的地址空间发生变化,那TLB怎麽办。
-页表只要改变,TLB就刷新
-在TLB实体上增加一个标志位,用于标志变化的页表。
第一种方法代价太大,只要有变化就刷新,刷新了很多本不需要刷新的。
第二种较第一种有改善。
页表的大小对TLB的性能也有影响。太大太小都降低其性能。
4.总结
关于TLB此处写得不详细,也很模糊,日后添坑。