首页/目录/全部文章

全部文章

八个专题的源码、算法与协议笔记都在这里。

笔记列表

反向映射机制与实现详解

反向映射机制与实现详解

源码路径rk3588/kernel-6.1/mm/rmap.cpage_vma_mapped.c
内核版本:Linux 6.1(RK3588)
文档目录linuxDoc/mm/


目录


一、原理

1.1 正向 vs 反向映射

方向 含义 典型用途
正向 虚拟地址 → PTE → 物理页 进程访问内存
反向 物理页 → 所有映射它的 PTE 回收、迁移、写回、解除映射

无 rmap 时,内核无法知道某 物理页 还被哪些进程映射,不能安全回收或迁移。

1.2 两类映射

匿名页(堆、栈、匿名 mmap):

  • 通过 anon_vma / anon_vma_chain 挂到相关 VMA
  • fork 后树状共享 anon_vma

文件页(page cache):

  • 通过 address_space->i_mmap(interval tree)记录所有 mmap 该文件的 VMA
  • 每个 VMA 内再用页表遍历

1.3 锁顺序

rmap.c 文件头定义 MM 全局 锁顺序(mmap_lock → inode/i_mmap → page lock → anon_vma → pte lock → lru_lock)。违反易死锁。


二、实现方式

2.1 遍历映射:page_vma_mapped_walk

page_vma_mapped.c 提供 page_vma_mapped_walk

  • 在指定 VMA 的页表范围内查找 指向目标 pfn 的 PTE
  • 支持 THP、PMD 映射等层级

rmap 中 try_to_unmap_onepage_mkclean 等均依赖此 walker。

2.2 匿名 VMA 建立

  • anon_vma_prepare / __anon_vma_prepare:首次映射匿名页时创建 anon_vma
  • anon_vma_fork:fork 复制/合并 anon_vma 树
  • anon_vma_init:启动期初始化 slab cache

2.3 解除映射:try_to_unmap

回收路径调用 try_to_unmap(folio, flags)

  • 文件页:遍历 mapping->i_mmap 中 VMA
  • 匿名页:遍历 folio_anon_vma(folio)
  • 对每个 VMA 调用 try_to_unmap_one
1
2
3
4
5
static bool try_to_unmap_one(struct folio *folio, struct vm_area_struct *vma,
// ...
while (page_vma_mapped_walk(&pvmw)) {
// 清除 PTE 或换出
}

flags 含 TTU_IGNORE_MNUTTU_BATCH_FLUSH 等。

2.4 写回与 COW 辅助

函数 作用
page_mkclean 清除 PTE 写位,用于文件页回收前写回
try_to_migrate 迁移专用 unmap
page_referenced 检查 PTE young 位,供回收参考

2.5 TLB flush

unmap 后通过 flush_tlb_batched_pending / mmu_notifier 通知架构刷新 TLB。


三、关键数据结构与接口

结构/接口 说明
struct anon_vma 匿名页反向映射根
struct anon_vma_chain VMA 与 anon_vma 关联
struct address_space.i_mmap 文件 mmap 区间树
try_to_unmap 回收 unmap
page_vma_mapped_walk PTE 遍历器

四、与其它子系统协作

vmscan shrink_page_listtry_to_unmaprmap.c页表清除 PTEmigrate / 释放 foliotruncate_inode_pagesmemory_failure
  • 07 回收:必须先 unmap 才能释放 file/anon 页
  • 09 CMA / migratemigrate_pages 需 rmap 协助
  • 04 缺页:建立映射时注册 anon_vma / i_mmap

五、调试与观测

  • 死锁排查:对照 rmap.c 锁顺序与持有锁的栈
  • CONFIG_DEBUG_VM_RB 等选项可校验 interval tree

附录:源码索引

主题 文件 约略行号
try_to_unmap_one rmap.c 1470
anon_vma_init rmap.c 459
page_vma_mapped_walk page_vma_mapped.c 全文

内存回收与压缩机制与实现详解

内存回收与压缩机制与实现详解

源码路径rk3588/kernel-6.1/mm/vmscan.cworkingset.ccompaction.cvmpressure.c
内核版本:Linux 6.1(RK3588)
文档目录linuxDoc/mm/


目录


一、原理

1.1 为什么需要回收

空闲页低于水位线__alloc_pages 无法从 buddy 取页,必须 回收 已占用的 cache 或可换出匿名页,归还 buddy。

两种路径:

类型 触发 执行上下文
后台回收 free ≤ low kswapd 内核线程
直接回收 free ≤ min,分配慢路径 分配者上下文同步

1.2 LRU 分类

每 zone 的 lruvec 维护链表:

  • active / inactive × file / anon
  • 访问会 activate;长时间未访问在 inactive 上被扫描
  • swappiness(0–100):倾向回收 anon(换出)还是 file(丢 cache)

1.3 Working Set

workingset 区分「常被重用的 cache」与「一次性 cache」,通过 refault 距离调整回收积极性,减少 thrashing。

1.4 压缩(Compaction)

外部碎片:总空闲足够但无连续物理块。compaction 迁移可移动页,拼凑高 order 空闲块,服务于 CMA、THP、大块 DMA


二、实现方式

2.1 kswapd 与 balance_pgdat

每个 node 有 kswapd 线程,核心 balance_pgdat(pgdat, order, highest_zoneidx)(vmscan.c ~7021):

1
2
3
4
5
6
7
8
9
static int balance_pgdat(pg_data_t *pgdat, int order, int highest_zoneidx)
{
struct scan_control sc = { .gfp_mask = GFP_KERNEL, .order = order, ... };
sc.priority = DEF_PRIORITY;
do {
// shrink_zones / shrink_node
// 直到 zone 达到 balance 或 priority 用尽
} while (...);
}
  • scan_control:本次扫描的 gfp 掩码、order、是否允许 unmap/swap、target memcg 等
  • priority:从 12 递减,扫描强度递增

2.2 shrink 链路

1
2
3
4
5
6
7
shrink_node
└─ shrink_zones
└─ shrink_lruvec
└─ shrink_list (active/inactive)
└─ shrink_page_list
├─ 文件页:try_to_unmap → 若脏则 writeback → 释放
└─ 匿名页:swap_out 或释放(若已 unmapped)

2.3 direct reclaim

__alloc_pages_slowpath__perform_reclaim → 同样使用 scan_control,在调用进程上下文执行,可能显著增加延迟。

2.4 workingset.c

  • workingset_refault:页被回收后再次 fault
  • eviction_lru / shadow entries:估计 active/inactive 比例
  • memcg 层级统计协同

2.5 compaction.c

compact_zone / try_to_compact_pages

  1. isolate:从 zone 尾部 isolate 可迁移空闲页
  2. migratemigrate_pages 将可移动页搬到新位置(依赖 06 rmap)
  3. free:合并目标区域为大块

同步触发:高 order 分配失败且 __GFP_COMP 等条件允许。

2.6 vmpressure.c

memcg 或 userspace(eventfd)报告 low/medium/critical 压力,供 Android/lmkd 类策略使用。

2.7 PSI(Pressure Stall Information)

vmscan 与分配路径调用 psi_memstall_enter/leave,统计因内存等待的 CPU 停滞时间(/proc/pressure/memory)。


三、关键数据结构与接口

符号 说明
struct scan_control 一次回收扫描参数
balance_pgdat node 级回收
shrink_page_list 处理一批 LRU 页
try_to_compact_pages 分配慢路径压缩
lru_add_drain 将 per-cpu LRU 批提交到 lruvec

四、RK3588 平台说明

  • 多路 YPC 编码:匿名堆 + 媒体 buffer 压力上升 → kswapd 活跃、pgscan_* 计数增加。
  • vm.swappiness:嵌入式常偏低,减少 swap I/O,更倾向丢 file cache。
  • CMA 分配失败 时查看是否需 手动触发 compact 或增大 CMA 预留(09 文档)。
  • schedutil 无直接调用;回收占用 CPU 会影响调度负载观测。

五、调试与观测

接口 字段示例
/proc/vmstat pgscan_kswapd, pgsteal_*, compact_*
/proc/meminfo Active(file), Inactive(anon)
/proc/pressure/memory some/full avg10

附录:源码索引

主题 文件 约略行号
balance_pgdat vmscan.c 7021
compaction compaction.c 全文
workingset workingset.c 全文

OOM 机制与实现详解

OOM 机制与实现详解

源码路径rk3588/kernel-6.1/mm/oom_kill.c
内核版本:Linux 6.1(RK3588)
文档目录linuxDoc/mm/


目录


一、原理

1.1 何时触发 OOM

__alloc_pages 慢路径 在以下手段后仍失败:

  • direct reclaim
  • compaction
  • (可能)多次重试

则调用 __alloc_pages_may_oom()out_of_memory()

OOM 不是「物理 RAM 为 0」,而是 在给定 gfp/zone/cpuset 约束下无法满足分配

1.2 设计目标

在系统崩溃与随机杀进程之间,选择 oom_score 最高的进程终止,释放其 RSS + 页表 + 缓存引用,使后续分配成功。

1.3 与回收的区别

机制 行为
reclaim 回收 可丢弃 的 cache 或 swap 匿名页
OOM 终止 整个进程,回收其独占匿名页等

二、实现方式

2.1 入口:out_of_memory()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
bool out_of_memory(struct oom_control *oc)
{
if (oom_killer_disabled)
return false;
// notifier 可能释放内存
if (task_will_free_mem(current)) {
mark_oom_victim(current);
queue_oom_reaper(current);
return true;
}
// GFP_NOFS 等约束可能跳过全局 OOM
oc->constraint = constrained_alloc(oc);
check_panic_on_oom(oc);
// sysctl: oom_kill_allocating_task
select_bad_process(oc);
oom_kill_process(oc, ...);
return !!oc->chosen;
}

2.2 struct oom_control

记录本次 OOM 上下文:

  • gfp_maskorderzonelist
  • memcg(若为 cgroup OOM)
  • chosen:选中 victim
  • constraint:NUMA / cpuset / policy 限制

2.3 选择 victim:select_bad_process

遍历进程(for_each_process 或 memcg 子树):

  • 计算 oom_badness:RSS、swap、调度类、硬件损坏等
  • 加上 oom_score_adj/proc/<pid>/oom_score_adj,-1000 永不杀)
  • 跳过 内核线程PF_KTHREADOOM_SCORE_ADJ_MIN

2.4 杀进程:oom_kill_process

  1. mark_oom_victim:设置 TIF_MEMDIE
  2. 发送 SIGKILL(或依赖 oom reaper)
  3. oom_reaper 内核线程加速释放 victim 的 mm(unmap、释放页)

2.5 分配进程优先退出

若当前进程 task_will_free_mem(已有 SIGKILL、正在 exit),直接选为 victim,便于 快速释放 而不搜全局。

2.6 pagefault OOM

pagefault_out_of_memory():缺页路径无 gfp 上下文,主要处理 memcg OOM;全局 OOM 仍由分配上下文触发。

2.7 panic 路径

  • panic_on_oom:OOM 时内核 panic
  • 无可杀进程:panic("System is deadlocked on memory")

三、关键数据结构与接口

接口 说明
out_of_memory 全局/约束 OOM 入口
register_oom_notifier 第三方在杀进程前尝试释放内存
oom_killer_disable/enable 暂停 OOM(危险)
/proc/<pid>/oom_score 只读分数

四、memcg OOM 与全局 OOM

类型 范围 典型场景
全局 OOM 全系统 物理内存耗尽
memcg OOM 超过 cgroup limit 容器/Android 应用组

memcg 路径 mem_cgroup_out_of_memory → 仍调用 out_of_memoryis_memcg_oom(oc) 为真,仅杀组内进程。


五、RK3588 平台说明

  • 编码服务 + 多客户端:建议用 memcg 限制单应用,避免一次全局 OOM 杀掉编码守护进程。
  • lmkd(Android)根据 adj 与 vmpressure 杀应用,与内核 OOM 互补。
  • oom_score_adj 保护关键进程(如 mediaserver、自定义编码器)。

六、调试与观测

手段 说明
dmesg Out of memory: Kill process ...
/proc/<pid>/oom_score_adj 调整优先级
sysctl vm.panic_on_oom 2=panic
sysctl vm.oom_kill_allocating_task 杀当前分配者

附录:源码索引

主题 文件 约略行号
out_of_memory oom_kill.c 1106
oom_badness oom_kill.c 搜索 select_bad
pagefault OOM oom_kill.c 1185

CMA 连续内存机制与实现详解

CMA 连续内存机制与实现详解

源码路径rk3588/kernel-6.1/mm/cma.ccma.hcma_debug.ccma_sysfs.c
内核版本:Linux 6.1(RK3588)
文档目录linuxDoc/mm/


目录


一、原理

1.1 问题背景

DMA、摄像头、显示、VPU 等硬件常要求 物理地址连续 的缓冲区。伙伴分配器在高 order 或碎片化严重时难以提供大块连续物理页。

1.2 CMA 思路

在启动早期 预留 一片物理连续区域:

  • 平时:页作为 MIGRATE_CMA 类型进入 buddy,可被 可迁移 的普通分配使用
  • 驱动需要时:从 CMA 池分配,通过 迁移(compaction) 腾出连续物理块并 pin

兼顾 系统内存利用率驱动连续内存需求

1.3 与 reserved-memory 区别

机制 平时是否进 buddy 用途
memblock reserve 固件/驱动私有,内核不管理
CMA 是(可迁移页) 动态借出,需要时收回

DT 中 linux,cma 与独立 reserved-memory 可并存。


二、实现方式

2.1 初始化

  1. DT / cma= 启动参数指定区域名、大小、对齐
  2. cma_init_reserved_memblock() 在 memblock 阶段 reserve
  3. cma_init_reserved_areas():buddy 初始化后,将区域页标为 MIGRATE_CMA,建立 bitmap 跟踪 CMA 内分配

struct cma 字段:base_pfncountbitmapnameorder_per_bit

2.2 分配:cma_alloc()

1
2
3
4
5
6
7
8
9
struct page *cma_alloc(struct cma *cma, unsigned long count,
unsigned int align, bool no_warn)
{
// bitmap_find_next_zero_area_off 找连续空闲位
bitmap_set(...);
pfn = cma->base_pfn + (bitmap_no << cma->order_per_bit);
ret = alloc_contig_range(pfn, pfn + count, MIGRATE_CMA, GFP_KERNEL);
// 失败则 cma_clear_bitmap 并重试
}

要点:

  • bitmap 防止重复分配同一段
  • alloc_contig_rangecompaction.c):isolate + migrate 腾出 [pfn, pfn+count)
  • 失败 -EBUSY 时换偏移重试

2.3 释放:cma_release()

清除 bitmap,free_contig_range 将页归还 CMA migratetype 的 buddy。

2.4 驱动 API

API 说明
dma_alloc_from_contiguous DMA 框架封装
cma_alloc / cma_release 内核直接调用
devm_cma_alloc 设备 managed

2.5 与 page_alloc 协作

  • 普通 GFP 不应长期占用 CMA 页;is_migrate_cma() 检查
  • NR_FREE_CMA_PAGES 在 vmstat 中统计
  • 分配 CMA 时可能触发 全局 compact

三、关键数据结构与接口

符号 说明
cma_areas[] 全局 CMA 区域数组
cma_get_base/size/name 查询接口
cma_alloc / cma_release 分配释放
alloc_contig_range 底层连续化(compaction.c)

四、RK3588 平台说明

4.1 典型配置

  • defconfig CONFIG_CMA=y
  • DT reserved-memorylinux,cma 默认池
  • 显示/ISP/VPU 可能还有 命名 CMA 或固定 reserve

4.2 编解码场景

  • drm_gem_cmavb2 dma-contig 等从 CMA 取 buffer
  • 多路编码同时分配大块 → CmaFree 下降、compact 频繁 → 延迟抖动
  • 排查:/proc/meminfoCmaTotal/CmaAllocated/CmaFree

4.3 失败处理

  • 增大 DT CMA 或 cma=512M 等启动参数
  • 减少用户态 hoarding dmabuf
  • 检查是否有驱动泄漏未 cma_release

五、调试与观测

手段 说明
/proc/meminfo Cma* 行
CONFIG_CMA_DEBUGFS debugfs 位图
CONFIG_CMA_SYSFS /sys/kernel/mm/cma/
trace trace/events/cma.h

附录:源码索引

主题 文件 约略行号
cma_alloc cma.c 438
cma 初始化 cma.c 搜索 init_reserved

交换与 Zswap 机制与实现详解

交换与 Zswap 机制与实现详解

源码路径rk3588/kernel-6.1/mm/swap.cswapfile.cswap_state.cswap_slots.cpage_io.czswap.cfrontswap.c
内核版本:Linux 6.1(RK3588)
文档目录linuxDoc/mm/


目录


一、原理

1.1 Swap 的作用

物理内存不足,回收器可将 匿名页 内容写到 swap 设备/文件,释放物理页给其它用途;再次访问时 缺页 从 swap 读回(do_swap_page)。

文件页通常 直接丢弃 page cache(可从磁盘重读),匿名页无后备存储,必须 swap 或保留。

1.2 Swap 与 swappiness

vm.swappiness(0–100)控制回收时 匿名页 vs 文件页 比例:

  • 高:更积极 swap 匿名页
  • 低:优先丢 file cache

1.3 Zswap

在页写入块设备 之前,尝试 压缩 到 RAM 池(zpool);命中时避免慢速 eMMC/UFS I/O,未命中再写 swap。

1.4 Frontswap

抽象层,允许 zswap 等后端挂在 swap 路径前;frontswap.c 提供注册接口。


二、实现方式

2.1 换出路径(回收)

vmscan.c shrink_page_list 对匿名页:

  1. add_to_swap:分配 swap slot,页标 SWAP_TYPE
  2. try_to_unmap(06 文档)
  3. swap_writepage / __swap_writepage:写 page_io.c 提交 bio
  4. 成功后页可从 LRU 移除并释放物理帧

2.2 换入路径(缺页)

memory.c do_swap_page

  1. 根据 PTE swap entry 找 swap_info_struct
  2. read_swap_cache_async 或同步读
  3. 安装有效 PTE,更新 RSS

2.3 swap 子文件分工

文件 职责
swap.c 全局 swap 锁、类型、统计、swap_setup
swapfile.c swapon/swapoff、swap 区注册
swap_state.c swap cache(类似 address_space)
swap_slots.c slot 分配/释放
page_io.c 实际 I/O 完成回调

2.4 swap_setup

swap.c swap_setup() 启动时解析 swap= 等,初始化 swap 链表。

2.5 zswap.c

  • 注册 frontswap 操作
  • 压缩算法(lzo/lz4/zstd 等,Kconfig 选择)
  • 内存池 zpoolzpool.c + zbud/zsmalloc 后端)
  • 压缩失败或池满则 fallback 到真实 swap

2.6 swap_cgroup.c

CONFIG_MEMCG + CONFIG_SWAP:按 cgroup 计 swap 使用量。


三、关键数据结构与接口

结构/接口 说明
swp_entry_t PTE 中编码的 swap 位置
struct swap_info_struct 每个 swap 设备/文件
get_swap_page 分配 slot
swap_readpage / swap_writepage I/O
zswap_store/load 压缩存取

四、RK3588 平台说明

  • 嵌入式产品 常关闭 swap 分区 或仅 zram,避免 eMMC 磨损与延迟。
  • 无 swap:匿名页回收只能靠释放或 OOMswappiness 无效。
  • zram + zswap 组合在部分 Android/RK 镜像中出现,需看具体 defconfig。
  • 编解码大匿名分配 + 无 swap → OOM 风险上升,依赖 memcg 与 cache 回收。

五、调试与观测

手段 说明
/proc/swaps 已启用 swap
/proc/meminfo SwapTotal/Free/Cached
swapon -s 用户态查看
sysctl vm.swappiness 调整策略

附录:源码索引

主题 文件
swap 核心 swap.c
swapon swapfile.c
zswap zswap.c
swap in fault memory.c (do_swap_page)

cgroup 内存控制机制与实现详解

cgroup 内存控制机制与实现详解

源码路径rk3588/kernel-6.1/mm/memcontrol.cvmpressure.cmempolicy.cpage_counter.cswap_cgroup.c
内核版本:Linux 6.1(RK3588)
文档目录linuxDoc/mm/


目录


一、原理

1.1 cgroup v2 内存控制器

memcg 将进程的 RSS、cache、swap、kernel 内存 计入对应 cgroup,支持:

  • limit:硬上限,超限触发 reclaim 或 OOM
  • high/max:分层压力与上限
  • 统计memory.currentmemory.stat
  • 继承:子 cgroup 受父级约束

1.2 与全局 MM 的关系

分配页时若设置了 __GFP_ACCOUNT,在 __alloc_pages 返回后调用 __memcg_kmem_charge_page;匿名 fault、cache charge 亦挂钩。

回收时 scan_control 可带 target memcg,优先回收该组页。

1.3 NUMA policy(可选)

mempolicy.cmbindset_mempolicy、MPOL_BIND/INTERLEAVE 等,约束分配 node(RK3588 UMA 场景较少用)。

1.4 vmpressure

vmpressure.c 监测 cgroup 或全局的 回收效率,上报 low/medium/critical,供用户态 lmkd 等决策。


二、实现方式

2.1 核心结构 memcontrol.c

组件 说明
struct mem_cgroup 计数器、层级、OOM 状态
page_counter 可层次化的字节计数(page_counter.c
mem_cgroup_charge 页/account 到 memcg
try_charge 分配前检查是否超限
mem_cgroup_reclaim 组内 direct reclaim

2.2 charge 路径

  1. mem_cgroup_charge / mem_cgroup_charge_skmem
  2. 超限 → drain_all_stock / reclaim → 仍失败 → memcg OOM
  3. cancel_charge 在释放时回退

2.3 kmem accounting

memcg_kmem_enabled() 时 slab 对象可计入 memory.kmem__memcg_kmem_charge_page__alloc_pages 尾路径)。

2.4 OOM

mem_cgroup_out_of_memoryout_of_memoryis_memcg_oom,仅杀该 cgroup 内进程(见 08 文档)。

2.5 swap_cgroup.c

swap 页计入 memory.swap,与 limit 协同。

2.6 list_lru 与 memcg

list_lru.c 提供 per-memcg LRU(inode、dentry 等),文件缓存可按组回收。

2.7 memory-tiers.c(NUMA)

CONFIG_NUMA,内存分层与 tier 统计;RK3588 单 node 通常不启用热路径。


三、关键数据结构与接口

接口 说明
mem_cgroup_charge 页 charge
get_mem_cgroup_from_mm 从 mm 取 memcg
cgroup_file memory.max/current cgroupfs
mem_cgroup_try_charge 预检查

cgroup v2 挂载/sys/fs/cgroup(unified hierarchy)。


四、RK3588 平台说明

  • Android:应用 cgroup 由 lmkd/init 配置,memory.min/low/high 影响杀进程策略。
  • 编码服务:可为客户端进程设 memory.max,防止单路拉垮整机。
  • PSI + vmpressure:与 07 文档 PSI 结合,做自适应限流。

五、调试与观测

路径 内容
memory.current 当前用量
memory.stat anon/file/kernel 分项
memory.events oom、max 等事件
memory.pressure pressure 接口(若启用)

附录:源码索引

主题 文件
memcg 核心 memcontrol.c
page_counter page_counter.c
vmpressure vmpressure.c
mempolicy mempolicy.c

扩展内存机制与实现详解

扩展内存机制与实现详解

源码路径rk3588/kernel-6.1/mm/vmalloc.cgup.cmigrate.chugetlb.chuge_memory.cshmem.cmemfd.cksm.cuserfaultfd.chmm.cdamon/
内核版本:Linux 6.1(RK3588)
文档目录linuxDoc/mm/


目录


一、原理

除核心「页分配 + VMA + page cache + 回收」外,MM 还提供多种 专用内存机制,分别解决:

需求 机制
内核大块虚拟连续 vmalloc
固定用户页供 DMA GUP
页迁移 / 热插拔 migrate
大页 / TLB 优化 hugetlb / THP
共享匿名 / tmpfs shmem
密封匿名 fd memfd
同内容合并 KSM
用户态缺页 userfaultfd
设备内存镜像 HMM
访问模式监控 DAMON

二、实现方式

2.1 vmalloc(vmalloc.c)

  • VMALLOC_STARTVMALLOC_END 虚拟范围分配 连续虚拟地址
  • 物理页逐页 alloc_page,通过 vmalloc 页表 映射
  • 用于模块加载、大缓冲区、vmap
  • vmalloc_init 建立 vmap_area 红黑树/链表管理

2.2 GUP(gup.c)

get_user_pages / pin_user_pages

  • 遍历用户 PTE,将页 pin 住(增加 ref),供 RDMA、VFIO、io_uring、drm 等 DMA
  • FOLL_* 标志:写、force、longterm 等
  • mmu_notifier 协同(设备 unmap 通知)

2.3 migrate(migrate.c)

migrate_pages / unmap_and_move

  • 将 folio 从一组 PFN 搬到新 PFN
  • 更新 rmap PTE,flush TLB
  • 用于 NUMA balancingmemory hotplugCMA/compactionmemory failure

2.4 hugetlb(hugetlb.c)

  • 启动预留或运行时从 buddy 分配 大页池(如 2MB)
  • hugetlbfs 文件系统 mmap 使用固定大页
  • hugetlb_cgroup.c 限制大页使用

2.5 透明大页 THP(huge_memory.c + khugepaged.c)

  • khugepaged 内核线程:扫描匿名 VMA,合并为 PMD 大页
  • fault 路径 create_huge_pmd(04 文档)
  • sysfs /sys/kernel/mm/transparent_hugepage

2.6 shmem(shmem.c)

  • tmpfsashmemmemfd 底层
  • 基于 shmemfs 的 page cache + swap 支持
  • shmem_mmap、写时复制、锁页

2.7 memfd(memfd.c)

  • memfd_create:匿名 sealed 内存 fd
  • 与 shmem 集成,Android 共享内存常用

2.8 KSM(ksm.c)

  • 扫描匿名页内容,合并相同页 为一份只读共享
  • 写时拆分;虚拟机去重场景多,嵌入式较少开

2.9 userfaultfd(userfaultfd.c)

  • 用户注册 缺页 / 迁移 处理
  • QEMU live migration、用户态 pager

2.10 HMM(hmm.c)

  • GPU 等设备与进程地址空间 镜像、迁移设备页

2.11 DAMON(damon/)

  • 监控访问频率,模块可做 reclaimlru_sort 等策略实验

2.12 其它

文件 说明
memory_hotplug.c 内存热插拔
memory-failure.c 硬件错误页隔离
secretmem.c 加密内存(若启用)
memremap.c ZONE_DEVICE 持久内存

三、各机制对照表

机制 CONFIG 主要 API
vmalloc 内置 vmalloc, vfree
GUP 内置 get_user_pages
migrate CONFIG_MIGRATION migrate_pages
hugetlb CONFIG_HUGETLBFS hugetlb_alloc
THP CONFIG_TRANSPARENT_HUGEPAGE khugepaged
shmem 内置 shmemfs
memfd CONFIG_MEMFD_CREATE memfd_create
KSM CONFIG_KSM ksmd
userfaultfd CONFIG_USERFAULTFD userfaultfd
HMM CONFIG_HMM_MIRROR hmm API
DAMON CONFIG_DAMON debugfs/sysfs

