免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2378 | 回复: 6
打印 上一主题 下一主题

[内存管理] 请教一个问题,关于内存寻址中的PUD_SHIFT [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-06-08 15:16 |只看该作者 |倒序浏览
最近在看《深入理解LINUX内核》第三版,看到一个地方不是很理解,望高手指点!

书中第64页,有如下的说明:
   在80x86处理器上,PUD_SHIFT总是等价于PMD_SHIFT,...

在网上搜了一下,也有大量类似的表述。
但是从代码中看(2.6.11),有如下的定义:
  #define PUD_SHIFT PGDIR_SHIFT

PAE使能时,PMD_SHIFT=21, PUD_SHIFT=PGDIR_SHIFT=30
PAE未使能时,PMD_SHIFT=PUD_SHIFT=PGDIR_SHIFT=22

说PUD_SHIFT总是等价于PGDIR_SHIFT是否更合适一些?是书中所写有误,还是我弄错了?

论坛徽章:
15
射手座
日期:2014-02-26 13:45:082015年迎新春徽章
日期:2015-03-04 09:54:452015年辞旧岁徽章
日期:2015-03-03 16:54:15羊年新春福章
日期:2015-02-26 08:47:552015年亚洲杯之卡塔尔
日期:2015-02-03 08:33:45射手座
日期:2014-12-31 08:36:51水瓶座
日期:2014-06-04 08:33:52天蝎座
日期:2014-05-14 14:30:41天秤座
日期:2014-04-21 08:37:08处女座
日期:2014-04-18 16:57:05戌狗
日期:2014-04-04 12:21:33技术图书徽章
日期:2014-03-25 09:00:29
2 [报告]
发表于 2014-06-09 09:01 |只看该作者
看似说的是,当32位且未启用PAE的情况下,PUD_SHIFT=PMD_SHIFT=PGD_SHIFT

论坛徽章:
0
3 [报告]
发表于 2014-06-09 13:57 |只看该作者
本帖最后由 cu_philfrank 于 2014-06-09 14:02 编辑

你这里提到的80x86处理器是32位的,所以PUD根本就用不上。只有64位的处理器才会用到PUD。

一下是我总结的intel处理器和Linux多级页表的关系:


N级页表 PGDE PUDE PMDE PTE 分页模式
4 PML4E PDPTE PDE PTE IA-32e
3 PDPTE PDPTE PDE PTE PAE/IA-32e
2 PDE PDE PDE PTE 32-bit/PAE/IA-32e
1 PTE PTE PTE PTE 32-bit

论坛徽章:
0
4 [报告]
发表于 2014-06-09 22:49 |只看该作者
谢谢,我只是想确认一下32位的情况,及书中描述是否有误

论坛徽章:
0
5 [报告]
发表于 2014-06-09 23:14 |只看该作者
本帖最后由 l4rmbr 于 2014-06-09 23:20 编辑

内核现在用的是通用的四级页表结构。
PGD -> PUD -> PMD -> PTE

对于x86(不开pae): 2级页表就够了:PGD -> PTE,  所以pud, pmd被折叠了
对于x86(开pae): 3级页表: PGD -> PMD -> PTE. 所以pud被折叠了
对于x86_64:4级页表: PGD -> PUD -> PMD -> PTE

关于“折叠”的意思,就是增加了多余的一层接口,但其实这一层接口是空操作,这样
内核可以使用通用的四级页表,而不用关心具体页表层次的差异。

大概页表的遍历接口如下(只描述概念,不对应实际的代码):

pgd = pgd_offset(mm, addr);
pud = pud_offset(pgd, addr);
pmd = pmd_offset(pud, addr);
pte = pte_offset(pmd, addr);

所以,书中的#define PUD_SHIFT PGDIR_SHIFT没有错,它表达的就是“折叠”的意思,此时pgd与pud等价的,
或者说,pud很特殊,它只有一项。


关于四级页表在内核中的演化,有兴趣可以看我之前写过的文章:
Linux内核4级页表的演进

论坛徽章:
0
6 [报告]
发表于 2014-06-10 21:32 |只看该作者
回复 5# l4rmbr

书中是讲:PUD_SHIFT总是等价于PMD_SHIFT
代码中是:#define PUD_SHIFT PGDIR_SHIFT


   

论坛徽章:
0
7 [报告]
发表于 2014-06-10 23:14 |只看该作者
本帖最后由 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。

    这一点想通了,这些代码就很容易理解了。
   
         
   


      
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP