寫在前面
-
內容涉及 Linux 進程內存監控
-
監控方式包括傳統工具?
ps/top/pmap
?,以及?cgroup
?內存子系統,proc
?內存偽文件系統 -
監控內容包括
進程內存使用情況
,?內存全局數據統計
,內存事件指標
,以及進程內存段數據監控
監控進程的內存使用量
這里分析的工具主要是原生工具,后面還會分享一些 BPF 相關的內存觀察工具以及系統內存的全局監控
PS/TOP
一般的內存監控工具,對于進程級別的,會使用如?ps/top
?命令, 通過指標?VIRT
?或?VSZ
?和?RES
?或?RSS
?來區分兩種不同的統計數據
-
VIRT
?或?VSZ
?代表進程申請的虛擬內存
大小, -
RES
?或?RSS
?代表的是虛擬內存當前實際映射的物理內存
大小,也叫常駐內存。
┌──[root@vms100.liruilongs.github.io]-[~]
└─$top
top - 11:46:44 up 8 min, ?1 user, ?load average: 6.52, 17.45, 10.38
Tasks: 449 total, ? 1 running, 448 sleeping, ? 0 stopped, ? 0 zombie
%Cpu(s): ?0.9 us, ?1.1 sy, ?0.0 ni, 96.8 id, ?0.0 wa, ?0.6 hi, ?0.5 si, ?0.0 st
MiB Mem : ?15730.5 total, ? 7503.6 free, ? 7147.4 used, ? 1079.5 buff/cache
MiB Swap: ? 2068.0 total, ? 2068.0 free, ? ? ?0.0 used. ? 8177.7 avail MemPID USER ? ? ?PR ?NI ? ?VIRT ? ?RES ? ?SHR S ?%CPU ?%MEM ? ? TIME+ COMMAND1947 42418 ? ? 20 ? 0 ?555196 132972 ?20272 S ? 1.3 ? 0.8 ? 0:12.86 heat-engine10320 42436 ? ? 20 ? 0 ?540276 122200 ?17492 S ? 1.3 ? 0.8 ? 0:08.95 nova-scheduler949 root ? ? ?20 ? 0 ?694072 ?31640 ?16876 S ? 1.0 ? 0.2 ? 0:16.58 tuned1945 42415 ? ? 20 ? 0 ?749212 142564 ?34988 S ? 1.0 ? 0.9 ? 0:12.38 glance-api1965 42436 ? ? 20 ? 0 ?540120 121848 ?17324 S ? 1.0 ? 0.8 ? 0:12.16 nova-conductor15567 root ? ? ?20 ? 0 ?269540 ? 5228 ? 4160 R ? 1.0 ? 0.0 ? 0:00.05 top..........................................
所以如果通過上面的命令,查看應用實際使用的內存大小,需要查看?RES(RSS(KB單位))
?列,表示進程當前駐留在物理內存中的內存總量(即沒有被交換到磁盤的部分)。
RSS
?包含的內容:
-
進程獨有的數據(如堆、棧、私有匿名頁)。 + 共享內存頁(如共享庫、共享內存 IPC 等)。
┌──[root@liruilongs.github.io]-[~]
└─$ps?-e -o pid,vsz,rss,comm | awk?'$2 > 0 {print}'PID ? ?VSZ ? RSS COMMAND1 170808 14208 systemd704 ?26824 11520 systemd-journal719 ?34968 12160 systemd-udevd892 ?18156 ?4540 auditd913 ?10796 ?4736 dbus-broker-lau
。。。。。。。。。。4177 ? 6664 ?3712 awk
┌──[root@liruilongs.github.io]-[~]
└─$
共享內存
需要說明的是,進程是共享物理內存頁幀的
。比如使用相同庫函數的兩個進程
,就可以共享使用相同的物理內存頁來存儲庫文件代碼。它們各自的?RSS(Resident Set Size)
?值會將該共享頁的物理內存(SHR 列)
重復計入每個進程的?RSS(RES)
。因此 進程的?RSS 總和 可能會明顯超過 系統實際的物理內存容量
。真實物理內存占用 = ?獨占內存(RES) - 共享內存SHR(Shared Memory)
。
SHR
列 :進程占用的 共享物理內存(如共享庫、共享內存 IPC)。
Cgroup 子系統
通過?Cgroup
?子系統來獲取內存信息,在獲取之前需要獲取當前進程的PID
以及對應的?Cgroup
?分組
獲取?htop
?進程ID, htop 是一個類似 top 的系統整體性能監控的進程
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]?
└─$pgrep?htop
4150
通過 ps 命令獲取 htop 對應的 Cgroup 分組
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]?
└─$ps?-o cgroup 4150
CGROUP
11:pids:/user.slice/user-1000.slice/session-1.scope,
8:memory:/user.slice/user-1000.slice/session-1.scope,
2:devices:/user.slice,
1:name=systemd:/user.slice/user-1000.sli
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]?
└─$
我們只關注內存子系統的,所以直接看內存的分組:?8:memory:/user.slice/user-1000.slice/session-1.scope
,這里的 8 表示 Cgroup 層級
可以通過下面的命令查看?Cgroup
?層級以及 當前系統掛載了多少子系統
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]?
└─$cat?/proc/cgroups
#subsys_name hierarchy num_cgroups enabled
cpuset 4 1 1
cpu ? ? 6 3 1
cpuacct 6 3 1
blkio ? 9 1 1
memory 8 91 1
devices 2 43 1
freezer 13 1 1
net_cls 12 1 1
perf_event 5 1 1
net_prio 12 1 1
hugetlb 7 1 1
pids 11 52 1
rdma 3 1 1
files 10 1 1
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]?
└─$
user.slice/user-1000.slice/session-1.scope
?表示 Cgroup 層級樹
-
user.slice
:表示該 cgroup 屬于 用戶會話層級,與用戶進程相關(與 system.slice 系統服務層級區分) -
user-1000.slice
:表示用戶 ID 為 1000 的普通用戶(Linux 中 UID 1000 通常是首個創建的非 root 用戶) -
session-1.scope
:表示該用戶的 會話單元(如一個終端會話或登錄會話),屬于臨時性資源組(scope 用于管理短生命周期的進程組)
htop
?是一個前臺進程,通過?Cgroup
?資源樹可以很清晰的看到,下面來看下?Cgroup
?內存子系統觀察進程內存信息的一些指標文件
內存詳細信息指標監控
下面一組是內存詳細信息的數據統計
參數 | 作用 |
---|---|
memory.numa_stat | NUMA 節點的內存使用統計 (適用于多 CPU 架構)。 |
memory.stat | 詳細內存使用統計 |
在這之前我們先介紹一個特殊的值,memory.limit_in_bytes?這個可能是我們接觸最多的參數,用于進程 物理內存資源限制
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]?
└─$cat?/sys/fs/cgroup/memory/user.slice/user-1000.slice/session-1.scope/memory.limit_in_bytes
9223372036854771712
可以看到上面的 htop, 文件中的值?9223372036854771712
?表示當前?cgroup
?的內存限制處于無限制狀態,當?cgroup
?未顯式設置內存限制時,內核會默認將此值設為?PAGE_COUNTER_MAX
,該值由內核通過?LONG_MAX / PAGE_SIZE * PAGE_SIZE
?計算得出,確保與內存頁對齊.
memory.stat
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]?
└─$cat?/sys/fs/cgroup/memory/user.slice/user-1000.slice/session-1.scope/memory.stat?
cache 393973760
rss 301170688
rss_huge 171966464
shmem 847872
mapped_file 86605824
dirty 8192
writeback 0
swap 0
pgpgin 241505
pgpgout 113977
pgfault 231305
pgmajfault 260
inactive_anon 302727168
active_anon 147456
inactive_file 348233728
active_file 44892160
unevictable 0
hierarchical_memory_limit 9223372036854771712
hierarchical_memsw_limit 9223372036854771712
total_cache 393973760
total_rss 301170688
total_rss_huge 171966464
total_shmem 847872
total_mapped_file 86605824
total_dirty 8192
total_writeback 0
total_swap 0
total_pgpgin 241505
total_pgpgout 113977
total_pgfault 231305
total_pgmajfault 260
total_inactive_anon 302727168
total_active_anon 147456
total_inactive_file 348233728
total_active_file 44892160
total_unevictable 0
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]?
└─$
以下是關鍵參數的說明
memory.stat
?核心參數解析表
參數分類 | 參數名 | 值(字節) | 說明 | 相關引用 |
---|---|---|---|---|
基礎內存使用 | cache | 393,973,760 | 文件緩存和 tmpfs/shmem 內存,用于加速文件訪問(可回收) | |
rss | 301,170,688 | 進程匿名內存(堆、棧等)占用,反映實際物理內存使用量 | ||
swap | 0 | 當前 cgroup 使用的交換空間大小,非零表示物理內存不足 | ||
內存頁管理 | active_anon | 147,456 | 活躍的匿名內存頁(正在使用的堆、棧內存) | |
inactive_anon | 302,727,168 | 非活躍的匿名內存頁(可被回收的堆、棧內存) | ||
active_file | 44,892,160 | 活躍的文件緩存頁(近期被頻繁訪問的文件數據) | ||
inactive_file | 348,233,728 | 非活躍的文件緩存頁(長時間未訪問的文件數據,優先回收) | ||
內存事件 | pgpgin | 241,505 | 從磁盤換入內存的頁數,高值可能反映頻繁 I/O | |
pgpgout | 113,977 | 從內存換出到磁盤的頁數 | ||
pgmajfault | 260 | 需磁盤 I/O 的硬缺頁次數,高值可能引發性能問題 | ||
層級管理 | hierarchical_memory_limit | 9,223,372,036... | 層級化內存限制(當前值為極大數,表示未啟用限制) | |
total_* ?系列(如? | 與同名參數一致 | 包含當前 cgroup 及其子 cgroup 的總統計值(如? | ||
其他 | rss_huge | 171,966,464 | 透明大頁(THP)占用量,大頁可減少內存管理開銷 | |
unevictable | 0 | 不可回收的內存(如? |
-
單位與換算:上述值均為?字節(Bytes),可通過?
1 GB = 1073741824 Bytes
?轉換為更易讀的單位。例如: ??cache = 393,973,760 Bytes ≈ 376 MB
??rss = 301,170,688 Bytes ≈ 287 MB
-
關鍵場景判斷: ??內存壓力:若?
rss
?接近?hierarchical_memory_limit
,需警惕 OOM(內存耗盡)風險。 ??緩存優化:若?inactive_file
?較高,可通過?sync; echo 3 > /proc/sys/vm/drop_caches
?手動回收緩存。 -
與?
free
/vmstat
?的關系: ??free -m
?中的?buff/cache
?對應?cache + buff
(部分系統可能合并統計)。 ??vmstat
?的?si
/so
?對應?pgpgin
/pgpgout
?的實時動態變化。
如需進一步分析具體進程的內存行為,可結合?/proc/<PID>/smaps
?或工具如?smem
。
memory.numa_stat
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]?
└─$cat?/sys/fs/cgroup/memory/user.slice/user-1000.slice/session-1.scope/memory.numa_stat?
total=169929 N0=169929
file=95978 N0=95978
anon=73951 N0=73951
unevictable=0 N0=0
hierarchical_total=169929 N0=169929
hierarchical_file=95978 N0=95978
hierarchical_anon=73951 N0=73951
hierarchical_unevictable=0 N0=0
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]?
└─$
以下是對?memory.numa_stat
?輸出參數的詳細解釋
參數名 | 類型 | 描述 | |
---|---|---|---|
total | 基礎統計項 | 當前 cgroup 在 NUMA 節點上的總內存占用(單位字節),等于? | |
file | 基礎統計項 | 文件頁緩存(File-backed memory)占用量,例如程序文件、共享庫等通過文件映射的內存 | |
anon | 基礎統計項 | 匿名頁(Anonymous pages)和 Swap 緩存的總量,例如堆、棧等動態分配的內存 | |
unevictable | 基礎統計項 | 不可回收的內存頁(例如被鎖定或標記為不可回收的頁面) | |
hierarchical_total | 層級統計項 | 包含所有子 cgroup 的總內存占用(單位字節),統計范圍覆蓋當前 cgroup 及其子級 | |
hierarchical_file | 層級統計項 | 包含所有子 cgroup 的文件頁緩存總量 | |
hierarchical_anon | 層級統計項 | 包含所有子 cgroup 的匿名頁和 Swap 緩存總量 | |
hierarchical_unevictable | 層級統計項 | 包含所有子 cgroup 的不可回收內存總量 |
補充說明:
-
NUMA 節點標識:輸出中的?
N0=169929
?表示當前統計值屬于 NUMA 節點 0(N0
)。在 NUMA 架構中,每個節點的本地內存訪問速度更快,跨節點訪問會增加延遲。 -
層級統計的意義: 帶?
hierarchical_
?前綴的參數表示當前 cgroup 及其所有子 cgroup 的累積內存使用量。例如,hierarchical_total
?是當前 cgroup 和子 cgroup 在所有 NUMA 節點上的內存總量。 -
應用場景:通過對比?
total
?和?hierarchical_total
,可判斷子 cgroup 的內存分配是否合理。若?unevictable
?值較高,可能需排查是否有進程誤用內存鎖定(如?mlock
)。
上面的輸出信息中提供的輸出中,total=169929 N0=169929
?表示該 cgroup 僅在 NUMA 節點 0 上分配了 169,929 字節內存。其中:
? 文件頁緩存占 95,978 字節(file=95978
),
? 匿名頁和 Swap 緩存占 73,951 字節(anon=73951
),
? 無不可回收內存(unevictable=0
)。
內存事件指標監控
下面為內存事件指標依次來看一下
參數 | 作用 |
---|---|
memory.usage_in_bytes | 當前物理內存使用量 (包括匿名內存、文件緩存等)。 |
memory.memsw.usage_in_bytes | 當前物理內存 + swap 總使用量 。 |
memory.failcnt | 記錄內存限制觸發的失敗次數 (超出? |
memory.events | 內存事件計數器 (如? |
memory.events.local | 同上,但僅統計當前 cgroup(不包含子 cgroup)。 |
這里我們使用?tuned
?這個服務,這是一個系統調優的服務,作為一個獨立的?service unit
?存在,所以會有一個單獨?Cgroup
?分組
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]?
└─$pgrep?tuned
3654
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]?
└─$ps?-o cgroup 3654
CGROUP
11:pids:/system.slice/tuned.service,
8:memory:/system.slice/tuned.service,
2:devices:/system.slice/tuned.service,
1:name=systemd:/system.slice/tuned.service
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]?
└─$
可以在?Cgroup
?路徑下面看到所有的指標數據?/sys/fs/cgroup/memory/system.slice/tuned.service/
,還有部分內核相關的,這里我們只看一下內存相關的
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]?
└─$cat?/sys/fs/cgroup/memory/system.slice/tuned.service/
cgroup.clone_children ? ? ? ? ? ? ? memory.kmem.limit_in_bytes ? ? ? ? ?memory.max_usage_in_bytes ? ? ? ? ? memory.pressure_level
cgroup.event_control ? ? ? ? ? ? ? ?memory.kmem.max_usage_in_bytes ? ? ?memory.memfs_files_info ? ? ? ? ? ? memory.qos_level
cgroup.kill ? ? ? ? ? ? ? ? ? ? ? ? memory.kmem.slabinfo ? ? ? ? ? ? ? ?memory.memsw.failcnt ? ? ? ? ? ? ? ?memory.soft_limit_in_bytes
cgroup.procs ? ? ? ? ? ? ? ? ? ? ? ?memory.kmem.tcp.failcnt ? ? ? ? ? ? memory.memsw.limit_in_bytes ? ? ? ? memory.stat
memory.events ? ? ? ? ? ? ? ? ? ? ? memory.kmem.tcp.limit_in_bytes ? ? ?memory.memsw.max_usage_in_bytes ? ? memory.swappiness
memory.events.local ? ? ? ? ? ? ? ? memory.kmem.tcp.max_usage_in_bytes ?memory.memsw.usage_in_bytes ? ? ? ? memory.usage_in_bytes
memory.failcnt ? ? ? ? ? ? ? ? ? ? ?memory.kmem.tcp.usage_in_bytes ? ? ?memory.min ? ? ? ? ? ? ? ? ? ? ? ? ?memory.use_hierarchy
memory.force_empty ? ? ? ? ? ? ? ? ?memory.kmem.usage_in_bytes ? ? ? ? ?memory.move_charge_at_immigrate ? ? notify_on_release
memory.high ? ? ? ? ? ? ? ? ? ? ? ? memory.limit_in_bytes ? ? ? ? ? ? ? memory.numa_stat ? ? ? ? ? ? ? ? ? ?tasks
memory.kmem.failcnt ? ? ? ? ? ? ? ? memory.low ? ? ? ? ? ? ? ? ? ? ? ? ?memory.oom_control
memory.usage_in_bytes?: 當前 cgroup 中所有進程實際使用的物理內存總量(包括 RSS 和 Page Cache),單位字節(約 15.86 MB)。
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]?
└─$cat?/sys/fs/cgroup/memory/system.slice/tuned.service/memory.usage_in_bytes?
16629760
memory.memsw.usage_in_bytes?: 當前 cgroup 中所有進程使用的物理內存 + Swap 空間的總量(單位字節)。此處與物理內存相等,說明未使用 Swap。
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]?
└─$cat?/sys/fs/cgroup/memory/system.slice/tuned.service/memory.memsw.usage_in_bytes
16629760
memory.failcnt?存使用達到?memory.limit_in_bytes?設定的限制值的次數。值為 0 表示未觸發過內存超限。
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]?
└─$cat?/sys/fs/cgroup/memory/system.slice/tuned.service/memory.failcnt
0
memory.events 內存事件計數器:
-
low: 低內存壓力事件次數
-
high: 高內存壓力事件次數
-
limit_in_bytes: 達到內存限制的次數
-
oom: OOM(內存耗盡)觸發次數。全為 0 表示無相關事件發生。
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]?
└─$cat?/sys/fs/cgroup/memory/system.slice/tuned.service/memory.events
low 0
high 0
limit_in_bytes 0
oom 0
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]?
└─$
當然還有一些其他的參數,感興小伙伴可以研究下,通過去讀上面的參數可以進行性能分析,系統監控
proc 內存偽文件系統
如果需要詳細查看一個進程使用了哪些虛擬地址
,可用使用?pmap PID
?命令或者基于?proc
?內存偽文件系統查看內存詳細信息,比如?/proc/1/status
,/proc/PID/maps
?和/proc/PID/smaps
等,
查看進程詳細內存段數據
pmap 1002
快速查看進程的虛擬內存布局和總占用。
┌──[root@liruilongs.github.io]-[~]
└─$pmap?1002
1002: ? /usr/bin/python3 -Es /usr/sbin/tuned -l -P
0000561ae3586000 ? ? ?4K r---- python3.9?# 文件路徑
0000561ae3587000 ? ? ?4K r-x-- python3.9
0000561ae3588000 ? ? ?4K r---- python3.9
0000561ae3589000 ? ? ?4K r---- python3.9
。。。。。。。。。。。。。。。。
00007ffc6f79b000 ? ?132K rw--- ? [ stack ]?#進程棧。
00007ffc6f7ce000 ? ? 16K r---- ? [ anon ]?#匿名內存(堆、棧等)
00007ffc6f7d2000 ? ? ?8K r-x-- ? [ anon ]
ffffffffff600000 ? ? ?4K --x-- ? [ anon ]total ? ? ? ? ? 256364K
┌──[root@liruilongs.github.io]-[~]
└─$
對應的列分別表示:內存段的起始虛擬地址(如 0000561ae3586000)
。內存段的大小(如 4K)。內存訪問權限 (r)可讀 |(w)可寫 |(x)可執行 |(s)共享 |(p)私有
/proc/1/maps
詳細列出所有內存段的地址范圍、權限和映射文件
┌──[root@liruilongs.github.io]-[~]
└─$cat?/proc/1/maps | head -20
55e05a46b000-55e05a471000 r--p 00000000 fd:00 372298 ? ? ? ? ? ? ? ? ? ? /usr/lib/systemd/systemd
55e05a471000-55e05a47c000 r-xp 00006000 fd:00 372298 ? ? ? ? ? ? ? ? ? ? /usr/lib/systemd/systemd
55e05a47c000-55e05a481000 r--p 00011000 fd:00 372298 ? ? ? ? ? ? ? ? ? ? /usr/lib/systemd/systemd
55e05a482000-55e05a483000 r--p 00016000 fd:00 372298 ? ? ? ? ? ? ? ? ? ? /usr/lib/systemd/systemd
55e05a483000-55e05a484000 rw-p 00017000 fd:00 372298 ? ? ? ? ? ? ? ? ? ? /usr/lib/systemd/systemd
55e05af99000-55e05b2a3000 rw-p 00000000 00:00 0 ? ? ? ? ? ? ? ? ? ? ? ? ?[heap]
7ff43c000000-7ff43c021000 rw-p 00000000 00:00 0
7ff43c021000-7ff440000000 ---p 00000000 00:00 0
7ff444000000-7ff444021000 rw-p 00000000 00:00 0
7ff444021000-7ff448000000 ---p 00000000 00:00 0
7ff44b761000-7ff44b762000 ---p 00000000 00:00 0
7ff44b762000-7ff44bf62000 rw-p 00000000 00:00 0
7ff44bf62000-7ff44bf63000 ---p 00000000 00:00 0
7ff44bf63000-7ff44c766000 rw-p 00000000 00:00 0
7ff44c766000-7ff44c768000 r--p 00000000 fd:00 33948825 ? ? ? ? ? ? ? ? ? /usr/lib64/libffi.so.8.1.0
7ff44c768000-7ff44c76e000 r-xp 00002000 fd:00 33948825 ? ? ? ? ? ? ? ? ? /usr/lib64/libffi.so.8.1.0
7ff44c76e000-7ff44c76f000 r--p 00008000 fd:00 33948825 ? ? ? ? ? ? ? ? ? /usr/lib64/libffi.so.8.1.0
7ff44c76f000-7ff44c770000 ---p 00009000 fd:00 33948825 ? ? ? ? ? ? ? ? ? /usr/lib64/libffi.so.8.1.0
7ff44c770000-7ff44c771000 r--p 00009000 fd:00 33948825 ? ? ? ? ? ? ? ? ? /usr/lib64/libffi.so.8.1.0
7ff44c771000-7ff44c772000 rw-p 0000a000 fd:00 33948825 ? ? ? ? ? ? ? ? ? /usr/lib64/libffi.so.8.1.0
可以看到在上面的基礎上,展示了內存段的起始和結束虛擬地址(如 55e05a46b000-55e05a471000)
。多了映射文件在文件中的偏移量(十六進制,如 00000000)
。文件所在設備的編號(格式 fd:00,主設備號:次設備號)
。文件的?inode 編號(如 372298)
。
/proc/1/smaps
提供每個內存段的詳細物理內存統計(RSS、PSS、共享/私有內存等)
┌──[root@liruilongs.github.io]-[~]
└─$cat?/proc/1/smaps | head -30
55e05a46b000-55e05a471000 r--p 00000000 fd:00 372298 ? ? ? ? ? ? ? ? ? ? /usr/lib/systemd/systemd
Size: ? ? ? ? ? ? ? ? 24 kB
KernelPageSize: ? ? ? ?4 kB
MMUPageSize: ? ? ? ? ? 4 kB
Rss: ? ? ? ? ? ? ? ? ?24 kB
Pss: ? ? ? ? ? ? ? ? ? 7 kB
Shared_Clean: ? ? ? ? 24 kB
Shared_Dirty: ? ? ? ? ?0 kB
Private_Clean: ? ? ? ? 0 kB
Private_Dirty: ? ? ? ? 0 kB
Referenced: ? ? ? ? ? 24 kB
Anonymous: ? ? ? ? ? ? 0 kB
LazyFree: ? ? ? ? ? ? ?0 kB
AnonHugePages: ? ? ? ? 0 kB
ShmemPmdMapped: ? ? ? ?0 kB
FilePmdMapped: ? ? ? ? 0 kB
Shared_Hugetlb: ? ? ? ?0 kB
Private_Hugetlb: ? ? ? 0 kB
Swap: ? ? ? ? ? ? ? ? ?0 kB
SwapPss: ? ? ? ? ? ? ? 0 kB
Locked: ? ? ? ? ? ? ? ?0 kB
THPeligible: ? ?0
VmFlags: rd mr mw me sd
55e05a471000-55e05a47c000 r-xp 00006000 fd:00 372298 ? ? ? ? ? ? ? ? ? ? /usr/lib/systemd/systemd
Size: ? ? ? ? ? ? ? ? 44 kB
KernelPageSize: ? ? ? ?4 kB
┌──[root@liruilongs.github.io]-[~]
└─$
部分字段說明:
-
Size: 內存段的虛擬大小(如 24 kB)。
-
Rss:(Resident Set Size) 實際占用的物理內存(包含共享內存)。
-
Pss:(Proportional Set Size) 按共享比例計算的物理內存(如 3 個進程共享 24KB → 每個進程 Pss 8KB)。
-
Shared_Clean/Shared_Dirty: 共享內存中未修改/已修改的部分。
-
Private_Clean/Private_Dirty: 私有內存中未修改/已修改的部分。
-
Swap: 被交換到磁盤的內存大小。
-
VmFlags: 內存段的屬性標志(如 rd 可讀,mr 可映射,mw 可寫等)。
進程全局內存數據統計
status?用于展示當前進程的一些基本指標,進程基礎信息,權限與身份,信號與中斷等
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]?
└─$cat? /proc/1/status?
Name: systemd
Umask: 0000
State: S (sleeping)
Tgid: 1
Ngid: 0
Pid: 1
PPid: 0
TracerPid: 0
Uid: 0 0 0 0
Gid: 0 0 0 0
FDSize: 256
Groups: ?
NStgid: 1
NSpid: 1
NSpgid: 1
NSsid: 1
VmPeak: ? 165112 kB
VmSize: ? 100636 kB
VmLck: ? ? ? ?0 kB
VmPin: ? ? ? ?0 kB
VmHWM: ? ?12688 kB
VmRSS: ? ?12688 kB
RssAnon: ? ? 4084 kB
RssFile: ? ? 8604 kB
RssShmem: ? ? ? ?0 kB
VmData: ? ?19052 kB
VmStk: ? ? 1036 kB
VmExe: ? ? ?884 kB
VmLib: ? ? 8832 kB
VmPTE: ? ? ? 84 kB
VmSwap: ? ? ? ?0 kB
HugetlbPages: ? ? ? ?0 kB
CoreDumping: 0
THP_enabled: 1
Threads: 1
SigQ: 0/29616
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 7be3c0fe28014a03
SigIgn: 0000000000001000
SigCgt: 00000001000004ec
CapInh: 0000000000000000
CapPrm: 000001ffffffffff
CapEff: 000001ffffffffff
CapBnd: 000001ffffffffff
CapAmb: 0000000000000000
NoNewPrivs: 0
Seccomp: 0
Seccomp_filters: 0
Speculation_Store_Bypass: thread vulnerable
Cpus_allowed: f
Cpus_allowed_list: 0-3
Mems_allowed: 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001
Mems_allowed_list: 0
voluntary_ctxt_switches: 2558
nonvoluntary_ctxt_switches: 483
這里只關注內存相關的
虛擬內存核心指標
參數 | 值 | 描述 | |
---|---|---|---|
VmPeak | 165,112 kB | 進程生命周期內虛擬內存的?峰值(含已分配但未使用的內存),反映進程曾達到的最大內存需求 | |
VmSize | 100,636 kB | 當前進程?虛擬地址空間總大小(包括代碼、數據、堆、棧等所有映射區域),約 98.27 MB |
物理內存核心指標
參數 | 值 | 描述 | |
---|---|---|---|
VmHWM | 12,688 kB | 進程物理內存使用?峰值(Resident Set Size 最大值),約 12.38 MB | |
VmRSS | 12,688 kB | 當前實際駐留物理內存(RSS),等于? | |
RssAnon | 4,084 kB | 匿名頁(動態分配的堆/棧內存)占用的物理內存,例如? | |
RssFile | 8,604 kB | 文件頁緩存占用的物理內存(如加載的共享庫、內存映射文件) | |
RssShmem | 0 kB | 共享內存段(如? |
內存區域細分指標
參數 | 值 | 描述 | |
---|---|---|---|
VmData | 19,052 kB | 數據段 + 堆 ?的虛擬內存大小(動態分配的內存通過? | |
VmStk | 1,036 kB | 棧空間 ?的虛擬內存大小(存放局部變量和函數調用幀),默認上限由? | |
VmExe | 884 kB | 可執行代碼段 ?的虛擬內存大小(程序本身的機器指令,只讀) | |
VmLib | 8,832 kB | 共享庫 ?的虛擬內存大小(如? |
其他關鍵參數
參數 | 值 | 描述 | |
---|---|---|---|
VmLck | 0 kB | 鎖定的物理內存 (通過? | |
VmPTE | 84 kB | 頁表項 ?占用的物理內存(用于管理虛擬地址到物理地址的映射關系) | |
VmSwap | 0 kB | 當前已換出到?Swap 分區?的內存大小(若值持續增長,需排查內存泄漏或物理內存不足) |
關鍵應用場景分析
內存泄漏檢測
-
對比?
VmSize
?和?VmRSS
:若?VmSize
?持續增長而?VmRSS
?穩定,可能為虛擬內存分配過多但未實際使用(如未初始化的?malloc
)。 -
監控?
VmSwap
:若長期非零,需檢查物理內存是否不足或進程存在內存濫用。
性能優化方向
-
共享庫優化:
VmLib
?值較高時,可考慮靜態鏈接或減少動態庫依賴以降低內存開銷。 -
堆棧管理:
VmData
?和?VmStk
?異常增長可能提示堆內存泄漏或遞歸調用過深。
系統資源分配
-
VmHWM
?可用于設置 CGroup 內存限制(memory.max_usage_in_bytes
),避免單個進程耗盡物理內存。 -
RssFile
?較高時,可通過清理緩存(sync; echo 1 > /proc/sys/vm/drop_caches
)釋放非關鍵文件緩存。
statm?用于展示進程內存快照,但需注意 單位是內存頁,通常 1 頁 = 4 KB
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]?
└─$cat? /proc/1/statm
25159 3172 2151 221 0 5022 0
字段解析
參數 | 值 | 描述 | 換算為 KB | |
---|---|---|---|---|
size | 25159 | 進程虛擬地址空間總大小(含代碼、數據、堆棧等所有映射區域) | 25159 × 4 ≈ 100,636 KB | |
Resident | 3172 | 實際駐留物理內存(RSS),即當前進程使用的物理內存總量 | 3172 × 4 ≈ 12,688 KB | |
Shared | 2151 | 共享內存頁數(如動態鏈接庫、共享內存段等被多個進程共享的部分) | 2151 × 4 ≈ 8,604 KB | |
Trs | 221 | 可執行代碼段(Text Resident Set)占用的內存頁(如程序自身的機器指令) | 221 × 4 ≈ 884 KB | |
Lrs | 0 | 庫的內存頁數(Linux 2.6+ 中已廢棄,通常為 0) | - | |
Drs | 5022 | 數據段(堆、全局變量)和用戶態棧的總內存頁 | 5022 × 4 ≈ 20,088 KB | |
dt | 0 | 臟頁數量(已修改但未寫入磁盤的頁,Linux 2.6+ 中已廢棄) | - |
與?/proc/1/status
?的關聯?對比?/proc/1/status
?中的內存參數可驗證數據一致性
??VmSize:?100636 kB
?=?size × 4
?=?25159 × 4
??VmRSS:?12688 kB
?=?Resident × 4
?=?3172 × 4
??RssFile:?8604 kB
?≈?Shared × 4
?=?2151 × 4
??VmExe:?884 kB
?=?Trs × 4
?=?221 × 4
??VmData + VmStk:?19052 + 1036 = 20088 kB
?≈?Drs × 4
?=?5022 × 4
smaps_rollup?提供進程 全局匯總統計(如總 RSS、PSS、Swap 等), 讀取?smaps_rollup
?比遍歷?smaps
?更高效(減少鎖競爭時間),適合高頻監控場景,
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]?
└─$cat? /proc/1/smaps_rollup?
56476fafe000-7ffc5b7f8000 ---p 00000000 00:00 0 ? ? ? ? ? ? ? ? ? ? ? ? ?[rollup]
Rss: ? ? ? ? ? ? ? 12692 kB
Pss: ? ? ? ? ? ? ? ?4648 kB
Pss_Anon: ? ? ? ? ? 3463 kB
Pss_File: ? ? ? ? ? 1184 kB
Pss_Shmem: ? ? ? ? ? ? 0 kB
Shared_Clean: ? ? ? 8540 kB
Shared_Dirty: ? ? ? ?936 kB
Private_Clean: ? ? ? ?64 kB
Private_Dirty: ? ? ?3152 kB
Referenced: ? ? ? ?12692 kB
Anonymous: ? ? ? ? ?4088 kB
LazyFree: ? ? ? ? ? ? ?0 kB
AnonHugePages: ? ? ? ? 0 kB
ShmemPmdMapped: ? ? ? ?0 kB
FilePmdMapped: ? ? ? ? 0 kB
Shared_Hugetlb: ? ? ? ?0 kB
Private_Hugetlb: ? ? ? 0 kB
Swap: ? ? ? ? ? ? ? ? ?0 kB
SwapPss: ? ? ? ? ? ? ? 0 kB
Locked: ? ? ? ? ? ? ? ?0 kB
核心內存統計
參數 | 值 | 描述 | |
---|---|---|---|
Rss | 12,692 kB | 常駐物理內存總量 (包含共享和私有內存),等于? | |
Pss | 4,648 kB | 比例集內存 (按共享比例分攤后的內存), | |
Pss_Anon | 3,463 kB | 匿名頁(如堆、棧)分攤后的內存,反映獨占或部分共享的匿名內存 | |
Pss_File | 1,184 kB | 文件頁緩存(如共享庫、映射文件)分攤后的內存 | |
Pss_Shmem | 0 kB | 共享內存(如? |
共享與私有內存分布
參數 | 值 | 描述 | |
---|---|---|---|
Shared_Clean | 8,540 kB | 共享的未修改內存(如只讀共享庫),可被內核直接回收 | |
Shared_Dirty | 936 kB | 共享的已修改內存(如被多個進程寫入的共享內存),需同步到磁盤后才能回收 | |
Private_Clean | 64 kB | 私有的未修改內存(如未修改的私有數據),可快速回收 | |
Private_Dirty | 3,152 kB | 私有的已修改內存(如進程堆內存),需寫入 Swap 或文件后才能回收 |
其他關鍵參數
參數 | 值 | 描述 | |
---|---|---|---|
Anonymous | 4,088 kB | 匿名內存總量 (無法關聯文件的內存,如? | |
Swap | 0 kB | 已換出到 Swap 分區的內存量,此處為 0 表示未啟用 Swap 或內存充足 | |
Locked | 0 kB | 通過? | |
Referenced | 12,692 kB | 最近被訪問過的內存頁,反映當前活躍內存 |
這是兩個 OOM 內存殺手相關的,這里不多講,在之后的博客中會和小伙伴分享
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]?
└─$cat? /proc/1/oom_score
0
┌──[root@liruilongs.github.io]-[/usr/lib/systemd/system]?
└─$cat? /proc/1/oom_score_adj?
0