Linux中的分页机制

2011年10月25日 由 edsionte 留言 »

Linux中采用了一种通用的四级分页机制,即页全局目录(Page Global Directory)、页上级目录(Page Upper Directory)、页中间目录(Page Middle Directory)和页表(Page Table)。在这种分页机制下,一个完整的线性地址被分为五部分:页全局目录、页上级目录、页中间目录、页表和偏移量,但是对于每个部分所占的位数则是不定的,这跟系统所在的体系架构有关。

对于x86-32(未采用PAE)架构的系统来说,线性地址中的页上级目录和页中间目录两部分占用的位数均为0,页上级目录和页中间目录中都只包含一个目录项,这两个页表项(这里称为页目录项更为确切,下文中的页表项均指某级页表中的一项,对页目录项和页表项不再作特别区分)都被映射到页全局目录中一个适当的目录项中。这种方法本质上只包含两级页表,但是它却仍然保持着四级页表模型。其他未采用四级页表模型的体系架构都采用类似的方法,因此这种四级分页机制具有通用性。

1.数据结构

Linux分别采用pgd_t、pmd_t、pud_t和pte_t四种数据结构来表示页全局目录项、页上级目录项、页中间目录项和页表项。这四种数据结构本质上都是无符号长整型,Linux为了更严格数据类型检查,将无符号长整型分别封装成四种不同的页表项。如果不采用这种方法,那么一个无符号长整型数据可以传入任何一个与四种页表相关的函数或宏中,这将大大降低程序的健壮性。下面仅列出pgd_t类型的内核源码实现,其他类型与此类似。

arch/x86/include/asm/pgtable_64_types.h
 13 typedef unsigned long   pgdval_t;
arch/x86/include/asm/pgtable_types.h
192 typedef struct { pgdval_t pgd; } pgd_t;
arch/x86/include/asm/pgtable.h
 66 #define pgd_val(x)      native_pgd_val(x)
arch/x86/include/asm/pgtable_types.h
199 static inline pgdval_t native_pgd_val(pgd_t pgd)
200 {
201         return pgd.pgd;
202 }

这里需要区别指向页表项的指针和页表项所代表的数据。如果已知一个pgd_t类型的指针pgd,那么通过pgd_val(*pgd)即可获得该页表项(也就是一个无符号长整型数据),这里利用了面向对象的思想。

2.线性地址、页表和页表项

线性地址

不管系统采用多少级分页模型,线性地址本质上都是索引+偏移量的形式,甚至你可以将整个线性地址看作N+1个索引的组合,N是系统采用的分页级数。在四级分页模型下,线性地址被分为5部分,如下图:

 

在线性地址中,每个页表索引即代表线性地址在对应级别的页表中中关联的页表项。正是这种索引与页表项的对应关系形成了整个页表映射机制。

页表

多个页表项的集合则为页表,一个页表内的所有页表项是连续存放的。页表本质上是一堆数据,因此也是以页为单位存放在主存中的。因此,在虚拟地址转化物理物理地址的过程中,每访问一级页表就会访问一次内存。

页表项

从四种页表项的数据结构可以看出,每个页表项其实就是一个无符号长整型数据。每个页表项分两大类信息:页框基地址和页的属性信息。在x86-32体系结构中,每个页表项的结构图如下:

这个图是一个通用模型,其中页表项的前20位是物理页的基地址。由于32位的系统采用4kb大小的 页,因此每个页表项的后12位均为0。内核将后12位充分利用,每个位都表示对应虚拟页的相关属性。

不管是那一级的页表,它的功能就是建立虚拟地址和物理地址之间的映射关系,一个页和一个页框之间的映射关系体现在页表项中。上图中的物理页基地址是个抽象的说明,如果当前的页表项位于页全局目录中,这个物理页基址是指页上级目录所在物理页的基地址;如果当前页表项位于页表中,这个物理页基地址是指最终要访问数据所在物理页的基地址。

 3.地址转换过程

有了上述的基本知识,就很好理解四级页表模式下如何将虚拟地址转化为逻辑地址了。基本过程如下:

1.从CR3寄存器中读取页目录所在物理页面的基址(即所谓的页目录基址),从线性地址的第一部分获取页目录项的索引,两者相加得到页目录项的物理地址。

2.第一次读取内存得到pgd_t结构的目录项,从中取出物理页基址取出(具体位数与平台相关,如果是32系统,则为20位),即页上级页目录的物理基地址。

3.从线性地址的第二部分中取出页上级目录项的索引,与页上级目录基地址相加得到页上级目录项的物理地址。

4.第二次读取内存得到pud_t结构的目录项,从中取出页中间目录的物理基地址。

5.从线性地址的第三部分中取出页中间目录项的索引,与页中间目录基址相加得到页中间目录项的物理地址。

6.第三次读取内存得到pmd_t结构的目录项,从中取出页表的物理基地址。

7.从线性地址的第四部分中取出页表项的索引,与页表基址相加得到页表项的物理地址。

8.第四次读取内存得到pte_t结构的目录项,从中取出物理页的基地址。

9.从线性地址的第五部分中取出物理页内偏移量,与物理页基址相加得到最终的物理地址。

10.第五次读取内存得到最终要访问的数据。

整个过程是比较机械的,每次转换先获取物理页基地址,再从线性地址中获取索引,合成物理地址后再访问内存。不管是页表还是要访问的数据都是以页为单位存放在主存中的,因此每次访问内存时都要先获得基址,再通过索引(或偏移)在页内访问数据,因此可以将线性地址看作是若干个索引的集合。

广告位

发表评论

windows 7 ultimate product key

windows 7 ultimate product key

winrar download free

winrar download free

winzip registration code

winzip registration code

winzip free download

winzip free download

winzip activation code

winzip activation code

windows 7 key generator

windows 7 key generator

winzip freeware

winzip freeware

winzip free download full version

winzip free download full version

free winrar download

free winrar download

free winrar

free winrar

windows 7 crack

windows 7 crack

windows xp product key

windows xp product key

windows 7 activation crack

windows7 activation crack

free winzip

free winzip

winrar free download

winrar free download

winrar free

winrar free

download winrar free

download winrar free

windows 7 product key

windows 7 product key