阅读484 返回首页    go iPhone_iPad_Mac_apple


Linux内核剖析 之 内存寻址(二)

//接前一篇博客:

本节主要介绍硬件中分页机制。

4、线性地址->物理地址(分页:硬件部分

       为了效率,线性地址被分成以固定长度为单位的组,称为页(Page),页内部连续的线性地址被映射到连续的物理地址中。

      分页单元把所有的内存分成固定长度的页框(page frame)。每个页框包含一个页(page),也就是说一个页框的长度与一个页的长度一致。页框是主存的一部分,因此是一个存储区域。页和页框是不同的,也只是一个数据块,可以存放在任何页框或磁盘中。

4.1、分页

      从80386起,Intel处理器的分页单元处理4KB的页。

      32位线性地址被分成3个域:

      *Directory(目录):最高10位

      *Table(页表):中间10位

      *Offset(偏移量):最低12位

      线性地址的转换分两步完成:

      *页目录表转换;

      *页表转换。

      使用二级模式的目的在于减少每个进程页表所需内存的数量。

 

      控制寄存器cr3中存放正在使用的页目录的物理地址。线性地址内的Directory字段决定页目录中的目录项,而目录项指向适当的页表。地址的Table字段依次又决定页表中的表项,而页表含有页所在页框的物理地址。Offset字段决定页框内的相对位置。由于Offset字段是12位长,故每一页含有4096B的数据。


      页目录项和页表项具有相同的结构每项包含下面的字段

      *Present标志:

      置1,所指页或页表在主存中;为0,不在主存中。如果当访问一个地址时,页目录项或页表项的Present标志为0,则分页单元将该线性地址存放在寄存器cr2中,产生14号异常:缺页异常。

      *Field 标志

      20位,页目录项中的Field指向包含一个页表的页框。页表项中的Field指向包含一页数据的页框。

      *PCD/PWT 标志控制硬件高速缓存处理页或页表的方式。

      *Accessed 标志:每当分页单元对相应页框进行寻址时,设置这个标志。分页单元从来不重置这个标志,而是必须由操作系统去做。

      *Dirty 标志:只应用于页表项中,每当对一个页框写操作时就设置。分页单元从来不重置这个标志,而是必须由操作系统去做。

      *Read/Write:页或页表的存取权限。与段的3种存取权限(读、写、执行)不同的是,页的存取权限只有两种(读、写)。如果Read/Write标志为0,说明相应的页表或页是只读的,否则是可读写的。

      *User/Supervisor:访问页或页表所需的特权级。若此标志为0,只有当CPL小于3(Linux:CPU处于内核态)时才能对页寻址,否则总能对页寻址。

      *Page Size:只应用于页目录项。设置为1,则页目录项指向2M或4M的内存。(hugepage)

      *Global标志:只应用于页表项,用于防止常用页(全局页)从TLB中刷新出去。(当cr4寄存器的PGE(页全局启用)标志置位时,这个标志才有效)


      ##扩展分页:(页框大小为4MB而不是4KB)

      ——通过设置cr4处理器寄存器的PSE标志能使扩展分页与常规分页共存。

 

     对于2M页面,启动时传递内核参数

hugepages=1024 

     对于1GB的页面:

default_hugepagesz=1G hugepagesz=1G hugepages=4

    CPU所支持的hugepage大小可以由cpu标志得知

If pse exists, 2M hugepages are supported; if pdpe1gb exists, 1G hugepages are supported.

For 2 MB pages, there is also the option of allocating hugepages after the system has booted.


echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages

 

mkdir /mnt/huge

mount -t hugetlbfs nodev /mnt/huge

      只要是在 /mnt/huge/ 目录下创建的文件,将其映射到内存中时都会使用 2MB 作为分页的基本单位。值得一提的是,hugetlbfs 中的文件是不支持读 / 写系统调用 ( 如read()或write()等 ) 的,一般对它的访问都是以内存映射的形式进行的。

     在实际应用中,为了使用大页面,还需要将应用程序与库libhugetlb链接在一起。libhugetlb库对malloc()/free()等常用的内存相关的库函数进行了重载,以使得应用程序的数据可以放置在采用大页面的内存区域中,以提高内存性能。


      ##物理地址扩展(PAE)分页机制:

      物理地址扩展(Physical Address ExtensionPAE)用于将32位线性地址转换为36位物理地址。

      通过设置cr4控制寄存器中的PAE标志激活PAE

      PAE分页机制:

      *64GBRAM被分为2^24个页框,页表项的物理地址字段从20位扩展到了24位。一个4KB的页表包含512个表项而不是1024个表项。

      *引入页目录表指针表(Page Directory Pointer TablePDPT)的页表新级别,它由464为表项组成。

      *cr3控制寄存器包含一个27为的页目录指针表(PDPT)基地址字段。

      *当把线性地址映射到4KB的页时,32位线性地址按下列方式解释:

      Cr3:指向一个PDPT

      位31-30:指向PDPT4个项的一个;

      位29-21:指向页目录表中512个项中的一个;

      位20-12:指向页表中512项中的一个;

      位11-04KB页中的偏移量。

     *当把线性地址映射到2MB的页时,32位线性地址按下列方式解释:

      Cr3:指向一个PDPT

      位31-30:指向PDPT4个项的一个;

      位29-21:指向页目录表中512个项中的一个;

      位20-02MB页中的偏移量。


4.2 加快线性地址转换

      为了缩小CPURAM之间的速度不匹配,引入了硬件高速缓存。基于局部性原理。

      #cache line :高速缓存与内存间一次传输数据的长度。

      #PCD 当访问该页框中数据时,高速缓存功能被启用还是禁用。

      #PWT:当数据被写到页框时,采用通写策略还是回写策略。

      Linux对所有页框都启用高速缓存,对写操作都采用回写策略。

 

      TLB(Translation Lookaside Buffer):转换后援缓冲器。

      在多处理器系统中,每个CPU都有自己的TLB,称为本地TLB

      机制:当一个线性地址第一次使用时,通过慢速访问RAM的页表计算出相应的物理地址,同时,该物理地址被存放在一个TLB表项(TLB Entry)中,以便以后对同一线性地址的引用可以快速地转换。

最后更新:2017-04-03 05:39:30

  上一篇:go Cocos2d-x中触摸事件
  下一篇:go C# Timer 定时器应用