嵌入式内存管理:从 ZRAM 压缩到 Flash 寿命,128MB 设备的自救实录
嵌入式内存管理从 ZRAM 压缩到 Flash 寿命128MB 设备的自救实录128MB 的 RAM256MB 的 Flash这样的嵌入式设备上跑着激光雷达和导航节点。内存总是不够用但换硬件不现实。于是我开始研究 ZRAM——在内存里划一块区域把数据压缩后塞进去用 CPU 算力换内存空间。这篇文章记录了 ZRAM 的配置、压缩比计算、与 ZSWAP 的区别以及为什么在嵌入式设备上内存压缩不只是一个性能问题更是一个关乎 Flash 存储寿命的问题。一、为什么需要内存压缩当物理内存不足时Linux 内核会把不常用的内存页移到 Swap 空间腾出物理内存给活跃进程。传统的 Swap 依赖硬盘或 Flash但对嵌入式设备来说有两个致命问题太慢Flash 的读写速度比内存慢几个数量级一旦触发 Swap系统会严重卡顿。太伤寿命Flash 的擦写次数有限频繁的 Swap 写入会快速耗尽存储寿命。ZRAM 就是为了解决这两个问题而生的——它在内存里划出一块区域把原本要写入 Flash 的 Swap 数据压缩后存放在这块内存里完全绕过 Flash。二、ZRAM 是什么—— 在内存里造一个“压缩 Swap”ZRAM 是 Linux 内核提供的一个模块它的核心思想很简单在物理内存中创建一个压缩的块设备把它当作 Swap 分区来用。当系统需要 Swap 数据时数据不是写入硬盘或 Flash而是被压缩后存入这块内存区域。效果速度极快全程在内存中操作彻底避免 Flash I/O 卡顿。节省物理内存原本 100MB 的数据压缩后可能只占 30MB 物理内存。代价需要消耗 CPU 算力进行压缩/解压。三、查看当前 ZRAM 状态先看系统使用了哪些 Swap 设备cat/proc/swaps Filename Type Size Used Priority /dev/zram0 partition204765304100输出显示系统只配置了/dev/zram0没有传统的硬盘或 Flash Swap。ZRAM 是唯一的交换空间大小约 20MB已使用约 5.3MB优先级为 100较高。查看压缩详情cat/sys/block/zram0/mm_stat507084818709662347008023470089811逐字段解读单位字节字段数值换算含义第 1 个5,070,848~4.84 MB压缩前的原始数据大小逻辑数据量第 2 个1,870,966~1.78 MB压缩后的纯数据大小不含元数据第 3 个2,347,008~2.24 MB实际占用的物理内存总大小含元数据和索引第 6 个98-相同页Same Page数量—ZRAM 的去重优化命中 98 个 4KB 页压缩比 原始数据 ÷ 压缩后数据 4.84 / 1.78 ≈ 2.7 倍即 ZRAM 用 2.24MB 的物理内存换来了 4.84MB 的逻辑 Swap 空间。四、压缩算法lz4vslzovszstd查看当前使用的压缩算法及详细状态zramctl输出示例NAME ALGORITHM DISKSIZE DATA COMPR TOTAL STREAMS MOUNTPOINT /dev/zram0 lz4 20M 5.3M 1.2M 1.3M 4 [SWAP]各列含义ALGORITHM当前使用的压缩算法DATA压缩前的逻辑数据COMPR压缩后的纯数据TOTAL含元数据的实际物理内存占用三种常见算法对比算法压缩比压缩速度解压速度适用场景lz4中等~2.5-3x极快极快嵌入式设备首选速度优先lzo较低~2x快快老设备兼容zstd较高~4-5x中等快追求高压缩比CPU 较强的设备对于实时性要求较高的机器人应用lz4是最佳选择。五、ZRAM vs ZSWAP一字之差天壤之别很多人会把 ZRAM 和 ZSWAP 搞混。它们都做内存压缩但架构完全不同特性ZRAMZSWAP本质直接创建一个压缩的内存块设备替代传统 Swap在内存和物理 Swap 之间增加一个压缩缓存层是否需要物理 Swap 设备不需要自成一体的 Swap 设备必须依赖一个真正的物理 Swap硬盘/Flash数据最终流向压缩后留在内存从不写存储设备缓存满了之后解压并写入物理 Swap 设备是否写 Flash/硬盘永不会写只是减少了写入次数适用场景无物理交换设备的嵌入式系统有 SSD 的桌面/服务器优化性能并减少 SSD 写入对于 128MB 内存、256MB Flash 的嵌入式设备ZRAM 是唯一正确的选择。ZSWAP 不适合因为它需要一个物理 Swap 设备作为最终存储——在无硬盘的设备上这个“最终存储”只能是 Flash而这正是我们需要避免的。六、ZRAM 的边界如果它爆了怎么办ZRAM 虽然不写 Flash但它本身占用了物理内存。如果 ZRAM 的物理内存占用加上其他进程的内存超过了物理内存总量系统依然会耗尽。6.1 最坏情况ZRAM 写满 物理内存耗尽内核收到内存分配请求但 ZRAM 没空间存放新的压缩数据物理内存也无剩余。因为没有后备 Swap 设备如果只配置了 ZRAM结果只能是内存分配请求返回-ENOMEM程序收到std::bad_alloc崩溃如果系统配置了 OOM Killer可能会随机杀进程6.2 如何防止 ZRAM 爆满① 设置物理内存上限mem_limit防止 ZRAM 无限制吞噬物理内存echo60M/sys/block/zram0/mem_limit② 适当增大逻辑容量disksizeswapoff /dev/zram0echo1/sys/block/zram0/resetecho60M/sys/block/zram0/disksizemkswap/dev/zram0swapon/dev/zram0-p100③ 添加低优先级 Flash Swap 作为最后保险丝需权衡 Flash 寿命fallocate-l50M /mnt/flash/swapfilechmod600/mnt/flash/swapfilemkswap/mnt/flash/swapfileswapon/mnt/flash/swapfile-p-1# 极低优先级ZRAM 爆了才用6.3 监控指标# 物理碎片状态watch-n1cat /proc/buddyinfo# ZRAM 压缩效率watch-n2cat /sys/block/zram0/mm_stat# Swap 写入频率看 so 列是否持续 0vmstat5七、Flash 擦写寿命为什么这是条红线Flash 存储eMMC/NAND的擦写次数是有限的类型每单元比特数典型擦写寿命SLC1 bit~100,000 次MLC2 bits~3,000 – 10,000 次TLC3 bits~500 – 3,000 次以 TLC 为例如果每天往 Flash 里写 50MB 数据256MB 的 Flash 大约 1 个月就会被写满一轮按 3000 次寿命计算约 8 年耗尽。但如果每天写 200MB寿命直接缩短到 2 年。这就是为什么嵌入式设备必须用 ZRAM 而不是 Flash Swap 的原因保护 Flash 寿命是硬约束。八、总结ZRAM 是嵌入式设备内存管理的最佳工具——用少量 CPU 算力和物理内存换取更大的可用内存空间同时完全避免 Flash 写入。ZRAM 和 ZSWAP 是两种截然不同的技术——ZRAM 自成一体的 Swap 设备ZSWAP 是内存与物理 Swap 之间的压缩缓存必须有后备物理设备不适合无硬盘的嵌入式环境。监控是关键——定期检查buddyinfo物理碎片、mm_stat压缩比、vmstat的so列Swap 写入频率在问题爆发前发现苗头。Flash 寿命是底线——任何导致频繁写入 Flash 的设计包括 ZSWAP 和低优先级的 Flash Swap都需要谨慎权衡只有在极端情况下才应该作为“保险丝”使用。如果你也在 128MB 内存的嵌入式设备上跑 ROS 节点希望这份经验能帮你少走一些弯路。