04. 从零带你学习Linux内核:/proc
/proc/meminfo
这一节核心解决一个问题:
为什么
MemFree不等于真正可用内存?
这也是 Linux 内存监控里最容易被问的点。
1. /proc/meminfo 是什么
一句话:
/proc/meminfo是 Linux 内核暴露当前系统内存状态的接口,里面记录了总内存、空闲内存、可用内存、缓存、Swap、页表、Slab 等信息。
文章里也提到,/proc/meminfo 保存系统当前内存利用状况,常被 free 命令使用,内容通常是“字段名 + 对应值”的形式。
你的性能监控项目里,Worker 内存采集模块会读取 /proc/meminfo,解析 MemTotal、MemFree、MemAvailable、Buffers、Cached 等字段;项目分析里也明确提醒:MemFree 不等于真正可用内存,MemAvailable 更重要。
2. 先看一个典型输出
执行:
cat /proc/meminfo
可能看到:
MemTotal: 8017864 kB
MemFree: 150608 kB
MemAvailable: 1928040 kB
Buffers: 59152 kB
Cached: 2957520 kB
SwapCached: 2304 kB
Active: 5212064 kB
Inactive: 2191888 kB
SwapTotal: 2097148 kB
SwapFree: 1936892 kB
Dirty: 1120 kB
Writeback: 0 kB
Slab: 284820 kB
你作为第一阶段,不需要全部背。
先抓这几个:
MemTotal
MemFree
MemAvailable
Buffers
Cached
SwapTotal
SwapFree
Dirty
Writeback
Slab
3. 最重要的几个字段
| 字段 | 小白解释 | 监控意义 |
|---|---|---|
MemTotal | 总物理内存 | 分母 |
MemFree | 完全没被用的空闲内存 | 不能单独代表可用内存 |
MemAvailable | 估算还能分配给新程序的内存 | 判断内存压力最重要 |
Buffers | 块设备元数据缓存 | 可回收缓存的一部分 |
Cached | 文件页缓存 page cache | Linux 会用它加速文件读写 |
SwapTotal | 总交换空间 | 物理内存不够时的后备空间 |
SwapFree | 剩余交换空间 | 判断是否大量换页 |
Dirty | 已修改但还没写回磁盘的页 | 写回压力 |
Writeback | 正在写回磁盘的页 | I/O 写回状态 |
Slab | 内核对象缓存 | 内核态内存消耗 |
4. 为什么 MemFree 不等于真正可用内存
这是本节最核心的点。
很多小白看到:
MemTotal: 8 GB
MemFree: 150 MB
会以为:
系统快没内存了
这不一定对。
因为 Linux 的设计原则是:
空着的内存是浪费,所以 Linux 会尽量把暂时不用的内存拿来做缓存。
比如:
你第一次读一个大文件
↓
Linux 从磁盘读到内存
↓
读完后不会马上丢掉
↓
它会把文件内容留在 page cache 里
↓
下次再读同一个文件,就可以直接从内存读
所以 Linux 里经常会出现:
MemFree 很低
Cached 很高
这通常不是坏事,而是说明 Linux 把空闲内存拿去做缓存了。
5. MemAvailable 才更接近“还能用多少”
MemAvailable 的含义是:
内核估算在不明显触发 Swap 的情况下,还能分配给新程序使用的内存。
它不只是看 MemFree,还会考虑:
当前完全空闲的内存
+
可以回收的 page cache
+
可以回收的一部分 slab
-
为了系统稳定必须保留的水位线
所以你应该这样判断:
| 字段 | 判断价值 |
|---|---|
MemFree | 只表示完全空闲内存,参考价值有限 |
MemAvailable | 更适合判断系统是否真的缺内存 |
Cached/Buffers | 很多时候可以被回收,不要简单认为是“被浪费” |
面试里最重要的一句话:
Linux 内存监控不能只看
MemFree,因为 page cache 和 buffer 可以在内存紧张时被回收;更应该看MemAvailable。
6. Buffers 和 Cached 区别
小白可以这样理解:
6.1 Buffers
偏向块设备层面的缓存。
比如磁盘块、文件系统元数据相关缓存。
磁盘块设备
↓
文件系统元数据 / block buffer
↓
Buffers
6.2 Cached
偏向文件内容页缓存,也就是 page cache。
比如你读了一个文件:
磁盘上的 file.txt
↓
读到内存
↓
放入 page cache
↓
Cached 增加
简单记:
Buffers:偏块设备/元数据
Cached:偏文件内容缓存
现在 Linux 里你更常关注 Cached 和 MemAvailable。
7. 内存使用率怎么算
7.1 不推荐的算法
很多人会直接写:
used = MemTotal - MemFree
usage = used / MemTotal
这个算法有问题。
因为它会把 Cached、Buffers 都算成“已经不可用”,导致内存使用率看起来虚高。
7.2 更推荐的算法
面试和监控里更推荐:
used = MemTotal - MemAvailable
usage = used / MemTotal
也就是:
内存使用率 = 1 - MemAvailable / MemTotal
举例:
MemTotal = 8000 MB
MemFree = 150 MB
MemAvailable = 2000 MB
如果用 MemFree 算:
usage = 1 - 150 / 8000 = 98.1%
看起来快爆了。
但用 MemAvailable 算:
usage = 1 - 2000 / 8000 = 75%
这更接近真实压力。
8. Swap 怎么看
Swap 是磁盘上的交换空间。
当物理内存紧张时,内核可能把一部分不常用内存页换到 Swap:
物理内存不够
↓
内核挑一些冷页
↓
写到 Swap
↓
释放物理内存
看两个字段:
SwapTotal
SwapFree
可以算:
SwapUsed = SwapTotal - SwapFree
如果出现:
SwapUsed 很高
说明系统可能经历过内存压力。
如果同时:
SwapUsed 持续增长
系统响应变慢
磁盘 I/O 上升
就要警惕内存不足导致频繁换页。
注意:
Swap 用了一点不一定马上有问题,关键看是否持续增长,以及是否伴随 major page fault、I/O 抖动和延迟升高。
9. Dirty 和 Writeback 怎么看
这两个和磁盘写回有关。
9.1 Dirty
表示:
已经被修改,但还没有写回磁盘的内存页
比如程序写文件:
write()
↓
先写到 page cache
↓
标记为 Dirty
↓
后续由内核异步刷盘
9.2 Writeback
表示:
正在被写回磁盘的内存页
如果:
Dirty 很高
Writeback 很高
可能说明:
磁盘写入压力大
后台刷盘跟不上
这时候可能会进一步影响:
iowait
load average
请求延迟
10. Slab 是什么
Slab 是内核对象缓存。
内核经常要创建和释放一些对象,比如:
inode
dentry
socket buffer
task_struct
文件描述符相关结构
如果每次都从通用内存分配器申请释放,成本高。所以 Linux 用 slab/slub allocator 做对象缓存。
小白先这么记:
Slab是内核自己用的一部分内存,主要缓存内核对象。
Slab 里还有两类常见字段:
SReclaimable
SUnreclaim
| 字段 | 含义 |
|---|---|
SReclaimable | 可回收 slab |
SUnreclaim | 不可回收 slab |
如果 SUnreclaim 异常高,可能要怀疑内核态内存泄漏或某类内核对象暴涨。
第一阶段不用深挖,知道它属于内核内存即可。
11. /proc/meminfo 要不要两次采样?
和 /proc/stat 不一样。
CPU 使用率需要两次采样,因为 CPU 字段是累计时间。
但 /proc/meminfo 大部分字段是当前时刻的状态量:
当前总内存是多少
当前可用内存是多少
当前 Cached 多少
当前 Dirty 多少
所以内存使用率通常读一次就能算当前状态:
usage = 1 - MemAvailable / MemTotal
但如果要看趋势,也会周期采样:
每 10 秒采一次
↓
观察 MemAvailable 是否持续下降
↓
观察 SwapUsed 是否持续上升
↓
判断是否存在内存泄漏或压力上升
12. 和前两节怎么联动判断问题
现在你已经学了:
/proc/stat -> CPU 使用率 / iowait
/proc/loadavg -> 系统负载
/proc/meminfo -> 内存状态
可以组合诊断:
| 现象 | 可能原因 |
|---|---|
| CPU 高,load 高,MemAvailable 正常 | CPU 计算压力 |
| CPU 不高,load 高,iowait 高 | I/O 阻塞 |
| MemAvailable 持续下降,SwapUsed 上升 | 内存压力或内存泄漏 |
| Dirty/Writeback 高,iowait 高 | 写盘压力大 |
| Cached 高,MemAvailable 也高 | 正常,Linux 在用缓存提速 |
| MemFree 低,但 MemAvailable 高 | 正常,不要误判内存不足 |
13. 放到你的性能监控项目里
项目链路可以这样讲:
Worker 定时读取 /proc/meminfo
↓
解析 MemTotal / MemAvailable / Buffers / Cached / Swap
↓
计算内存使用率
↓
MetricCollector 聚合到 MonitorInfo
↓
MonitorPusher 通过 gRPC Push 到 Manager
↓
HostManager 把内存使用率纳入健康评分
↓
写入 MySQL,QueryService 支持历史趋势查询
你的项目源里明确说低频指标包括 /proc/loadavg、/proc/meminfo、/proc/diskstats,Worker 一轮采样后会统一聚合到 MonitorInfo 再发,不是每个指标单独发 RPC。
项目分析里也提到,Worker 端不是单一采集器,而是 CPU、内存、磁盘、网络、eBPF、用户态监控等多个采集模块组合成总的 MonitorInfo;内存采集会读取 /proc/meminfo 并解析 MemTotal、MemFree、MemAvailable、Buffers、Cached 等字段。
14. 面试官可能会问什么
14.1 为什么 free 显示内存快满了,但系统没问题?
答:
因为 Linux 会尽量把空闲内存用作 page cache 和 buffer,加速文件 I/O。
MemFree低不代表系统真的没有可用内存,很多缓存可以在内存紧张时回收。判断真实内存压力更应该看MemAvailable、Swap 使用情况,以及是否出现持续换页。
14.2 内存使用率应该怎么算?
答:
不建议直接用
MemTotal - MemFree,因为这会把可回收的 page cache 和 buffer 都算成已占用,容易虚高。更合理的是用MemTotal - MemAvailable,即usage = 1 - MemAvailable / MemTotal,这样更接近实际内存压力。
14.3 Buffers 和 Cached 有什么区别?
答:
Buffers更偏块设备和文件系统元数据缓存,Cached更偏文件内容的 page cache。两者都可能在内存紧张时被回收,所以不能简单把它们都当成不可用内存。
14.4 Swap 使用了是不是一定有问题?
答:
不一定。少量 Swap 使用只能说明系统曾经或当前有过内存回收压力。真正危险的是 Swap 使用持续增长,同时伴随 major page fault、磁盘 I/O 升高、响应延迟变大,这通常说明物理内存不足或进程内存泄漏。
15. 小白最小记忆版
你先背这个:
/proc/meminfo 看当前内存状态。
MemTotal 是总内存。
MemFree 只是完全空闲内存,不等于真正可用内存。
Linux 会把空闲内存用作 Buffers/Cached,提高文件 I/O 性能。
MemAvailable 更接近“还能给新程序用多少内存”。
内存使用率推荐:
usage = 1 - MemAvailable / MemTotal。
SwapUsed = SwapTotal - SwapFree。
MemAvailable 持续下降 + SwapUsed 持续上升,说明内存压力变大。
16. 面试版一句话
/proc/meminfo记录 Linux 当前内存状态。监控内存时不能只看MemFree,因为 Linux 会把空闲内存用于 page cache 和 buffer,这些缓存很多在内存紧张时可以回收。更合理的判断方式是看MemAvailable,内存使用率可以按1 - MemAvailable / MemTotal计算。我的项目里 Worker 会读取/proc/meminfo,解析总内存、可用内存、缓存和 Swap 信息,计算内存压力后封装到MonitorInfo,再通过 gRPC 上报给 Manager 做健康评分和历史查询。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)