Linux 性能实战 | 附录:动态链接库是如何影响多个进程内存占用的?

在 Linux 内存分析中,很多工程师都会遇到一个现象:

ps aux | grep my_program

发现多个进程的 RSS 都很大,例如:

进程A RSS = 200MB
进程B RSS = 200MB
进程C RSS = 200MB

直觉上会认为系统用了:

600MB 内存

但实际物理内存可能只增加了:

220MB

为什么会这样?

答案就是:shared page(共享页)

而 shared page 最常见的来源,就是 动态链接库 (.so)

这篇文章将从工程角度,彻底讲清楚:

  • 什么是 shared page
  • 动态链接库如何产生 shared page
  • 为什么多个进程 RSS 很大,但实际内存没增加多少
  • RSS / PSS / USS 的本质区别

一、shared page 是什么?

一句话定义:

shared page = 多个进程映射到同一个物理内存页

关键点:

  • 每个进程有自己的虚拟地址空间
  • 但不同进程的虚拟页,可以指向同一个物理页

示意图:

PhysicalMemory

ProcessB

ProcessA

virtual page

virtual page

physical page

结果:

两个进程
共享同一份物理内存

不是复制。


二、shared page 最常见来源:动态链接库 (.so)

例如系统中的:

/lib/x86_64-linux-gnu/libc.so.6
/lib/x86_64-linux-gnu/libstdc++.so.6

当程序启动:

./my_program

Linux 不会把 libc.so 复制进进程。

而是通过:

mmap("libc.so", MAP_SHARED)

把文件映射进内存。

流程:

Program

Loader

mmap

PageCache

ProcessA

ProcessB

关键:

多个进程共享 page cache 中的物理页

三、核心机制:page cache

Linux 有一个全局结构:

page cache

作用:

缓存文件内容对应的物理页

例如:

libc.so

只加载一次:

libc.so on disk

physical pages

ProcessA

ProcessB

ProcessC

结果:

100个进程
只使用一份物理内存

四、为什么 RSS 看起来很大?

RSS 定义:

RSS = 进程映射的物理页数量

注意:

RSS 不关心页是否共享

示例:

libc.so 占用:

10MB

运行 100 个进程:

每个进程:

RSS += 10MB

但真实物理内存:

仍然是 10MB

不是:

1000MB

五、PSS 才是真实物理占用的更好指标

PSS 定义:

PSS = shared page 按进程数量平均分配

示例:

libc.so = 10MB
进程数 = 10

每个进程:

PSS = 1MB

系统总 PSS:

10MB

符合真实物理内存。


六、USS:进程真正独占的内存

USS 定义:

USS = 进程独占页

不包含:

shared page

示例:

heap = 50MB
shared libc = 10MB

结果:

RSS = 60MB
PSS ≈ 51MB
USS = 50MB

七、动态链接库为什么可以共享?

因为动态库是:

文件-backed memory
read-only

Linux 可以安全共享。

而不是:

匿名内存(heap)

匿名内存不能共享。


八、如果使用静态链接,会发生什么?

静态链接:

gcc main.c -static

结果:

每个进程:

都有一份 libc 副本

示意:

ProcessC

libcC

ProcessB

libcB

ProcessA

libcA

无法共享。

内存占用:

线性增长

九、fork 也会产生 shared page(Copy-on-Write)

fork 后:

Parent

Page

Child

共享同一页。

只有写入时:

才复制

这叫:

Copy-on-Write

十、如何查看 shared page?

查看:

cat /proc/<pid>/smaps

示例:

Shared_Clean: 2048 kB
Private_Clean: 0

说明:

全部共享

推荐工具:

smem -r

输出:

PID RSS PSS USS

十一、shared page 如何影响 RSS / PSS / USS

关系图:

not counted

not counted

libc.so

physical pages

ProcessA

ProcessB

RSS includes

RSS includes

PSS split

PSS split

USSA

USSB

总结:

指标 是否包含 shared
RSS 包含
PSS 按比例
USS 不包含

十二、工程中的典型误解

误解:

RSS 大 = 内存真的占用大

正确理解:

RSS 包含 shared page

真实占用更接近:

PSS
或
USS

十三、一个真实工程案例

系统运行:

100 个 nginx worker
每个 RSS = 50MB

直觉:

5000MB

实际:

物理内存 ≈ 800MB

原因:

libc
libssl
libcrypto
共享

十四、总结

shared page 本质:

多个进程共享 page cache 中的物理页

主要来源:

动态链接库 (.so)
mmap 文件
fork (COW)

对内存指标影响:

RSS 包含 shared
PSS 按比例分摊
USS 只统计独占

工程实践建议:

看真实内存占用:

优先看 PSS
其次看 USS
不要只看 RSS

在这里插入图片描述

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