- 论坛徽章:
- 0
|
本帖最后由 l4rmbr 于 2014-06-10 23:31 编辑
回复 6# tsdcsp
总是等价于的说法肯定是错的。对于x86_64架构,四级页表,PUD_SHIFT不等同于PMD_SHIFT。页表项分割如下:
| PGDIR | PUD | PMD | PTE | page offset |
|<----------------------- PGDIR_SHIFT --------------------->|
|<---------------- PUD_SHIFT ---------------->|
|<------- PMD_SHIFT ---------->|
|<-- PTE_OFFSET ->|
对于Linux来说,这就是它的通用四级页表,所有页表遍历代码都是依次遍历每一个层次: PGD --> PUD --> PMD --> PTE
它不了解底层架构的差异,不管它们用的是2级,3级,还是4级页表等。
对于底层只有2级硬件页表的架构(如i386)来说, 必须虚构出两层页表来。它只有PGDIR, PTE, 现在要虚构出PUD, PMD来。
怎么虚构?
前面的回答曾说了,四级页表遍历的流程如下:
pgd = pgd_offset(mm, addr);
pud = pud_offset(pgd, addr);
pmd = pmd_offset(pud, addr);
pte = pte_offset(pmd, addr);
当遍历第一层页表: pgd = pgd_offset(mm, address); 就得到下一级页表的物理地址,就是PTE页表。
但现在的通用页表是四级,接下来一级是PUD, 所以要虚构一个 PUD.
pud = pud_offset(pgd, addr);
想要一个pud是吧。那我们造一个给它。
造的方法很简单,就是把当前的页表,进行伪装。即:
pud_t *pud_offset(pgd, address)
{
return (pud_t *)pgd;
}
也就是这一层接口,并不是遍历页表,而是简单返回pgd(当然,要把它转型),这样就”欺骗“了通用四级页表结构,让它
以为自己得到了一个pud.
类似,下一级同样这样虚构。
这里面用的技巧就是:返回同一个页表项,把它假装为下一级的页表项。
等价地理解, 这表示该级(虚拟)页表有且只有一项
所以,此时等价于: PGDIR_SHIFT == PUD_SHIFT。
这一点想通了,这些代码就很容易理解了。
|
|