用Rust写系统监控工具:别被 `free -h` 的内存数据给骗了
Linux 内存管理里有个非常典型的“陷阱”:
下一篇
AI Agent真的能接管所有行业吗? →
MemFree 并不代表你真正能用的剩余内存。很多初学者(包括之前的我)在读取 /proc/meminfo 时,看到 MemFree 接近于 0 就会惊慌,觉得系统快崩了。但实际上,Linux 内核极其厌恶内存闲置,它会尽可能用 Page Cache 把空闲内存填满,一旦有进程需要,它会瞬间释放。所以,真正能衡量系统健康度的指标是 MemAvailable。在开发类似 ratatop 这种系统监控工具时,如果你试图通过 Total - Free - Cached - Buffers 来计算已用内存,很容易陷入混乱,因为这些指标之间存在重叠,并不是简单的加减法关系。
为了在实操中拿到最准确的数值,我参考了 btop 的实现逻辑。最简单且最靠谱的计算方式其实是:Used = MemTotal - MemAvailable
直接信任内核给出的估算值,比自己在那儿算各种缓存偏移要稳得多。
在 Rust 中实现这个内存收集器时,我定义了一个简单的结构体来承载原始字节数据,绝对不要在数据层做单位转换,格式化交给 UI 层处理:

pub struct Memory {
pub total: u64,
pub used: u64,
pub available: u64,
pub cached: u64,
pub free: u64,
}这里分享一个我在解析 /proc/meminfo 时踩的坑,非常具有代表性。如果你用 contains 或者简单的子字符串匹配来提取数据,你会发现 Cached 的数值经常莫名其妙地变小。
原因在于 /proc/meminfo 的内容格式:
MemTotal: 14177796 kB
MemFree: 497404 kB
MemAvailable: 7490900 kB
Buffers: 1235656 kB
Cached: 5146132 kB
SwapCached: 81068 kB注意看 SwapCached 这一行,它包含了 Cached 这个字符串。如果你的解析逻辑不够严谨,SwapCached 的值会直接覆盖掉真正的 Cached 值,而且程序不会报错,只会给你一个看起来很正常但完全错误的结果。
正确的实战做法是使用 split_once(':') 严格匹配标签名,确保精准命中:
let Some((label, rest)) = line.split_once(':') else { continue };
match label {
"MemTotal" => memory.total = parse_kb(rest),
"MemAvailable" => memory.available = parse_kb(rest),
"Cached" => memory.cached = parse_kb(rest),
// ... 其他字段
_ => {}
}