当前位置:首页 > 文章列表 > 文章 > linux > Linux procfs smaps_rollup 统计进程内存的读取方法

Linux procfs smaps_rollup 统计进程内存的读取方法

来源:17golang原创 2026-10-17 08:21:27 0浏览 收藏

排查 Linux 服务的内存上涨时,如果只看 VmRSS,经常还不够回答“共享库和共享页到底算给谁”。更直接的入口是 /proc//smaps_rollup:它把进程所有内存映射的统计项合并成一份文本,适合做一次采集和趋势记录。

最小结论是:先读取目标 PID 的 smaps_rollup,重点记录 Rss、Pss、Pss_Anon、Pss_File 和 Pss_Shmem,再根据权限错误、PID 消失和字段缺失分别处理。Pss 不是 Rss 的别名,它会按共享页比例分摊,更适合估算进程实际承担的内存。

官方参考地址:https://docs.kernel.org/filesystems/proc.html

smaps_rollup 到底汇总了什么

smaps 会按每个虚拟内存区域列出明细,smaps_rollup 则把这些映射对应字段相加,保留一个汇总入口。Linux Kernel 文档还特别列出了 Pss_Anon、Pss_File 和 Pss_Shmem,它们分别帮助区分匿名页、文件页和共享内存页。

阅读时先抓住三个区别:

  • Rss 表示当前驻留在物理内存中的页总量,共享页会在多个进程的 RSS 中分别出现。
  • Pss 会按共享关系分摊页面,因此多个进程的 PSS 相加通常比直接相加 RSS 更接近整体占用。
  • 所有数值通常以 kB 展示,做监控入库时要保留单位或统一转换,不能把数字直接当作字节。
smaps_rollup 从进程内存映射到 Rss 和 Pss 汇总字段的结构说明图
图1:smaps_rollup 汇总字段与内存映射的结构说明图,不是终端或运行截图。

先用命令读取关键字段

临时排查不必先解析完整 smaps。下面的命令只保留常用汇总项,输出仍是文本示意,实际字段是否存在要以当前内核和权限为准。

# 把目标 PID 换成需要排查的进程号,并只查看汇总字段
pid=1234
grep -E '^(Rss|Pss|Pss_Anon|Pss_File|Pss_Shmem):' "/proc/$pid/smaps_rollup"

# 只看总量时保留第一行之外的关键字段,避免把单位误当成字节
awk '/^(Rss|Pss|Pss_Anon|Pss_File|Pss_Shmem):/ { print $1, $2, $3 }' \
  "/proc/$pid/smaps_rollup"

如果命令返回“权限不允许”,先确认采集进程与目标进程的用户、容器 PID 命名空间和系统的 ptrace 访问限制;如果返回文件不存在,也可能是 PID 已经退出,而不一定是 procfs 没有挂载。不要把一次读取失败直接记成“内存为 0”。

在 Python 中解析并区分失败原因

应用采集时,可以把每一行拆成字段名和带单位的值。读取器只关心汇总文件的键值格式,不依赖字段排列顺序;缺少非核心字段时保留已有结果,便于跨内核版本运行。

from pathlib import Path


def read_smaps_rollup(pid: int) -> dict[str, int]:
    # 只读取指定 PID 的汇总文件,不展开每个 VMA 的 smaps 明细
    path = Path(f"/proc/{pid}/smaps_rollup")
    values: dict[str, int] = {}

    try:
        # 一次读取文本后逐行解析,数值统一保存为 kB
        for line in path.read_text(encoding="utf-8").splitlines():
            if ":" not in line:
                continue
            key, raw = line.split(":", 1)
            parts = raw.split()
            if not parts or parts[0].isdigit() is False:
                continue
            # 只接受内核输出的整数值,避免把异常文本写入指标
            values[key] = int(parts[0])
    except PermissionError as exc:
        # 权限失败要单独上报,不能伪装成进程内存为零
        raise RuntimeError(f"cannot read {path}: permission denied") from exc
    except FileNotFoundError as exc:
        # PID 可能已经退出,也可能位于另一个 PID 命名空间
        raise RuntimeError(f"process {pid} is gone or procfs is unavailable") from exc
    except ProcessLookupError as exc:
        # 进程在读取窗口内退出时,调用方应稍后重试或丢弃本次样本
        raise RuntimeError(f"process {pid} disappeared during collection") from exc

    return values


memory = read_smaps_rollup(1234)
rss_kb = memory.get("Rss", 0)
pss_kb = memory.get("Pss", 0)

这里的返回值仍是 kB。如果监控系统要求字节,可以在写入前统一乘以 1024,但要把字段名写成 rss_bytes、pss_bytes,避免下游误解。Rss 或 Pss 缺失时使用 0 只是代码示例里的默认值,生产采集最好同时记录“字段缺失”状态。

Python smaps_rollup 读取器的字段解析、单位转换和错误出口结构说明图
图2:smaps_rollup 读取器的字段解析与错误边界说明图,不是代码编辑器截图。

权限、PID 消失与接口边界

读取 /proc/ 是观察接口,不是稳定的历史数据库。采集器应把下面三类情况分开记录:

现象更可能的原因处理建议
Permission denied采集身份无权查看目标进程调整采集权限或改用允许的目标范围,不把值写成 0
No such file or directoryPID 已退出、命名空间不同或 procfs 不可用记录采集失败原因,必要时重新枚举 PID
字段不完整内核接口差异、权限或读取窗口问题保留已读字段,并把缺失键作为样本元数据

smaps_rollup 适合回答“一个进程当前承担了多少映射内存”以及“PSS 中匿名页和文件页怎样变化”。它不替代 cgroup 的资源限制统计,也不能告诉你是哪一个具体 VMA 造成了增长;需要定位映射来源时,再按权限和成本评估读取完整 smaps。

采集前后的速查清单

  • 先确认 PID 属于当前采集器可见的 PID 命名空间。
  • 优先记录 Rss、Pss、Pss_Anon、Pss_File、Pss_Shmem 和单位。
  • 权限错误、PID 消失、字段缺失分别打标签,不要统一转换成零值。
  • 趋势采集使用 smaps_rollup,映射级定位再考虑完整 smaps。

相关问题

smaps_rollup 和 status 里的 VmRSS 应该选哪个?

需要快速、低成本的粗略指标时可以看 VmRSS;需要 PSS 及匿名页、文件页拆分时选 smaps_rollup。两者的统计语义和读取成本不同,不建议混成一个指标。

为什么多个进程的 PSS 相加仍然和机器内存不完全一致?

PSS 只描述进程映射相关的分摊结果,内核缓存、不可计入的内存、采集时间差和其他资源仍会造成差异。它更适合比较进程趋势,而不是当作整机内存总账。

读取 smaps_rollup 失败要不要重试?

如果原因是 PID 在采集窗口内退出,短暂重试可能有意义;如果是权限或命名空间错误,重试不会修复根因,应先调整采集身份和可见范围。

把 smaps_rollup 当成“进程级汇总接口”,把 Pss 当成“共享页分摊后的估算”,再把失败原因保留下来,基本就能避免 Linux 内存采集里最常见的误读。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Linux systemd socket activation 的监听交接Linux systemd socket activation 的监听交接
上一篇
Linux systemd socket activation 的监听交接
Linux lsns 怎样按类型和 PID 筛选命名空间
下一篇
Linux lsns 怎样按类型和 PID 筛选命名空间
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    500次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    558次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    587次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    539次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    349次使用