在介绍HugePages之前,我们先来回顾一下Linux下虚拟内存和物理内存的关系。物理内存:即安装在电脑中的记忆棒。例如安装2GB内存条,则物理内存地址范围为0~2GB。虚拟内存:虚拟内存地址。由于CPU只能使用物理内存地址,所以需要将虚拟内存地址转换为物理内存地址,才能被CPU使用。这个转换过程是由MMU(MemoryManagementUnit,内存管理单元)完成的。在32位操作系统中,虚拟内存空间的大小为0~4GB。我们用图1来描述虚拟内存地址转换为物理内存地址的过程:如图1所示,页表中存放着虚拟内存地址和物理内存地址的映射关系,MMU找到这个映射页表中虚拟内存地址和物理内存地址之间的关系。物理内存地址,然后将物理内存地址提交给CPU,这个过程类似于Hash算法。内存映射基于内存页。通常一个内存页的大小为4KB(如图1所示),因此称为分页机制。1、内存映射我们看一下在64位Linux系统(Intelx64CPU)中虚拟内存地址转换为物理内存地址的过程,如图2所示:从图2可以看出,Linux只使用64位虚拟内存地址的前48位(0~47位),Linux将48位虚拟内存地址分为5部分,如下:PGD索引:39~47位(共9位),在页面全局目录(PGD,PageGlobalDirectory)中指定。PUD索引:30~38位(共9位),指定页上层目录(PUD,PageUpperDirectory)中的索引。PMD索引:21~29位(共9位),指定页中间目录(PMD,PageMiddleDirectory)中的索引。PTE索引:12~20位(共9位),指定在页表(PT,PageTable)中的索引。Offset:0~11bits(共12bits),指定物理内存页中的偏移量。图1中的页表分为4级:页全局目录、页上层目录、页中间目录和页表。目的是减少内存消耗(想想为什么可以减少内存消耗)。注意:页全局目录、页上层目录、页中间目录和页表都占用一个4KB的物理内存页。由于一个64位的内存地址占用8个字节,一个4KB的物理内存页可以容纳512个64位的内存地址。此外,CPU还有一个名为CR3的寄存器,用于保存页全局目录的起始物理内存地址(如图2所示)。因此,将虚拟内存地址转换为物理内存地址的过程如下:从CR3寄存器中获取页全局目录的物理内存地址,然后将虚拟内存地址的39~47位作为索引从页全局目录读取到页上一级目录的物理内存地址。以虚拟内存地址的30~38位为索引,从页的上层目录读取页中层目录的物理内存地址。以虚拟内存地址的21~29位为索引,从页中间目录中读取页表的物理内存地址。以虚拟内存地址的12~20位为索引,从页表中读取物理内存页的物理内存地址。将虚拟内存地址的0到11位作为物理内存页的偏移量,得到最终的物理内存地址。2、HugePages的原理上面介绍了以4KB内存页作为内存映射的单位,但是在某些场景下我们希望使用更大的内存页作为映射单位(比如2MB)。使用更大的内存页作为映射单元有以下优点:减少TLB(TranslationLookasideBuffer)的失效。减少页表的内存消耗。减少PageFault(缺页中断)的次数。Tips:TLB是缓存,TLB缓存虚拟内存地址和它们映射的物理内存地址。MMU先从TLB中查找内存映射关系,如果找到了,就不需要再回头找页表了。否则只能根据虚拟内存地址在页表中查找映射的物理内存地址。因为映射的内存页越大,需要的页表就越小(容易理解);页表越小,TLB故障越少。这种使用大于4KB的内存页作为内存映射单元的机制称为HugePages。目前,Linux中常用的HugePages大小有2MB和1GB。我们以一个2MB的内存页为例。映射更大的内存页,只需要增加偏移量部分,如图3所示:如图3所示,现在将偏移量部分扩展到21位(页表部分被覆盖,21位可以表示大小范围为0~2MB),所以页中间目录直接指向映射的物理内存页地址。这样就可以减少页表部分的内存消耗。由于内存映射关系较少,因此TLB未命中数也较少。3.HugePages的使用了解了HugePages的原理之后,我们来介绍一下HugePages的使用方法。HugePages的使用并不像普通的内存申请那么简单,需要借助Hugetlb文件系统来创建。下面将介绍HugetPages的使用步骤:1.挂载Hugetlb文件系统Hugetlb文件系统是专门为HugetPages创建的,我们可以使用如下命令挂载Hugetlb文件系统:$mkdir/mnt/huge$mountnone/mnt/huge-thugetlbfs执行上面的命令后,我们就在/mnt/huge目录下挂载了Hugetlb文件系统。2.声明可用HugePages的个数要使用HugePages,首先要向内核声明可用HugePages的个数。/proc/sys/vm/nr_hugepages文件保存了内核可以使用的HugePages的数量。我们可以使用下面的命令来设置新的可用HugePages的数量:$echo20>/proc/sys/vm/nr_hugepages上面的命令将可用HugePages的数量设置为20(即20个2MB的内存页)。3.编写申请HugePages的代码要使用HugePages,必须使用mmap系统调用将虚拟内存映射到Hugetlb文件系统中的文件,如下:#include
