嵌入式和服务器Linux系统下free -m Memory统计信息解析(VSS/RSS/PSS/USS)

本文详细解析了Linux系统下free命令输出的内存统计信息,特别是VSS、RSS、PSS和USS的区别和计算,探讨了内核如何区分可回收和不可回收的缓冲/缓存,以及它们对可用内存的影响。通过分析内存使用,了解Linux内核如何管理内存,包括共享内存、缓冲/缓存的分类和回收,以及如何利用工具进行内存泄漏检测和分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在PC/服务器控制台下输入free -m输出如下:

caozilong@caozilong-Vostro-3268:~$ free -m
              总计         已用        空闲      共享    缓冲/缓存    可用
内存:        7869        1389        4713         520        1766        5674
交换:        6808           0        6808
caozilong@caozilong-Vostro-3268:~$ free -m
              总计         已用        空闲      共享    缓冲/缓存    可用
内存:        7869        1388        4706         528        1774        5666
交换:        6808           0        6808
caozilong@caozilong-Vostro-3268:~$ free -m
              总计         已用        空闲      共享    缓冲/缓存    可用
内存:        7869        1389        4705         528        1774        5665
交换:        6808           0        6808
caozilong@caozilong-Vostro-3268:~$ free -m
              总计         已用        空闲      共享    缓冲/缓存    可用
内存:        7869        1659        4263         565        1947        5355
交换:        6808           0        6808
caozilong@caozilong-Vostro-3268:~$ 
​

总计:表示内存总量,保持不变。

已用:表示已经在用的内存,这里包括用户程序使用的内存+系统缓存使用的内存。

空闲:空闲内存数量(真正的空闲,未被任何程序占用)

共享:多个进程共享的内存数量

缓冲/缓存:对应page cache/buffer cache的内存数量,这里面既有不能释放的,也有可以释放的。

可用:可以使用的内存数量,包括缓冲/缓存中可以释放的部分和空下内存两部分构成。

假设系统中的内存总量为M,其中内核占用S,用户私有空间占用UM,用户共享空间占用USM,空闲内存用FM表示。

按照道理,page cache/buffer cache是缓冲区,既然是缓冲区,那么没有也应该没有问题,缓冲/缓存不属于已用内存,所以应该算在可以释放的可用内存之列,所以按照道理:

可用内存=空闲内存+缓冲/缓存内存.

可是当我们按照这种方式计算是,发现不符合,以上面的为例:

5674(可用) < 4713 (空闲)+ 1766 (缓冲/缓存)= 6479

5666 (可用)< 4706(空闲) + 1774(缓冲/缓存) = 6480

5665 (可用) < 4705(空闲) + 1774(缓冲/缓存)   = 6479

5355 (可用) < 4263(空闲) + 1947(缓冲/缓存)   = 6210

原因就在于缓冲/缓存的部分包含不可释放的存储,不能全部算在可用里面,所以前面的公式不太对,应该修正为:

可用内存=空闲内存+缓冲/缓存中的可回收部分内存.

并且可以发现如下规律:

总计≈已用 +空闲 +缓冲/缓存

7869≈1389+4713 + 1766 = 7868

7869≈1388+4706 + 1774 = 7868

7869≈1389+4705 + 1774 = 7868

7869=1659+4263 + 1947 = 7869

至于这种不一致,目前猜测,page cache/buffer cache中,包含一部分可以释放的文件缓冲,还有一部分不能释放的缓冲,所以直接相加的话,会把不能释放的一部分也算在可用内存内,导致计算结果比实际值偏大,至于内核如何区分这两种page cache,待查。

free文档中已经明确给出来了,还推导个啥:

                              Used memory = total - free - buffers - cache

为啥USED memory要这样计算,可能是因为USED内存和场景有关,从广义上说,所有的从BUDDY中分配的PAGE都是USED,但是这些分配出来的PAGE根据是否可回收,又有不同的特点,对于那些作为设备缓存和文件缓存的PAGE,因为有BACKEND存储,是可以回收的,所以这部分PAGE可以根据需要还回去,而对于另外一些PAGE,比如SLAB,和驱动中使用的PAGE,他们无法回收,是真正的USED:

实际上,不同的free版本(procps)计算方法有所不同,有些版本 used memory = total - available. 这相当于将buff/cache中不可释放部分统计到了USED中:

把BUFF/CACHE分开统计free -w

对公式进行演化:

总计≈已用 +空闲 +缓冲/缓存(可回收+不可回收)= 已用 +空闲 +缓冲/缓存(可回收)+缓冲/缓存(不可回收) = 已用 + 缓冲/缓存(不可回收)+ 空闲 +缓冲/缓存(可回收)= 不可用部分+可用部分。

继续演化:

缓冲/缓存 -(总计-可用-已用)+空闲 = 可用

其实就是上面公式的变形,只是这里从可用角度来分析,其中:

总计-可用-已用=缓冲/缓存中的不可回收部分

总计=可用+不可用

不可用部分=已用+缓冲/缓存中的不可回收部分

缓冲/缓存中包含两部分,可回收部分和不可回收部分

不可用部分包括已用和缓冲/缓存中的不可回收部分:

可用部分包括缓冲/缓存中的可回收部分和空闲部分,从缓冲/缓存减去不可以回收的那部分后,再加上空闲部分即是可用部分。

最终,总内存分为可用部分和不可用部分:


经过思考,怀疑这种区分(缓冲/缓存 中存在的不可释放部分)和PAGE页的状态FLAG有关,内核中有一个函数是buffer_busy(bh),所以缓冲/缓存中不可回收部分可能是脏BH数据,PIN数据以及被LOCK的buffer_head数据.这部分BH对应的PAGE是不可回收的。

所以,同样是缓冲区,但是加不加这些FLAG,会造成状态的不同,反映到FREE命令中,有的可以释放,有的不可以释放。

上图中,表示等式

Mem.total = Mem.used + Mem.free + Mem.(page/buffer) cache

缓冲中的不可用部分计算公式为:

缓冲/缓存中的不可用部分=Mem.free+Mem.buff/cache-Mem.avail = 3469860 + 2458400 - 5456168 = 472092

free -h -s 1命令会周期性的执行,按照比较友好的方式输出:

czl@czl-VirtualBox:~$ free -h -s 1
              total        used        free      shared  buff/cache   available
Mem:           981M        744M         66M         13M        169M         84M
Swap:          1.9G        437M        1.4G

              total        used        free      shared  buff/cache   available
Mem:           981M        745M         66M         13M        169M         84M
Swap:          1.9G        437M        1.4G

              total        used        free      shared  buff/cache   available
Mem:           981M        745M         66M         13M        169M         84M
Swap:          1.9G        437M        1.4G

              total        used        free      shared  buff/cache   available
Mem:           981M        745M         66M         13M        169M         84M
Swap:          1.9G        437M        1.4G

              total        used        free      shared  buff/cache   available
Mem:           981M        745M         66M         13M        169M         84M
Swap:          1.9G        437M        1.4G

^C
czl@czl-VirtualBox:~$ 

经过计算确认,符合

Mem.total = Mem.used  + Mem.free + Mem.buff/cache

981M≈745M+66M+169M

from this equation view, we can clucude that:

Mem.buff/cache = shared + Mem.buf/cache(cant be freed) + Mem.buf/cache(can be freed).

shared + Mem.buf/cache(cant be freed) cant be freed, some of the cache buffer can be freed. so in this way:

可用内存 - (空闲内存+缓冲/缓存内存) = shared + Mem.buf/cache(cant be freed).

that will be resonable.

以上猜想在<<奔跑吧,Linux内核>>卷一中得到证实,在这本书中对各个成员的描述如下:

total:计算机中总的内存,这里有两种内存,一种是mem,一种是swap.前者是真实的物理内存,后者可以是某个磁盘文件,或者单个磁盘分区。

used:程序使用的内存大小.

free:未分配的物理内存大小.

shared:共享内存的大小,主要用于进程间通信.

buff/cache:buff指的是缓冲器,用于缓存输出到块设备的数据 buffer cache,而cache指的是page cache,用于缓存打开的文件,以提高访问文件的速度。

available:这是free命令新加的一个选项,当内存短缺时,系统可以回收buff和cache,那么avaiable = free + buff+ cache,这样做也不完全精确,因为在现在的linux内核中,不是所有的buffer和cache都可以回收,如共享内存段,tmpfs和ramfs等都属于不可回收的.所以这个公式应该变成:available = free + buff + cache -  不可回收的部分.

2024-01-15: 上面的总结可能有点问题,shared 不应该全部被算到Mem.buff/cache里面,因为除了文件共享,还有一些纯粹是进程之间BUFFER共享的部分。

2024-01-16:2024-01-15的总结不对,shared部分应该全部在mem.buf/cache里面,共享文件不可能是SHARED,SHARED的包含IPC的部分和匿名共享映射的部分,这部分都是可以交换出去的。

2024-01-16:在三思考后,经过测试:

  1. 写一个应用不断malloc,之后memset触发页分配一段大内存,free查看,buff/cache没有变化,而used猛增,所以匿名页面占用的是used,不是buff/cache.

  2.同样的方式测试匿名共享页面

  ptr = map(NULL, FILE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);memset(ptr, 0x5a, FILE_SIZE);

不断循环执行,发现此时的USED不变,但是BUFF/CACHE激增,所以SHARED是 BUFF/CACHE的一部分。

由于MAP_SHARED FLAG的匿名页面,用的vm_ops是shmem_vm_ops,其PAGE FAULT中是从SHMEM分配页面的,其调用路径上的关键函数shmem_add_to_page_cache:将分配的页面增加到了NR_FILE_PAGES和NR_SHMEM上面:

所以可以得到,SHARED的确实是BUFF/CACHE的一部分,不是USED的一部分,最早的说法更对。

3.实验3,将实验2的MAP 属性修改为MAP_PRIVATE | MAP_ANONYMOUS 在做测试,发现此时递增的不再是BUFF/CACHE,而是USED,这就和实验1,MALLOC的方式一样了。所以,匿名页面算在USED之内,SHARED页面算在BUFF/CACHE之内。

如何优化缓冲,缓存部分?

使用如下命令,命令会遍历所有文件系统中的超级块,将注册在超级块中的inode节点文件对应的page cache回刷到磁盘,释放page cache.

echo 3 > /proc/sys/vm/drop_caches
<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

papaofdoudou

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值