news 2026/7/4 3:14:20

第六篇:《内存分析工具:vmstat、smem、pmap、Valgrind》

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
第六篇:《内存分析工具:vmstat、smem、pmap、Valgrind》

理解了内存管理的原理之后,需要用工具把理论“可视化”。内存分析工具链可以分为三个层次:系统级(vmstat,看整体趋势)、进程级(smem、pmap,看具体进程的内存分布)和代码级(Valgrind,检测内存泄漏)。本文深入讲解这四个核心工具的使用方法和实战技巧,帮你从“内存不够”的模糊感觉,精准定位到“哪个进程的哪段代码在泄漏内存”。

一、vmstat:系统级内存“气象雷达”
vmstat(Virtual Memory Statistics)是最常用的系统级监控工具,可以报告进程、内存、分页、块 I/O、中断和 CPU 活动等信息。

1.1 基本用法

# 每 1 秒刷新一次,共输出 5 次vmstat15

输出示例:

procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpdfreebuff cache si so bi boincs us syidwa st1010240500002000030000000102050080002556820201024049000200003001000001060085003056320

1.2 内存相关字段详解

💡 核心判断:si 和 so 是内存是否充足的最直接指标。只要这两个值长期为 0,即使 free 很少,系统也不算内存不足。一旦 si/so 持续大于 0,说明系统已经在频繁使用 Swap,内存已经成为瓶颈。

1.3 实战:判断内存是否充足

# 持续监控 10 秒vmstat110

观察:

如果 si 和 so 始终为 0 → 内存充足,即使 free 看起来很少。

如果 si 和 so 间歇性 > 0 → 内存偶尔不足,需要关注。

如果 si 和 so 持续 > 0 → 内存严重不足,需要扩容或优化。

二、smem:比 RSS 更准确的内存统计
2.1 RSS 的局限性
传统的 top 或 ps 使用 RSS(Resident Set Size,常驻内存集) 来衡量进程的内存占用。但 RSS 有一个重大缺陷:它会把共享内存完整地计入每个进程。

例如,两个进程都使用了同一个共享库(如 libc.so),该库在物理内存中只有一份拷贝,但 RSS 会把它分别计入两个进程的统计中。这会导致所有进程的 RSS 之和远大于系统实际使用的物理内存。

2.2 smem 的三个核心指标
smem 提供了三种内存度量:

大小关系:VSS >= RSS >= PSS >= USS

💡 实践建议:PSS 是最接近真实内存占用的指标。当你想知道“这个进程到底占了多少内存”时,看 PSS。USS 则适合评估“如果杀掉这个进程,能释放多少内存”。

2.3 安装与基本用法

# Ubuntu/Debiansudoaptinstallsmem# CentOS/RHEL(需启用 EPEL)sudoyuminstallepel-releasesudoyuminstallsmem

显示所有进程的内存使用(按 PSS 排序) :

smem-r

显示指定进程:

smem-p-Pnginx# -P 按进程名过滤

按用户汇总:

smem-u

输出示例(关键列):

$ smem-rPID User Command Swap USS PSS RSS1234root /usr/bin/nginx01024204840965678www-data /usr/sbin/php-fpm0163841843224576

注意观察 RSS 和 PSS 的差异——对于使用了大量共享库的进程,RSS 可能比 PSS 大 50% 以上。

三、pmap:进程内存分布的“X 光片”
pmap 命令可以显示一个进程的详细内存映射,告诉你进程的每一段内存从哪里来、有多大、权限是什么。

3.1 基本用法

pmap-x<PID>

-x 选项显示扩展信息(包括 RSS 和脏页大小)。

输出示例:

$ pmap-x12341234: /usr/bin/nginx Address Kbytes RSS Dirty Mode Mapping 0000555555554000100920r-x-- nginx 000055555556e000444r---- nginx 000055555556f000444rw--- nginx 00007f123456700020483232rw---[anon]... total Kbytes204804096512

3.2 各列含义

3.3 实战:定位内存泄漏
当一个进程的内存持续增长时,用 pmap 可以观察增长发生在哪个段:

# 第一次采集pmap-x1234>/tmp/pmap_1.txt# 等待一段时间(如 10 分钟)# 第二次采集pmap-x1234>/tmp/pmap_2.txt# 对比差异diff/tmp/pmap_1.txt /tmp/pmap_2.txt

如果 [anon](匿名内存,即堆)持续增长 → 可能是堆内存泄漏(如 malloc 后未 free)。

如果某个文件映射(Mapping)持续增长 → 可能是文件缓存未释放或内存映射文件泄漏。

如果共享库的 RSS 增长 → 可能是共享库内部的状态泄漏。

四、Valgrind:代码级内存问题“侦探”
vmstat 告诉你“内存不够”,smem 告诉你“哪个进程占内存”,pmap 告诉你“内存分布在哪里”。但如果问题是内存泄漏(malloc 了但忘记 free),你需要 Valgrind 来定位到具体的代码行。

4.1 Valgrind 的核心工具:Memcheck
Memcheck 是 Valgrind 中最常用的工具,可以检测:

内存泄漏(Memory Leaks)

使用未初始化的内存

使用已释放的内存(Use-After-Free)

内存越界访问(Buffer Overflow)

4.2 基本用法

# 使用 Memcheck 运行程序valgrind --leak-check=full ./my_program# 输出泄漏摘要到文件valgrind --leak-check=full --log-file=valgrind.log ./my_program

输出示例(泄漏摘要):

text
12345LEAK SUMMARY:
12345definitely lost: 1024 bytes in 1 blocks
12345indirectly lost: 512 bytes in 2 blocks
12345possibly lost: 0 bytes in 0 blocks
12345still reachable: 4096 bytes in 10 blocks
definitely lost:明确泄漏,必须修复。

indirectly lost:间接泄漏(指向泄漏内存的指针本身也泄漏了)。

possibly lost:可能泄漏(指针指向内存块的中间位置)。

still reachable:程序退出时仍有指针指向,但未释放——通常不是问题(全局变量等)。

4.3 定位泄漏代码行
要定位到具体的代码行,需要在编译时加入调试信息:

# 编译时加 -ggcc-g-omy_program my_program.c# 运行 Valgrindvalgrind --leak-check=full --show-leak-kinds=all ./my_program

Valgrind 会输出类似:

text
123451024 bytes in 1 blocks are definitely lost in loss record 5 of 10
12345at 0x4C2BBA0: malloc (vg_replace_malloc.c:299)
12345by 0x4005A4: create_buffer (my_program.c:42)
12345by 0x4005E8: main (my_program.c:58)
这告诉你:泄漏发生在 my_program.c 的第 42 行 create_buffer 函数中。

4.4 Valgrind 的局限性

五、四个工具的协同使用流程
当遇到内存问题时,按照“从宏观到微观”的顺序使用这四个工具:

text
第1步:vmstat 1 10
↓ 观察 si/so 是否 > 0,判断内存是否真的不足
第2步:smem -r
↓ 找出 PSS 最大的进程,确定“嫌疑进程”
第3步:pmap -x
↓ 查看该进程的内存分布,判断是堆泄漏还是文件映射泄漏
第4步:根据语言选择代码级工具
├── C/C++ → Valgrind
├── Java → JVisualVM / MAT
└── Go → pprof
六、小结
vmstat:系统级监控,si/so 是判断内存是否充足的最直接指标。

smem:比 RSS 更准确的进程内存统计,PSS 是最接近真实占用的指标。

pmap:查看进程的内存映射,定位内存增长发生在哪个段。

Valgrind:代码级内存问题检测,定位泄漏的具体代码行。

这四个工具构成了从系统到代码的完整内存分析工具链。熟练掌握它们,你就能从“内存不够”的模糊感觉,精准定位到具体的问题根源。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/4 3:14:01

个人AI聊天机器人真的必要吗?三重过滤网评估技术适配度

1. 这不是又一个“AI聊天机器人教程”&#xff0c;而是一次对技术存在意义的诚实复盘“Rethinking the Necessity of Personal AI Chatbots in Modern Society”——这个标题里没有一行代码&#xff0c;不提任何模型参数&#xff0c;也没列一个部署步骤。它问的是一个被我们集体…

作者头像 李华
网站建设 2026/7/4 3:12:29

深入AI生产实践下,关于AI产品边界的深刻认识

一、局限性任何模型都永远存在三种局限性&#xff0c;即知识边界、推理边界、行为边界&#xff0c;只是对于不同模型有不同程度的体现。 1、知识边界&#xff1a;由于模型在特定任务下缺少相应的知识&#xff0c;而使用其泛化的理解力以实现目的&#xff0c;出现不稳定及不精准…

作者头像 李华
网站建设 2026/7/4 3:08:47

Direct3D Draw函数 异步调用原理解析

我们知道&#xff0c;实际渲染的过程大部分是在GPU上完成的&#xff0c;CPU只负责发号施令。实际上&#xff0c;数据准备完成后&#xff0c;当你的程序调用了Draw函数后&#xff0c;CPU才会真正的将数据和命令提交到GPU上进行渲染。从命令提交到渲染完成通常需要数十毫秒的时间…

作者头像 李华
网站建设 2026/7/4 3:05:45

一文了解电涡流传感器应用和发展趋势

前言涡流传感作为近年国内外传感器发展的热门领域之一&#xff0c;日益得到重视和应用。涡流传感器可以实现非接 触测量金属导体表面多种物理量&#xff0c;具有结构简单&#xff0c;灵敏度高&#xff0c;频率响应宽&#xff0c;不受油污等介质影响&#xff0c;抗干 扰能力强等…

作者头像 李华
网站建设 2026/7/4 3:04:11

像这样玩C#

我们玩技术&#xff0c;不是被技术玩。Coding是快乐的&#xff0c;而非苦逼的。.Net/C# 这个神器竟然天天有人吐槽。看不下去鸟。在top10语言中&#xff0c;C#是最优美的语言&#xff0c;没有之一。在top10语言中&#xff0c;C#所可用的标准库及可获得其它库是最强大的之一&…

作者头像 李华