3. 内存分析工具入门:使用 /proc/meminfo、free -m、smem 查看内存分布

做嵌入式内存优化,第一步不是动手改代码。

而是先搞清楚——内存到底去哪了?

我见过太多工程师,上来就怀疑自己代码有内存泄漏,结果一查,是内核占了一大块。所以,学会用工具看内存分布,是基本功。

3.1 /proc/meminfo:最原始的内存快照

这个文件,说白了就是内核给你的一张内存账单。

你只要敲一行命令:

cat /proc/meminfo

就能看到一大堆指标。但别被吓到,我们重点关注这几个:

字段 含义 我的关注点
MemTotal 物理内存总量 确认硬件容量
MemFree 完全空闲的内存 如果接近0,不一定有问题
Buffers 块设备缓存 文件系统相关
Cached 页面缓存 + tmpfs 这部分可以回收
SwapTotal / SwapFree 交换分区总量和剩余 边缘设备尽量别用swap

核心公式:

实际可用内存 ≈ MemFree + Buffers + Cached

因为 Buffers 和 Cached 在内存紧张时可以被内核回收。

我个人习惯,先看 MemAvailable 这个字段。它是内核帮你算好的「预估可用内存」,比你自己加来加去更准。

小技巧:

如果你只想看某个字段,可以配合 grep:

cat /proc/meminfo | grep MemAvailable

3.2 free -m:更友好的命令行工具

/proc/meminfo 信息太原始了。你想想看,每次都要自己算,多麻烦。

所以 Linux 提供了 free 命令。加上 -m 参数,以 MB 为单位显示:

free -m

输出大概是这样的:

              total        used        free      shared  buff/cache   available
Mem:           1984         456         234          34        1294        1345
Swap:             0           0           0

这里有个坑,我刚开始做嵌入式时经常搞混。

你看那个 used 列,它其实包含了 buff/cache。所以 used + free 并不等于 total。

真正该看的是 available 列——它表示在不触发 swap 的情况下,还能给新进程分配多少内存。

避坑指南:

我曾经在一个项目里,看到 free 显示 used 高达 80%,以为内存不够了。后来才发现,大部分是 buff/cache,available 还有 60%。

所以,别被 used 吓到。先看 available。

3.3 smem:按进程看内存,更直观

free 和 /proc/meminfo 只能看全局。但问题往往出在某个进程上。

这时候,smem 就派上用场了。

smem 不是系统自带的,需要安装:

sudo apt install smem   # Debian/Ubuntu
sudo yum install smem   # CentOS/RHEL

安装后,直接运行:

smem

它会按 RSS、PSS、USS 三个维度,列出每个进程的内存占用。

指标 全称 含义
RSS Resident Set Size 进程占用的物理内存(包含共享库)
PSS Proportional Set Size 按比例分摊共享库后的内存
USS Unique Set Size 进程独占的物理内存

我个人最常用的是 PSS。为什么?

你想想看,两个进程都用了 libc.so,RSS 会重复计算。但 PSS 会把共享库按进程数分摊。这样加起来,才接近系统总内存。

实战用法:

按内存占用排序,找出「内存大户」:

smem -rs pss | head -20

-r 表示倒序,-s pss 表示按 PSS 排序。

嗯,这里要注意。smem 在嵌入式设备上可能跑得比较慢。如果设备内存只有 256MB,建议用 smem -t 只显示 totals,或者干脆用 top 先粗筛一遍。

3.4 三个工具怎么配合?

我一般按这个流程来:

  1. 先看全局:free -m 扫一眼 available,心里有个底。
  2. 再查细节:cat /proc/meminfo 确认 Buffers 和 Cached 的分布。
  3. 最后定位进程:smem -rs pss 找出谁在吃内存。

举个例子。有一次,我发现设备运行 3 天后,available 从 500MB 掉到了 100MB。

用 free -m 一看,Cached 涨了 300MB。再用 smem 一查,发现是一个日志进程不停地写文件,导致页面缓存暴涨。

解决方案很简单:限制日志文件大小,或者定期 sync 并 drop_caches。

补充命令:

如果你想手动清理缓存(仅限调试用):

echo 3 > /proc/sys/vm/drop_caches

但千万别在生产环境乱用。我曾经手滑过,结果系统性能骤降,因为所有缓存都被清空了。

3.5 小结

这三个工具,是内存分析的入门三板斧。

/proc/meminfo 给你原始数据,free -m 给你友好视图,smem 帮你定位进程。

记住一句话:先看 available,再看 PSS,最后动手优化。

下一章,我们会深入讲 slabtop 和 /proc/slabinfo,专门对付内核态的内存泄漏。到时候你会发现,用户态那点内存占用,其实都是小意思。