四、RK3588 平台说明

机制 RK 相关性
GUP / dmabuf 编解码 buffer 与用户空间共享
CMA + migrate 09/07 文档,大块 buffer
THP 可选,匿名大堆可能降 TLB miss
shmem/memfd Android 图形 buffer、共享内存
hugetlb 一般不用,除非专用性能调优
KSM 嵌入式少见
DAMON 调试/研究用途

五、调试与观测

机制 观测
THP /sys/kernel/mm/transparent_hugepage/enabled
hugetlb /proc/meminfo HugePages_*
KSM /sys/kernel/mm/ksm/*
DAMON CONFIG_DAMON debugfs

附录:源码索引

主题 文件
vmalloc vmalloc.c
GUP gup.c
migrate migrate.c
hugetlb hugetlb.c
THP huge_memory.c, khugepaged.c
shmem shmem.c
memfd memfd.c

mm/ 内存管理机制与原理详解

mm/ 内存管理机制与原理详解

源码路径rk3588/kernel-6.1/mm/
内核版本:Linux 6.1(RK3588 平台)
平台:RK3588(ARM64,典型配置含 CMA、DMA32、无 highmem)
文档目录linuxDoc/mm/

该目录实现 Linux 6.1 的 内存管理(Memory Management, MM)子系统,涵盖从引导期物理内存描述、伙伴页分配、SLUB 小对象分配、虚拟地址空间与缺页、页缓存与写回、反向映射与回收,到 OOM、CMA、cgroup 限流等完整链路。目录内 无 Rockchip 专有补丁;RK3588 相关内存布局与预留通常在设备树、arch/arm64/ 及驱动中配置。


目录

延伸阅读


一、子系统职责与架构

1.1 分层模型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
┌─────────────────────────────────────────────────────────────┐
│ 用户态:mmap / brk / madvise / mincore / userfaultfd │
├─────────────────────────────────────────────────────────────┤
│ 虚拟内存:VMA、页表、缺页、COW、mprotect、mremap │
│ memory.c, mmap.c, mprotect.c, mremap.c │
├─────────────────────────────────────────────────────────────┤
│ 页缓存 / 写回:filemap、readahead、writeback │
│ filemap.c, readahead.c, page-writeback.c │
├─────────────────────────────────────────────────────────────┤
│ 反向映射 + 回收:rmap、LRU、kswapd、compaction │
│ rmap.c, vmscan.c, compaction.c, workingset.c │
├─────────────────────────────────────────────────────────────┤
│ 物理页:伙伴分配器、zone、水位线、per-CPU 页列表 │
│ page_alloc.c, mmzone.c, vmstat.c │
├─────────────────────────────────────────────────────────────┤
│ 小对象:SLUB / SLAB / kmalloc │
│ slub.c, slab_common.c │
├─────────────────────────────────────────────────────────────┤
│ 引导期:memblock → sparse → buddy │
│ memblock.c, sparse.c, page_alloc.c │
└─────────────────────────────────────────────────────────────┘

1.2 核心抽象(Linux 6.1)

抽象 说明
struct page / folio 物理页描述;6.1 逐步以 folio 作为页缓存与部分 MM 路径的中心
pg_data_t / node NUMA 节点;UMA 系统通常仅 node 0
struct zone 每个 node 内按寻址/用途划分的内存池(Normal、DMA32、CMA 等)
struct mm_struct 进程地址空间
struct vm_area_struct 虚拟内存区域(VMA)
struct address_space 文件/inode 的页缓存索引
gfp_t 分配标志(原子、IO、FS、高阶、NUMA 等)

二、源码目录与编译结构

2.1 规模

mm/176 个文件(含 kasan/kfence/damon/ 等子目录),是内核中最大子系统之一。

2.2 Makefile 核心划分

始终编入内核(obj-y) 包括:page_alloc.cmemblock.cfilemap.cvmscan.cslub 公共部分等。

MMU 相关(CONFIG_MMU) 在 RK3588 ARM64 上必开,额外链接:

  • memory.c, mmap.c, rmap.c, vmalloc.c, mprotect.c, mremap.c

常见 RK 产品 defconfig 可选项

  • CONFIG_CMA → 多媒体 / GPU 连续 DMA 内存
  • CONFIG_SLUB → 默认 slab
  • CONFIG_MEMCG → cgroup 内存限制
  • CONFIG_TRANSPARENT_HUGEPAGE → 透明大页(可选)

完整文件列表见 源码文件与模块索引.md

2.3 internal.h

internal.h 定义 MM 子系统内部接口与 GFP 约束,例如:

  • GFP_RECLAIM_MASK:影响水位与回收行为的标志子集
  • GFP_BOOT_MASK:早期引导可用标志
  • folio 相关 inline、写回记账、unmap 辅助声明

驱动与通用内核代码应使用 <linux/mm.h><linux/gfp.h> 等公开头文件,而非直接依赖 internal.h


三、启动期内存初始化

3.1 流程概览

架构 setup_archmemblock 记录物理内存与保留区sparse_init 建立 pfn ↔ pagefree_area_init 初始化各 zonepage_alloc_init buddy 与 per-CPU 列表kmem_cache_init SLUBinit_mm / 用户进程可用

3.2 memblock.c

memblock 在 buddy 与 slab 就绪前管理内存:

集合类型 含义
memory 内核可见物理内存(可被 mem= 限制)
reserved 已保留区域(内核镜像、DTB、initrd、CMA 预留等)
physmem 部分架构上的实际物理内存视图

典型 API:

  • memblock_add() / memblock_add_node():登记可用内存
  • memblock_reserve():标记保留
  • 引导末期:memblock_free_all() 将可用内存交给伙伴系统

RK3588arch/arm64/ 与设备树解析在引导早期调用 memblock;reserved-memory 节点对应的区域在此阶段被 reserve。

3.3 sparse.c

CONFIG_SPARSEMEM 下,物理内存按 section 稀疏建模,避免为空洞内存分配 struct page 数组。CONFIG_SPARSEMEM_VMEMMAP 可用虚拟 vmemmap 降低元数据开销。

3.4 init-mm.c

定义全局 init_mm(内核 swapper 页表),mm_users/mm_count 初始化,供内核线程与早期映射使用。

3.5 mm_init.c

提供启动后 校验与调试(如 CONFIG_DEBUG_MEMORY_INIT 下的 zonelist 打印、pageflags 布局检查),不参与运行时分配热路径。


四、物理页分配(伙伴系统)

详细原理与实现见 02-物理页分配机制与实现详解.md

4.1 核心文件

page_alloc.c(约 9800+ 行)— 空闲页管理中枢;注释说明 kmalloc 在 slab 中,页级分配在此文件。

4.2 伙伴算法与 order

  • 物理页以 2^order 个连续页 为块管理(order 0 = 单页,order 9 = 512 页块等)。
  • 分配时从合适 order 的 free_list 取块;若无则向更高 order 分裂。
  • 释放时尝试与 buddy 合并,降低 外部碎片

4.3 Zone 与 ARM64

Zone ARM64 典型用途
ZONE_DMA32 32 位 DMA 可寻址物理内存
ZONE_NORMAL 主要可分配内存
CMA 区域 落在某 zone 内,页带 PageCMA 属性,仅供 CMA 分配

RK3588 无 ZONE_HIGHMEM(64 位线性映射足够),highmem.c 一般不参与实际路径。

4.4 关键入口

1
2
struct page *__alloc_pages(gfp_t gfp, unsigned int order,
int preferred_nid, nodemask_t *nodemask);
  • 慢路径:内存不足时触发 direct reclaim、compaction,仍失败则可能 OOM
  • per-CPU 页列表:减少锁竞争,bulk 分配/释放优化(见文件头历史注释)。

4.5 水位线(watermark)

每个 zone 有 min / low / high

  • 低于 low:唤醒 kswapd 后台回收
  • 低于 min:分配器在 __alloc_pages 中同步回收(direct reclaim)
  • min 以下仍无法满足 → 可能进入 OOM

统计项见 vmstat.c(如 NR_FREE_PAGESNR_FREE_CMA_PAGES)。

4.6 GFP 标志(常用)

标志 含义
GFP_KERNEL 可睡眠,普通内核上下文
GFP_ATOMIC 不可睡眠(中断/持有锁)
__GFP_HIGHMEM 高端 zone(ARM64 通常无关)
__GFP_DMA32 从 DMA32 zone 分配
__GFP_MOVABLE 可迁移页,利于 compaction
__GFP_NOFAIL 尽力保证成功(慎用)

五、小对象分配(SLUB)

5.1 实现

RK3588 内核通常 CONFIG_SLUB=y

  • slub.c:per-CPU slab、per-node partial 列表,减少锁与 cache line 抖动
  • slab_common.c:cache 创建、kmalloc 类型表、引导期 create_boot_cache

5.2 与页分配器关系

SLUB 向 __alloc_pages 申请 slab 页(order 由 kmem_cacheoo 决定),再在 slab 内切分对象。

5.3 启动顺序

1
2
kmem_cache_init()        // 早期,依赖 memblock 页
kmem_cache_init_late() // 更完整 cache 集

5.4 调试子系统(可选)

组件 目录/文件 作用
KASAN kasan/ 越界、use-after-free
KFENCE kfence/ 低开销采样检测
KMSAN kmsan/ 未初始化使用
kmemleak kmemleak.c 泄漏扫描

六、虚拟内存与缺页

6.1 mmap.c

处理用户 mmap / munmap / brk

  • 创建/合并/拆分 VMAvm_area_struct
  • 与文件 vm_ops、匿名映射、MAP_SHARED/MAP_PRIVATE 等语义
  • Linux 6.1 中 VMA 管理逐步使用 maple tree(见 init-mm.cmm_mt

6.2 memory.c

缺页异常与页表操作核心:

  • handle_mm_fault() → 根据 VMA 类型分发
  • 匿名页do_anonymous_page(),可能 COW(do_wp_page()
  • 文件页:常与 filemap.c 协作
  • swapdo_swap_page() 从 swap 读入
  • THP:与 huge_memory.c 协作(若开启)

6.3 相关系统调用文件

文件 功能
mprotect.c 修改 VMA 权限
mremap.c 重映射虚拟地址
mlock.c 锁定物理页
madvise.c MADV_* 建议(丢弃、大页、顺序访问等)
mincore.c 查询页是否在内存中
msync.c 映射区与存储同步

6.4 vmalloc.c

vmalloc:内核虚拟地址连续、物理页可分散,用于大块内核缓冲区、模块加载等。与 线性映射区(lowmem/direct map)分配路径不同。

6.5 init_mm 与用户进程

每个用户进程有独立 mm_struct;内核线程可借用 active_mminit_mm。上下文切换时 switch_mm() 切换页表(架构相关,在 arch/arm64/)。


七、页缓存与文件 I/O

7.1 filemap.c

实现 通用文件 mmap 语义page cache

  • filemap_fault:文件映射缺页,读盘或复用已有 folio
  • filemap_read / filemap_write:缓冲 I/O 与页缓存交互
  • address_space、inode 锁、i_mmap_rwsem 协同

7.2 readahead.c

根据访问模式 预读 相邻页,降低顺序读延迟。

7.3 page-writeback.c + backing-dev.c

  • 脏页标脏、回写线程、wb_writeback
  • backing device 控制回写并发与脏页比例,避免内存被脏页占满

7.4 truncate.c

文件截断时释放或无效化 page cache 中超出文件大小的页。


八、反向映射(rmap)

8.1 作用

rmap.c 维护 物理页 → 所有映射它的 PTE 的关系,用于:

  • 回收时 unmap 并剥离引用
  • 迁移KSM内存故障 处理
  • 判断页是否仍被引用(page_referenced

8.2 两类映射

类型 结构 场景
匿名页 anon_vma 堆、栈、匿名 mmap
文件页 address_space + i_mmap 文件映射、shmem

8.3 锁顺序

rmap.c 文件头注释了 MM 子系统 锁顺序,调试死锁时需严格遵守(mmap_lockanon_vma/mappinglru_lock 等)。


九、内存回收与压缩

9.1 vmscan.c

页回收核心:

  • kswapd:per-node 内核线程,水位低于 low 时异步扫描 LRU
  • direct reclaim:在 __alloc_pages 慢路径中同步回收
  • LRU 链表active / inactive,分 fileanon
  • swappiness:控制匿名页 vs 文件页回收倾向

9.2 workingset.c

利用 refault 等信息区分 working set 与可回收缓存,改善回收质量。

9.3 compaction.c

内存压缩:迁移可移动页,拼凑 物理连续 空闲块,服务于:

  • CMA 分配
  • 大页透明大页
  • 高 order 伙伴块分配失败后的恢复

9.4 vmpressure.c

cgroup 或用户空间报告内存压力事件(与 memcontrol.c 配合)。


十、OOM 杀手

10.1 oom_kill.c

__alloc_pages 在回收、压缩后仍无法获得足够内存时,可能调用 out_of_memory()

  • oom_score_adj、内存占用、子进程等选择 victim
  • 发送 SIGKILL 或依赖 panic_on_oom 策略
  • memcg 结合时可做 cgroup 级 OOM(仅杀组内进程)

10.2 与调度的关系

OOM 选择进程时考虑 task_struct 属性,但不经过 sched_class;与 cpufreq_schedutil 无直接调用链,但内存压力导致的回收会增加 CPU 与 I/O 负载,间接影响调度与调频观测。


十一、CMA 连续内存分配器

详细原理与实现见 09-CMA连续内存机制与实现详解.md

11.1 cma.c

CMA(Contiguous Memory Allocator) 在启动时预留一块 物理连续 内存:

  • 平时可作为 可迁移页 参与 buddy 分配(带 PageCMA
  • 驱动需要连续 DMA buffer 时,通过 cma_alloc() 分配并 pin 住连续区域
  • 分配失败时可触发 compaction 迁移周围页

11.2 与设备树

RK3588 常见配置:

1
2
3
4
reserved-memory {
linux,cma { ... };
/* 或独立 display/camera 预留 */
};

内核启动参数 cma=256M 等可调整默认 CMA 大小(具体以 defconfig 与 DT 为准)。

11.3 编解码 / 显示

VPU、RGA、DRM 等驱动常依赖 dma_alloc_from_contiguousdrm 子系统 从 CMA 池取 buffer;问题排查需同时看:

  • /proc/meminfoCmaTotal / CmaFree
  • dmesgcma: 前缀日志
  • DT reserved-memory 是否与驱动匹配

十二、交换与子系统扩展

12.1 swap(CONFIG_SWAP)

文件 功能
swapfile.c swap 设备/文件注册
swap_state.c swap cache、swap entry
page_io.c 读写 swap 槽
swap_slots.c slot 管理

12.2 zswap(CONFIG_ZSWAP)

在写 swap 前 压缩 页到内存池,减少闪存/块设备 I/O(zswap.c + zpool/zbud/zsmalloc 等后端)。

12.3 其他扩展

机制 文件 说明
KSM ksm.c 合并相同匿名页
THP huge_memory.c, khugepaged.c 透明大页
hugetlb hugetlb.c 显式大页文件系统
shmem shmem.c tmpfs、共享内存
memfd memfd.c sealing、匿名 fd
userfaultfd userfaultfd.c 用户态处理缺页
DAMON damon/ 访问监控与回收策略
memcontrol memcontrol.c cgroup v2 内存控制器

十三、RK3588 / 编解码场景关联

13.1 本目录与平台差异

  • mm/ 内无 rockchip / rk3588 字符串,为上游 Linux 6.1 MM 代码。
  • 平台差异体现在:defconfig设备树 reserved-memory/CMAIOMMU/SWIOTLBarch/drivers/iommu)、DRM/V4L2 驱动

13.2 SeagullYpcEncode 典型关注点

场景 MM 相关点
编码 buffer CMA、dma_alloc_coherent、dmabuf(drivers + gup.c
内存压力 vmscan 回收、oom_kill、可选 memcg 限制编码进程
碎片 / 大 buffer 失败 compaction、CMA 预留不足、order 过高
32 位 DMA 设备 ZONE_DMA32CONFIG_DMA_COHERENT_POOL
性能观测 /proc/meminfo/proc/vmstat/proc/pressure/memory(PSI)

13.3 ARM64 特性

  • 无 highmemhighmem.c 非关键路径
  • 4K 页(可配置 16K/64K,以实际 Image 为准)
  • MTE/KASAN HW tags:若启用,与 kasan/hw_tags.c 相关

十四、调试与观测

14.1 proc / sysfs

接口 内容
/proc/meminfo 总览:MemFree、Cached、Swap、Cma*
/proc/vmstat 详细计数(vmstat.c
/proc/buddyinfo 各 zone 各 order 空闲块
/proc/pagetypeinfo 页类型(可迁移、不可迁移、CMA 等)
/proc/zoneinfo zone 水位与统计
/sys/kernel/mm/cma/ CMA 区域信息(CONFIG_CMA_SYSFS)

14.2 内核参数(示例)

  • mem=512M:限制可见内存
  • cma=256M:CMA 默认大小
  • vm.swappiness:回收倾向(sysctl)
  • panic_on_oom:OOM 时 panic

14.3 跟踪

  • trace/events/kmem.htrace/events/cma.h
  • CONFIG_PAGE_OWNERCONFIG_DEBUG_VM_PGTABLE 等调试选项见 Kconfig.debug

十五、总结

要点 说明
定位 Linux 6.1 通用 MM 子系统,约 176 源文件
引导 memblock → sparse → buddy → SLUB
热路径 __alloc_pages、缺页、filemap_fault、kswapd
RK3588 依赖 CMA/DT/defconfig,非 mm/ 内厂商补丁
编解码 重点 CMA、DMA、回收/OOM、memcg

附录:关键函数与调用关系

A.1 页分配慢路径(简化)

1
2
3
4
5
6
7
__alloc_pages()
├─ get_page_from_freelist() // 快路径尝试
└─ __alloc_pages_slowpath()
├─ wake_all_kswapds()
├─ try_to_compact_pages() // 可选
├─ __alloc_pages_direct_reclaim()
└─ out_of_memory() // 仍失败

A.2 缺页(简化)

1
2
3
4
5
6
7
架构 data abort / page fault
└─ handle_mm_fault()
├─ __handle_mm_fault()
│ ├─ filemap_fault() // 文件映射
│ ├─ do_anonymous_page() // 匿名
│ └─ do_swap_page() // swap
└─ 返回 VM_FAULT_* 重试或 SIGSEGV

A.3 回收(简化)

1
2
3
4
5
kswapd / direct reclaim
└─ balance_pgdat() / shrink_lruvec()
└─ shrink_list() → shrink_page_list()
└─ try_to_unmap() [rmap]
└─ 脏页写回 / 释放 / swap out

A.4 关键文件行号参考(便于跳转源码)

符号 文件 约略位置
__alloc_pages page_alloc.c ~5596
page_alloc_init page_alloc.c ~8733
kmem_cache_init slub.c ~4818
anon_vma_init rmap.c ~459
init_mm init-mm.c 全局变量

文档生成自 rk3588/kernel-6.1/mm/ 目录分析,与 README.md 配套使用。

mm 文档索引

mm 文档索引

Linux 6.1(RK3588)内存管理(Memory Management)子系统源码分析与原理说明。

总览文档

文档 说明
mm内存管理机制与原理详解.md 总览:架构、启动、各模块关系、RK3588 关联
源码文件与模块索引.md mm/ 文件清单、Makefile/Kconfig 对照

功能组专题(原理 + 实现)

每篇文档结构:原理 → 实现方式 → 数据结构/接口 → RK3588 → 调试 → 附录

编号 文档 源码重点
01 引导期内存机制与实现详解.md memblock、sparse、init-mm
02 物理页分配机制与实现详解.md page_alloc、buddy、zone、水位线
03 SLUB小对象分配机制与实现详解.md slub、slab_common、kmalloc
04 虚拟内存与缺页机制与实现详解.md memory、mmap、mprotect、mremap
05 页缓存与写回机制与实现详解.md filemap、readahead、writeback
06 反向映射机制与实现详解.md rmap、page_vma_mapped
07 内存回收与压缩机制与实现详解.md vmscan、workingset、compaction
08 OOM机制与实现详解.md oom_kill
09 CMA连续内存机制与实现详解.md cma、alloc_contig_range
10 交换与Zswap机制与实现详解.md swap*、zswap、page_io
11 cgroup内存控制机制与实现详解.md memcontrol、vmpressure、mempolicy
12 扩展内存机制与实现详解.md vmalloc、gup、migrate、hugetlb、shmem 等

源码路径

1
rk3588/kernel-6.1/mm/

阅读顺序建议

总览 mm内存管理机制与原理详解01 引导期02 物理页分配03 SLUB04 虚拟内存05 页缓存06 rmap07 回收与压缩08 OOM09 CMA10 交换11 memcg12 扩展机制

核心机制速查

机制 主要文件 关键入口
引导期内存 memblock.c memblock_add(), memblock_free_all()
物理页分配 page_alloc.c __alloc_pages()
小对象分配 slub.c kmem_cache_alloc(), kmalloc()
虚拟内存 / 缺页 memory.c, mmap.c handle_mm_fault(), do_mmap()
页缓存 filemap.c filemap_fault(), filemap_read()
反向映射 rmap.c try_to_unmap()
回收 vmscan.c balance_pgdat()
OOM oom_kill.c out_of_memory()
连续物理内存 cma.c cma_alloc()
cgroup 内存 memcontrol.c mem_cgroup_charge()

与 RK3588 编解码场景

  • CMA / reserved-memory:DT 预留连续内存,驱动 DMA buffer(VPU/RGA/DRM)→ 09
  • ZONE_DMA32:32 位 DMA 设备寻址 → 02
  • 回收 / OOM:多路编码 → 070811
  • Rockchip 快启延迟释放 memblock:→ 01

mm/ 源码文件与模块索引

mm/ 源码文件与模块索引

源码路径rk3588/kernel-6.1/mm/
内核版本:Linux 6.1
文档目录linuxDoc/mm/


一、始终编译(obj-y)

文件 功能摘要
filemap.c 通用文件 mmap、page cache、fault、读路径
mempool.c 内存池,保证在原子上下文也能分配成功
oom_kill.c 内存耗尽时选择并终止进程
fadvise.c posix_fadvise / readahead 建议
maccess.c 内核安全访问用户内存
page-writeback.c 脏页写回、回写控制
folio-compat.c folio 与 legacy struct page 兼容层
readahead.c 预读控制
swap.c swap 子系统公共逻辑
truncate.c 截断 inode 页缓存
vmscan.c LRU 扫描、kswapd、direct reclaim
shmem.c tmpfs / 共享匿名内存(ashmem 等)
util.c MM 通用工具函数
mmzone.c zone 相关辅助
vmstat.c /proc/vmstat、zone 统计
backing-dev.c backing device 写回队列
mm_init.c 启动期 MM 校验与调试
percpu.c per-CPU 变量动态分配
slab_common.c slab 子系统公共接口
compaction.c 内存压缩,缓解外部碎片
interval_tree.c VMA 区间树
list_lru.c 按 memcg 的 LRU 列表
workingset.c refault 等 working set 启发
debug.c MM 调试辅助
gup.c get_user_pages 系列
mmap_lock.c mmap_lock 读写锁实现
page_alloc.c 伙伴系统、zone、页分配核心
init-mm.c 全局 init_mm
memblock.c 引导期 memblock 分配器

CONFIG_MMU=y 时额外链接(mmu-y)

文件 功能摘要
highmem.c 高端内存(ARM64 通常不用)
memory.c 缺页、COW、页表操作、swap in/out
mincore.c mincore() 系统调用
mlock.c mlock / munlock
mmap.c mmap / munmap / brk
mmu_gather.c TLB 批量 gather 卸载页表
mprotect.c mprotect()
mremap.c mremap()
msync.c msync()
page_vma_mapped.c 判断 page 是否在 VMA 中映射
pagewalk.c 页表遍历框架
pgtable-generic.c 通用页表辅助
rmap.c 反向映射
vmalloc.c vmalloc / vmap
process_vm_access.c process_vm_readv/writev(可选)

二、Kconfig 可选模块

CONFIG 文件/目录 功能
CONFIG_SWAP page_io.c, swap_state.c, swapfile.c, swap_slots.c swap 分区/文件
CONFIG_ZSWAP zswap.c 压缩 swap 缓存
CONFIG_FRONTSWAP frontswap.c frontswap 抽象
CONFIG_HAS_DMA dmapool.c DMA 池
CONFIG_HUGETLBFS hugetlb.c, hugetlb_cgroup.c 显式大页
CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP hugetlb_vmemmap.c 大页 vmemmap 优化
CONFIG_NUMA mempolicy.c, memory-tiers.c NUMA 策略与内存分层
CONFIG_SPARSEMEM sparse.c 稀疏内存模型
CONFIG_SPARSEMEM_VMEMMAP sparse-vmemmap.c 虚拟 vmemmap
CONFIG_SLUB slub.c SLUB 分配器(RK 默认)
CONFIG_SLAB slab.c SLAB 分配器
CONFIG_SLOB slob.c SLOB(嵌入式)
CONFIG_KASAN kasan/ 内核地址消毒
CONFIG_KFENCE kfence/ 采样式堆越界检测
CONFIG_KMSAN kmsan/ 内核 MSan
CONFIG_KSM ksm.c 内核同页合并
CONFIG_MIGRATION migrate.c 页迁移
CONFIG_DEVICE_MIGRATION migrate_device.c 设备页迁移
CONFIG_TRANSPARENT_HUGEPAGE huge_memory.c, khugepaged.c 透明大页
CONFIG_MEMCG memcontrol.c, vmpressure.c, swap_cgroup.c cgroup 内存控制
CONFIG_CMA cma.c, cma_debug.c, cma_sysfs.c 连续内存分配器
CONFIG_MEMORY_HOTPLUG memory_hotplug.c 内存热插拔
CONFIG_MEMORY_FAILURE memory-failure.c 硬件内存错误处理
CONFIG_USERFAULTFD userfaultfd.c 用户态缺页处理
CONFIG_DAMON damon/ 数据访问监控
CONFIG_ZONE_DEVICE memremap.c 设备内存 zone
CONFIG_HMM_MIRROR hmm.c Heterogeneous Memory Management
CONFIG_MEMFD_CREATE memfd.c memfd
CONFIG_ZPOOL / ZBUD / ZSMALLOC / Z3FOLD 对应 .c zswap 后端压缩存储

三、子目录

目录 说明
kasan/ KernelAddressSANitizer:shadow、report、quarantine
kfence/ 低开销堆内存错误检测
kmsan/ 未初始化内存使用检测
damon/ DAMON:监控访问模式、回收/排序模块

四、内部头文件

文件 说明
internal.h mm 子系统内部 API、GFP 掩码、folio 辅助
slab.h slab 内部
cma.h CMA 内部
swap.h swap 内部

五、配置文件

文件 说明
Makefile 编译单元与 KCOV/KCSAN 例外
Kconfig menu "Memory Management options"
Kconfig.debug MM 调试相关选项