如何在无交换分区的嵌入式Linux中检测低内存状况?
针对嵌入式Linux无swap环境下内存抖动的提前监控方案
你的场景太典型了——无swap的嵌入式系统里,内存泄漏或内存需求过载引发的clean page反复回收/加载,确实是个隐蔽的性能杀手,常规的内存监控手段很难提前预警。结合你提到的需求,我分享几个无需修改内核的实用方案:
1. 直接读取/proc文件系统的核心统计指标
Linux的/proc虚拟文件系统里藏着最底层的内存管理数据,完全满足你的监控需求:
- 监控major page fault(大页错误):当clean page被回收后再次访问,会触发大页错误(需要从磁盘重新加载),这是抖动最直接的前兆。你可以通过
/proc/vmstat查看:cat /proc/vmstat | grep -E 'pgfault_maj|pgscan_kswapd|pgsteal_kswapd'pgfault_maj:累计的大页错误次数,如果这个数值持续快速增长(比如每秒增加几十次甚至上百次),说明系统开始频繁从磁盘加载clean page,抖动即将到来。pgscan_kswapd/pgsteal_kswapd:kswapd内核线程扫描和偷取的clean page数量,当这两个数值持续上升,说明内存压力已经迫使内核主动回收clean page。
- 跟踪内存分区变化:通过
/proc/meminfo观察文件缓存和匿名内存的趋势:
当cat /proc/meminfo | grep -E 'Active\(anon\)|Inactive\(file\)|Cached'Inactive(file)和Cached持续减少,同时Active(anon)(进程占用的匿名内存)持续增长,说明进程正在抢占clean page的空间,内存压力逐步增大。
2. 用vmstat做实时趋势监控
vmstat是系统自带的轻量级监控工具,能直观展示内存管理的动态:
vmstat 1 # 每秒输出一次统计数据
重点关注这几个字段:
majflt:每秒的大页错误次数,这个数值的持续上升是抖动的明确信号(即使free内存看起来还有剩余)。pgscank/pgstealk:kswapd扫描和偷取的页数,对应/proc/vmstat里的指标,持续增长说明内核在拼命回收clean page。
(注:不同Linux发行版的vmstat字段名可能略有差异,比如部分版本会用pgscan/pgsteal代替)
3. 写个简单脚本实现阈值告警
你可以把上面的指标封装成定时脚本,设置合理的阈值来触发告警,比如这个bash脚本的示例:
#!/bin/bash # 记录上一次的majfault数值 prev_maj=$(cat /proc/vmstat | grep pgfault_maj | awk '{print $2}') while true; do sleep 1 curr_maj=$(cat /proc/vmstat | grep pgfault_maj | awk '{print $2}') maj_diff=$((curr_maj - prev_maj)) # 假设阈值为每秒20次大页错误,可根据系统正常状态调整 if [ $maj_diff -gt 20 ]; then echo "警告:大页错误激增,内存抖动风险!" >> /var/log/mem_warn.log # 这里可以加告警动作:比如发送邮件、触发GPIO指示灯等 fi prev_maj=$curr_maj done
把脚本设为后台服务(比如用systemd管理),就能在问题恶化前及时告警。
4. 结合进程级监控定位根源
除了系统级监控,你还可以结合进程的内存增长趋势,区分是内存泄漏还是正常的内存需求增长:
- 用
ps aux --sort=-%mem定期记录进程的RSS(常驻内存)占用,观察是否有进程的内存持续无限制增长(这大概率是内存泄漏)。 - 结合进程的
/proc/<pid>/statm或mallinfo(3)数据,补充进程内部的内存分配情况,但注意mallinfo只能监控glibc的堆内存,无法覆盖所有内存分配(比如mmap的内存)。
为什么这些方案比free/top更有效?
你提到的free里的"free"列其实参考价值有限——Linux会尽量用空闲内存做page cache,所以free内存低不一定是问题;而top只能看进程的内存占用,无法捕捉内核回收clean page的行为。而大页错误和kswapd的统计数据,直接反映了clean page被反复换入换出的过程,是抖动最早期的信号。
内容的提问来源于stack exchange,提问作者itaych
相关产品推荐
相关产品推荐

