Linux对内存的管理划分成三个层次,分别是Node、Zone、Page。对这三个层次简介如下:
层次 | 说明 |
Node(存储节点) | CPU被划分成多个节点,每个节点都有自己的一块内存,可以参考NUMA架构有关节点的介绍 |
Zone(管理区) | 每一个Node(节点)中的内存被划分成多个管理区域(Zone),用于表示不同范围的内存 |
Page(页面) | 每一个管理区又进一步被划分为多个页面,页面是内存管理中最基础的分配单位 |
它们之间的关系,用一张经典的图表示如下:图片来源
接下来我们重点讲述的是ZONE_HIGNMEM,也就是高端内存。
1 高端内存的由来
在32bit的x86机器中,4G的虚拟地址空间被划分成3G的用户空间(0—3G),1G的内核空间(3-4G)。在64bit的机器中于此不同。也就是说虚拟地址空间从0x0000 0000~0xBFFF FFFF为用户空间,0xC000 0000~0xFFFF FFFF为内核空间。Linux把每个内存节点的物理内存划分成3个管理区,也就是划分成ZONE_DMA、ZONE_NORMAL、ZONE_HIGHMEM。它们的介绍如下:
内存区域 | 说明 |
ZONE_DMA | 范围是0~16M,该区域的物理页面专门供I/O设备的DMA使用 |
ZONE_NORMAL | 范围是16~896M,该区域的物理页面是内核能够直接使用的 |
ZONE_HIGHMEM | 范围是896~结束,高端内存,内核不能直接使用 |
上面说到虚拟地址空间中的3~4G为Linux内核虚拟地址空间,其中内核空间3G~3G+896M对应物理内存空间的0~896M,并且在内核初始化时就已经将3G~3G+896M(0xC0000 0000~0xF7FF FFFF)虚拟地址空间与物理内存空间的0~896M进行了对应,内核在访问0~896M的内存的时候,只需要将其对应的虚拟地址空间增加一个偏移量就可以了。对于超过896M的物理地址空间,它们属于高端内存,高端内存区包含的内存页不能由内核直接访问,尽管它们也线性地映射到了线性地址空间的第4个G。也就是说对于高端内存区,只有128M的线性地址(0xF800 0000~0xFFFF FFFF)留给它进行映射。
有这样一个问题: