页表


  虽然应用程序操作的对象是映射到物理内存之上的虚拟内存,但是处理器直接操作的却是物理内存。所以当应用程序访问一个虚拟地址时,首先必须将虚拟地址转换为物理地址,然后处理器才能解析地址访问请求。地址的转换工作需要通过查询页表才能完成,概括地讲,地址转换需要将虚拟地址分段,使每段虚拟地址都作为一个索引指向页表,而页表项则指向下一级别的页表或者指向最终的物理页面。

  Linux中使用三级页表完成地址转换。利用多级页表能够节约地址转换需占用的存放空间。如果利用三级页表转换地址,即使是64位机器,占用的空间也很有限。但是如果使用静态数组实现页表,那么即便是在32位机器上,该数组也将占用巨大的存放空间。Linux对所有体系结构,包括那些不支持三级页表的体系结构(比如,有些体系结构只使用两级页表或者使用散列表完成地址转换)都使用三级页表管理,因为使用三级页表可以利用“最大公约数”的思想——一种设计简单的体系结构,可以按照需要在编译时简化使用页表的三级结构,比如只使用两级。

  顶级页表是页全局目录(PGD),它包含一个pgd_t类型数组,多数体系结构中pgd_t类型等同于无符号长整型类型。PGD中的表项指向二级页目录中的表项PMD。

  二级页表是中间页目录(PMD),它是一个pmd_t类型数组,其中的表项指向PTE中的表项。

  最后一级的页表简称页表,其中包含了pte_t类型的页表项,该页表项指向物理页面。

  多数体系结构中,搜索页表的工作由硬件完成(至少某种程度上)。虽然通常操作中,很多使用页表的工作都可以由硬件执行,但是只有在内核正确设置页表的前提下,硬件才能方便的操作它们。下图描述了虚拟地址通过页表找到物理地址的过程。

 

 

  由于每次对虚拟内存中页面的访问都必须先解析它,从而得到物理内存中对应的地址,所以页面操作的性能非常关键。但不幸的是,搜索内存中的物理地址速度很有限,因此为了加快搜索,多数体系结构都实现了一个翻译后缓冲器(translate lookaside buffer,TLB)。TLB作为一个将虚拟地址映射到物理地址的硬件缓存,当请求访问一个虚拟地址时,处理器将首先检查TLB中是否缓存了该虚拟地址到物理地址的映射,如果在缓存中直接命中,物理地址将立刻返回;否则,就需要再通过页表搜索需要的物理地址。

  虽然硬件完成了有关页表的部分工作,但是页表的管理仍然是内核的关键部分——而且在不断地改进。2.6版内核对页表管理的主要改进是:从高端内存分配部分页表。今后可能的改进包括通过在写时拷贝(copy-on-write)的方式共享页表。这种机制使得在fork()操作中可由父子进程共享页表。因为只有当子进程或父进程试图修改特定页表项时,内核才去创建该页表项的新拷贝,此后父子进程不再共享该页表项。可以看到,利用页表项可以消除fork()操作中页表拷贝所带来的消耗。

  


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM