交换与 Zswap 机制与实现详解
源码路径:
rk3588/kernel-6.1/mm/swap.c、swapfile.c、swap_state.c、swap_slots.c、page_io.c、zswap.c、frontswap.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 对匿名页:
add_to_swap:分配 swap slot,页标SWAP_TYPEtry_to_unmap(06 文档)swap_writepage/__swap_writepage:写page_io.c提交 bio- 成功后页可从 LRU 移除并释放物理帧
2.2 换入路径(缺页)
memory.c do_swap_page:
- 根据 PTE swap entry 找
swap_info_struct read_swap_cache_async或同步读- 安装有效 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 选择)
- 内存池 zpool(
zpool.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:匿名页回收只能靠释放或 OOM;
swappiness无效。 - 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) |
正在加载留言…