本文约2200字,今天仔细阅读了正在研发的项目文档关于内存优化相关的内容,深度学习一下爱芯的内存优化策略。嵌入式底层开发中,小内存(128MB/256MB DDR) 是常态。内存不够用会直接导致:应用崩溃、驱动加载失败、编码丢帧、系统 OOM、甚至启动不起来。本文从 CSAPP 内存模型讲起,把虚拟内存、物理内存、reserved memory、内存池讲透,再结合爱芯元智 AX615(128MB DDR) 官方内存优化指南,梳理一套可直接落地、能稳定量产的小内存优化方法论。
关注公众号, 即可获得与Linux相关的电子书籍以及常用开发工具,文末有文档清单。
一 从 CSAPP 看内存:我们必须建立的底层世界观
《深入理解计算机系统(CSAPP)》第 9 章告诉我们:Linux 内存 = 虚拟地址空间 → 页表 → 物理内存(DDR)。
对嵌入式小内存设备而言,我们只需要记住三句话:
虚拟内存再大也没用,最终都要落在物理 DDR 上。
物理内存一旦耗尽,OOM 会直接杀进程。
内核、驱动、硬件模块都要抢物理内存。
在 AX615 这种 128MB 超小 DDR 平台上:
内核占用~8MB
驱动 ko 占用~5MB
Linux 可用只剩~51MB
CMM 连续物理内存 64MB(视频 / ISP/NPU 专用)
内存查看命令如下:
[1].查看Linux 系统内存指令/root # cat /proc/meminfo | grep -E 'MemTotal|MemAvailable'MemTotal: 57220 kBMemAvailable: 21864 kB[2].查看内核自身占用内存指令/root # dmesg | grep Memory | head -2[ 0.000000] Memory policy: Data cache writealloc[ 0.000000] Memory: 57016K/61428K available (1881K kernel code, 104K rwdata, 1012K rodata, 148K init, 159K bss, 4412K reserved, 0K cma-reserved)内核自身占用 = 1881 + 104 + 1012 + 148 + 159 = 3304 KB ≈ 3.23 MB内核预留内存 = 4412 KB整个内核区域总消耗 ≈ 3.23MB + 4.31MB = 7.54 MB[3].查看驱动(.ko)占用内存root@infinova-virtual-machine:/mnt/nfs# awk 'BEGIN{sum=0} {sum+=$2} END{print sum/1024/1024 " MB"}' /proc/modules4.97266 MB[4].查看CMM 内存(ISP/VENC/NPU)/root # cat /proc/ax_proc/mem_cmm_info | grep -E 'total|used|remain'total size=200704KB(196MB),used=65824KB(64MB + 288KB),remain=134880KB(131MB + 736KB),partition_number=1,block_number=82
系统没有任何冗余空间,一不注意内存就爆了。
所以小内存优化的核心思想只有一条:统一分配、统一管理、按需申请、池化复用、绝不浪费。
二 嵌入式必须懂:内存池(Memory Pool)到底是什么
继续用 CSAPP 的逻辑讲:
动态 malloc/free, 容易产生碎片、慢、不可用于硬件。
硬件(ISP/VENC/NPU)必须用连续物理内存。
小内存系统严禁随时 new/delete。
于是就有了:
内存池 = 提前申请一大块连续内存 → 内部切成固定块 → 循环复用
优点:
>>无碎片
>>物理连续(硬件可用)
>>极快分配释放
>>可监控、可限流、可优化
我在爱芯AX615内存优化相关文档里看到的 CMM(Contiguous Memory Model)本质就是:专为硬件设计的连续物理内存池管理器。
三 AX615 内存架构:128MB 到底怎么分
文档明确划分:
DDR 128MB├── Linux 系统内存 64MB│ ├── 内核+reserved 8MB│ └── 驱动 ko 占用 5MB│ └── APP 可用 ~51MB└── CMM 硬件连续内存 64MB(ISP/VENC/IVPS/AUDIO/NPU)
大部分内存爆炸,都来自两个问题:
[1].Linux 内存和 CMM 划分比例不合理
[2].CMM 内部 pool 配置太大 / 太小
优化路线非常清晰:
第一步:调整 Linux和CMM 分配比例
文件:build/projects/AX615_nor/project.mak
OS_MEM_SIZE := 64 # Linux 大小
CMM_SIZE := 128 - OS_MEM_SIZE
视频多、分辨率大 → 加大 CMM
应用多、进程多 → 加大 Linux
这是最高收益、最简单、最优先做的优化。
四 Linux 内存优化(APP 可用内存从 50MB → 54MB)
文档给出的优化手段全部可落地:
[1]. 关闭无用内核配置
关闭 CONFIG_KALLSYMS_ALL → 节省 708KB
关闭 PM/SUSPEND/AOV → 节省 384KB
[2]. 关闭开机自启无用服务
syslogd / klogd
crontabs
telnet
urandom
sd_load.sh
ifplugd/dhcp
节省 600KB~1.2MB
[3]. 调整内存水位线(避免提前触发回收)
sysctl -w vm.min_free_kbytes=2048
sysctl -w vm.watermark_scale_factor=200
[4]. 精简 DTS reserved-memory
查看:
axera/AX615_nor.dts
reserved-memory {}
删除不用的 dump、optee、riscv 预留。
五 CMM 内存池优化
CMM 原理:
CMM (64MB)└── partition (anonymous 64MB)├── pool0 (FBC 格式块)├── pool1 (YUV 块)├── pool2 (编码用块)└── ...pool = 固定大小的 block 数组
优化原则:
[1].按分辨率计算 block size(必须 4K 对齐)
[2].按 pipeline 计算最少 block 数量
[3].监控 free cnt,长期多余就减少数量
[4].能用 FBC 压缩就绝不用裸 YUV
AX615的内存优化文档给出的最低配置如下:
FBC RAW:最少 4~7 帧
IVPS ↔ VENC:最少 2 帧
算法输入 YUV:最少 2 帧
CPU 读取:最少 2 帧
查看命令:
cat /proc/ax_proc/pool # 看 pool 状态cat /proc/ax_proc/mem_cmm_info # 看 CMM 总量
看到 FreeCnt 长期 ≥2,减少 block 数量
这是最有效、最安全的优化手段。
六 硬件模块级优化(VENC/ISP/AUDIO)
[1]. VENC 编码优化(文档重点)
限制通道数:max_h26x_chn_num=3
开启 mem_saveing=7,单 buffer 节省大量内存
开启 ref ringbuf,节省一整帧
码流 buffer 从 1.5 倍,1.0 倍(极限 0.5 倍)
[2]. IVPS 优化
启用 SW_LOW_MEM 模式
减少分流路数
高度按 64 对齐
[3]. AUDIO 优化
AI:最小 2 block ×4KB
AO:最小 4 block ×4KB
七 小内存嵌入式 Linux 终极优化心法
[1].先调 Linux/CMM 比例,这是最大头。
[2].CMM 必须用内存池,禁止零散分配
[3].能用 FBC 就不用裸 YUV
[4].pool 按最小帧缓存配置,不够再加,不要一步到位
[5].实时监控 free cnt,长期空闲必须缩
[6].关闭内核、服务、驱动里所有不用的功能
[7].reserved-memory 一定要精简
[8].应用层禁止频繁 malloc/free,全部用内存池
[9].驱动 ko 按需加载,不要开机全加载
[10].码流 buffer、参考帧、ringbuf 全部设为最小值
做到这 10 条,128MB 可以跑出 256MB 的效果。
八 总结
从 CSAPP 内存模型到虚拟内存,再到物理内存、reserved memory,最终落到嵌入式平台最关键的 CMM 连续物理内存池。
小容量 DDR(128MB)优化没有魔法,只有精确规划、精细管理、精准裁剪。
如果正在做:
爱芯 AX615、或者其他小内存 ARM/MIPS Linux 视频编码、ISP、NPU 平台
都可以参考,当然一般芯片厂家也会提供相应的内存优化文档供参考。
以上为全文内容。

这里是女程序员的笔记本
15年+嵌入式软件工程师兼二胎宝妈
分享读书心得、工作经验,自我成长和生活方式。
希望我的文字能对你有所帮助
夜雨聆风