分类: LINUX
2011-05-11 11:18:04
Linux采用页表的概念来管理虚拟地址空间。MIPS与i386一样,都是二级页表结构,但有些CPU采用三级,甚至四级结构,Linux为了兼容这些CPU,采用四级页表结构:
n PGD:Page Global Directory,页全局目录,是顶级页表。
n PUD:Page Upper Directory,页上级目录,是第二级页表
n PMD:Page Middle Derectory,页中间目录,是第三级页表。
n PTE:Page Table Entry,页面表,最后一级页表。指向物理页面。
进程通过数据结构mm_struct访问PGD,最终找到物理页面:
逻辑上把虚拟地址从高到低分成5部分,分别作为PGD、PUD、PMD、PTE的索引,以及页面内偏移。对于CPU发出的虚拟地址,linux内存管理单元分如下五步完成从虚拟地址到物理地址的映射:
1) 用虚拟地址的最高一个位段作为索引在PGD表中找到对应的表项,该表项指向一个PUD表的基地址。
2) 用虚拟地址中的第二个位段作为索引在PUD表中找到对应的表项,该表项指向一个PMD表的基地址。
3) 用虚拟地址中的第三个位段作为索引在PMD表中找到对应的表项,该表项指向一个PTE表的基地址。
4) 用虚拟地址中的第四个位段作为索引在PTE表中找到对应的表项,该表项中存放的就是指向物理页面的指针(实际上是页帧号PFN和一些标志位的组合体)。
5) 虚拟地址中的最后一个位段是物理页面的页内偏移,将此偏移与物理页面的起始地址相加便得到虚拟地址对应的物理地址。
后面分析内核代码时,会用到下面列出的宏:
n PGDIR_SHIFT:虚拟地址中PGD索引位段的起始地址。
n PTRS_PER_PGD:PGD表中表项的数目。
n PGDIR_SIZE:PGD中每个表项所代表的空间大小。
n USER_PTRS_PER_PGD:需要使用多少个PGD表项才能代表用户空间。
n PUD_SHIFT:虚拟地址中PUD索引位段的起始地址。
n PTRS_PER_PUD:PUD表中表项的数目。
n PUD_SIZE:每个PUD表项所代表的空间大小。对于二级映射的架构而言,PUD_SIZE即PGDIR_SIZE。
n PMD_SHIFT:虚拟地址中PMD索引位段的起始地址。
n PTRS_PER_PMD:PMD表中表项的数目。
n PMD_SIZE:每个PMD表项所代表的空间大小。对于二级映射的架构而言,PMD_SIZE即PGDIR_SIZE。
n PAGE_SHIFT:虚拟地址中PTE索引位段的起始地址。决定了页面的大小。
n PAGE_SIZE:页面大小,1 << PAGE_SHIFT。通常为4KB。
n PTRS_PER_PTE:PTE表中表项的数目。
在我的MIPS开发板上,如果没有使能CONFIG_64BIT_PHYS_ADDR,即不支持64位的地址空间。那么PGDIR_SHIFT为22,表示PGD索引位段为bit[22:31],共10位,则PGD表有210=1024个表项(PTRS_PER _PGD)。在32位CPU上,每个表项是4个字节,这样PGD表的大小为4KB。PGD中每个表项所代表的空间大小是222=4MB的空间(PGDIR_SIZE),则PGD表所能代表的虚拟地址空间为1K×4MB=4GB。对于32位的CPU,用户空间大小是2GB,故用户空间需占用512个PGD表项(USER_PTRS_PER_PGD)。
PUD_SHIFT也为22,表示PUD索引位段的长度为0,即PUD表的大小为20=1(PTRS_PER_PUD),表示每个PUD表只有一个表项,这个表项所代表的空间与一个PGD表项所代表的空间是一样大的。这表明32位MIPS架构的CPU与i386一样,都只有两级页表,但逻辑上又要与linux的三层映射兼容,所以设计了一个逻辑上的PUD。
PMD_SHIFT也为22,含义同PUD。
PAGE_SHIFT为12,表示PTE索引位段为bit[12:21],共10位,则PTE表有210=1024个表项(PTRS_PER_PTE),如果是32位CPU,则每张PTE表需占用4B*1024=4KB的空间,刚好占用一页。每个表项所代表的空间大小是212=4KB的空间(PAGE_SIZE),则每张PTE表代表4KB*1K=4MB的空间(PGDIR_SIZE)。
这样,前面介绍的5步映射的前两步就发生了变化:
1) MMU用虚拟地址的最高一个位段作为索引在PGD中找到对应的表项,该表项逻辑上指向一个PUD,但物理上直接指向PMD表。MMU并不知道PUD的存在。
2) PUD只是逻辑上存在,表中只有一个表项,直接指向PMD表。
3) PMD也只是逻辑上存在,表中只有一个表项,直接指向PTE表。
如果使能了CONFIG_64BIT_PHYS_ADDR,即支持64位的地址空间。而CPU仍是32位的。那么PGDIR_SHIFT为21,表示PGD索引位段为bit[21:31],共11位,则PGD表有211=2K个表项(PTRS_PER _PGD)。在32位CPU上,每个表项是4个字节,这样PGD表的大小为8KB。PGD中每个表项所代表的空间大小是221=2MB的空间(PGDIR_SIZE,则PGD表所能代表的虚拟地址空间为2K×2MB=4GB。。对于32位的CPU,用户空间大小是2GB,故用户空间需占用1024个PGD表项(USER_PTRS_PER_PGD)。
PUD_SHIFT与PMD_SHIFT也为21,含义与32位地址空间相同。
PAGE_SHIFT为12,表示PTE索引位段为bit[12:20],共9位,则PTE表有29=512个表项(PTRS_PER_PTE),如果是32位CPU,每个PTE表项分为高位和地位,共占用8个字节,则每张PTE表需占用8B*512=4KB的空间,也是刚好占用一页。每个表项所代表的空间大小是212=4KB的空间(PAGE_SIZE),则每张PTE表代表4KB*512=2MB的空间(PGDIR_SIZE)。
====
http://yuhao224.chinaunix.com/space.php?uid=7588746&do=blog&id=70703