memory model
在 Linux 内核中支持3种内存模型,分别为:
- flat memory model(平坦内存模型)
- discontiguous memory model(不连续内存模型)
- sparse memory model(稀疏内存模型)
所谓 memory model(内存模型),其实就是从 CPU 的角度看其物理内存的分布情况,代表了在 Linux Kernel 中,使用什么的方式来管理这些物理内存(某些体系架构支持多种内存模型,但在内核编译构建时只能选择使用一种内存模型)
- 程序分段和 CPU 内存分段是不同的概念
在 include/asm-generic/memory_model.h
中,Linux 为每个 memory model 准备了如下的宏定义:
1 |
- 用于把虚拟内存中的
struct page
和切分后的物理内存page frame
关联起来
Flat memory model(平坦内存模型)
平坦内存模型是相对于多段模型而言的
- 8086实模式CPU的16位寄存器最多只能在一个内存段的64kb空间内寻址,要是超过64kb,它只能先变换段基址,来达到长距离取指的目的
- 平坦模型至始至终只有一个段,它能直接访问内存空间,不用再进行段基址的变换
1 |
图示:
- 对于 flat memory model 来说,物理内存本身是连续的
- 如果不连续的话,那么中间一部分物理地址是没有对应的物理内存,就会形成一个个洞,这就浪费了 mem_map 数组本身占用的内存空间
其特点如下:
- 内存连续且不存在空隙
- 通常应用于 UMA 系统(一致内存访问)
- 通过 CONFIG_FLATMEM 进行配置
Discontiguous memory model(不连续内存模型)
如果CPU在访问物理内存的时候,其地址空间是有一些空洞的,是不连续的,那么这种计算机系统的内存模型就是 discontiguous memory model
- discontiguous memory model 是为了 NUMA 系统设计的(非一致内存访问)
- NUMA 系统中每个 CPU 都有自己的本地内存,CPU 访问本地内存不用过总线,因而速度要快很多,每个 CPU 和内存在一起,称为一个 NUMA 节点
- NUMA 中的每个节点 Node 用一个 pglist_data 的结构体表示
1 |
图示:
- 由于每个 CPU 都有自己的本地内存,导致了物理内存必然有一些空洞
其特点如下:
- 多个内存节点不连续并且存在空隙
- 适用于 UMA 系统和 NUMA 系统
- 通过 CONFIG_CONTIGMEM 配置
随着 sparse memory model 的提出,这种内存模型也逐渐被弃用了(ARM在2010年已经移除了对 discontiguous memory model 的支持)
Sparse memory model(稀疏内存模型)
sparse memory model 是为了解决 discontiguous memory model 存在的弊端,而被提出的
- 连续的地址空间按照 section 被分成一段一段的,其中每一个 section 都是 Hotplug 的,因此内存地址空间可以被切分的更细,支持更离散的不连续内存
- 被管理的物理内存由一个个任意大小的 mem_section 构成,因此整个物理内存可被视为一个 mem_section 数组,每个 mem_section 包含了一个间接指向 page 数组的指针
1 |
图示:
其特点如下:
- 多个内存区域不连续并且存在空隙
- 以 section 为单位管理 online 和 hot-plug 内存
- 支持内存热插拔(hot plug memory),但性能稍逊色于 DISCONTIGMEM
- 在x86或ARM64内存采用该中模型,其性能比 DISCONTIGMEM 更优并且与 FLATMEM 相当
- 对于ARM64平台默认选择该内存模型
- 通过 CONFIG_SPARSEMEM 配置
平台内存模型支持
系统架构 | FLATMEM | DISCONTIGMEM | SPARSEMEM |
---|---|---|---|
ARM | 默认 | 不支持 | 某些系统可选配置 |
ARM64 | 不支持 | 不支持 | 默认 |
x86_32 | 默认 | 不支持 | 可配置 |
x86_32(NUMA) | 不支持 | 默认 | 可配置 |
x86_64 | 不支持 | 不支持 | 默认 |
x86_64(NUMA) | 不支持 | 不支持 | 默认 |
参考:linux内存模型)