Linux 内核源码分析-物理内存组织形式
准备
内核版本: 4.20.1
在深入了解Linux物理内存管理之前,我们需要对物理内存的组织形式有一个初步的了解。Linux内核将物理内存简单的分为两部分: 用户物理内存空间和内核物理内存空间。当用户进程需要访问物理内存时,通过虚拟地址映射到用户的物理内存空间。这篇博客简单的介绍物理内存组织的相关概念和数据结构。
两种内存访问架构
UMA架构
将所有的物理内存以连续的方式组织起来。
NUMA架构
在多处理器计算机中,每个CPU都拥有本地内存,可以支持更快的访问速度,但CPU访问其他CPU的本地内存时,需要通过总线传输,从而速度慢些。
物理内存布局
在每一个进程看来,它是独占整个内存空间的,这是因为Linux采用了虚拟内存的技术来管理每一个进程的内存空间,但其实每个进程的使用的内存都能映射到不同的物理内存空间。虚拟内存的布局涉及代码段,数据段,堆栈等等,但这里我们讨论的是物理内存空间布局,即无关虚拟内存的抽象。
Linux 把物理内存划分为 3 个层次来管理: 存储节点(Node), 管理区(Zone)和页面(Page),并用 3 个相应的数据结构来描述, 在NUMA架构中一个Node就代表一个CPU直接访问的本地内存区域,而在非NUMA架构即UMA架构中,Node的个数为1.
上图为Node, Zone和Page的映射关系.
Zone的类型
物理内存被区分为以下几种常见的类型:
ZONE_DMA
: DMA的内存区域, 主要是各种设备驱动使用的内存区域.ZONE_DMA32
: 在x86_64
架构下,需要ZONE_DMA32
,因为需要32位地址寻址的DMA.ZONE_NORMAL
: 可以直接映射的普通内存区域.ZONE_HIGHMEM
: 在32 bit的架构中,ZONE_HIGHMEM
是需要的,因为32 bit的计算机最多只能映射2^32 即4GB的物理内存,假如计算机使用了更大的物理内存条,需要借助ZONE_HIGHMEM
来访问更大的内存区域.
x86的zone初始化
1 | void __init zone_sizes_init(void) |
x86_64物理内存布局
目前x86_64
支持的最大的寻址长度是48,即2^48 256TB的物理内存长度,所以暂时不需要ZONE_HIGHMEM
: