//接前一篇博客:
本节主要介绍硬件中分页机制。
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 Extension,PAE)用于将32位线性地址转换为36位物理地址。
通过设置cr4控制寄存器中的PAE标志激活PAE。
PAE分页机制:
*64GB的RAM被分为2^24个页框,页表项的物理地址字段从20位扩展到了24位。一个4KB的页表包含512个表项而不是1024个表项。
*引入页目录表指针表(Page Directory Pointer Table,PDPT)的页表新级别,它由4个64为表项组成。
*cr3控制寄存器包含一个27为的页目录指针表(PDPT)基地址字段。
*当把线性地址映射到4KB的页时,32位线性地址按下列方式解释:
Cr3:指向一个PDPT;
位31-30:指向PDPT中4个项的一个;
位29-21:指向页目录表中512个项中的一个;
位20-12:指向页表中512项中的一个;
位11-0:4KB页中的偏移量。
*当把线性地址映射到2MB的页时,32位线性地址按下列方式解释:
Cr3:指向一个PDPT;
位31-30:指向PDPT中4个项的一个;
位29-21:指向页目录表中512个项中的一个;
位20-0:2MB页中的偏移量。
4.2 加快线性地址转换
为了缩小CPU和RAM之间的速度不匹配,引入了硬件高速缓存。基于局部性原理。
#cache line :高速缓存与内存间一次传输数据的长度。
#PCD 当访问该页框中数据时,高速缓存功能被启用还是禁用。
#PWT:当数据被写到页框时,采用通写策略还是回写策略。
Linux对所有页框都启用高速缓存,对写操作都采用回写策略。
TLB(Translation Lookaside Buffer):转换后援缓冲器。
在多处理器系统中,每个CPU都有自己的TLB,称为本地TLB。
机制:当一个线性地址第一次使用时,通过慢速访问RAM的页表计算出相应的物理地址,同时,该物理地址被存放在一个TLB表项(TLB Entry)中,以便以后对同一线性地址的引用可以快速地转换。