Linux内存从0到1学习笔记(九,内存优化调试之三 - 内存拆解)--- 持续更新

Posted 高桐@BILL

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux内存从0到1学习笔记(九,内存优化调试之三 - 内存拆解)--- 持续更新相关的知识,希望对你有一定的参考价值。

写在前面

我们在日常的工作当中需要各种手段来调试内存,尤其是在内存泄漏的情况下,我们需要一种手段来统计内存的使用去向,以确定内存使用不合理的方向。或者物理内存有限的情况下,需要对内存进行优化,也需要通过一些手段达到对内存的拆解。

一、free命令

free命令用于显示系统中剩余物理内存大小、已使用物理内存大小、交换空间大小和内核使用的缓冲区和缓存大小等信息。这些信息通过解析/proc/meminfo而来,样式如下:

  • total:分两行,分别表示内存总大小,和swap空间总大小;
  • used:已使用物理内存大小,(计算方式 used = total - free - buffers - cache)
  • free:未使用物理内存大小,(来源于/proc/meminfo中的MemFree和SwapFree)
  • shared:tmpfs使用的内存(并非百分百),(来源于/proc/meminfo中的Shmem)
  • buff/cache:buffers和cache的总和
  • buffers:内核缓冲使用的内存(来源于/proc/meminfo中的Buffers)
  • cache:页缓存和slabs使用的内存(来源于/proc/meminfo中的Cached 和SReclaimable)

二、/proc/meminfo

该部分英文原版摘自于《proc(5) - Linux manual page》;其条目并不一定与实际使用的meminfo,可作为参考;

meminfo用于统计当前系统内存使用情况;

2.1 MemTotal %lu

表示实际可用内存总大小(即物理内存 - 保留位 - kernel二进制代码)。

2.2 MemFree %lu

LowFree和HihtFree总大小,这个在我实际使用的linux版本中并没有LowFree和HighFree,因此需要进一步调研学习。我把它理解为系统中完全没有被分配的内存;

2.3 MemAvailable %lu (Linux 3.14引入)

表示可供启动新的应用程序所使用的的内存大小;不包括交换空间;

2.4 Buffers %lu

表示为原始磁盘块所使用的的临时存储区域,不超过20M。有人理解为是用来给文件做缓冲大小,这部分需要再确认下。

2.5 Cached %lu

内存缓存(in-memory cache),用于缓存从磁盘读取文件。不包括交换缓存。

<buffers + cached的值就是可以使用的磁盘高速缓存的大小。>

<buffers + cached = Active(file) + Inactive(file) + Shmem>。

2.6 SwapCached %lu

内存使用交换空间交换出来的内存,但仍然被存放在swapfile中。(如果内存压力比较大的时候,这些内存页不需要再被换出,因为他们已经在交换文件中存在,这就解放了I/O。)

当该交换空间上的其他数据被换出,或是换入内存中的数据被改写,则交换缓存上的记录会被清空。

2.7 Active %lu

表示经常使用的和非必要不会被回收的内存大小,等于Active(anon) + Active(file)的和。

2.8 Inactive %lu

表示不经常使用的和某种原因更容易被回收的内存大小,等于Inactive(anon) + Inactive(file)的和。

2.9 Active(anon) %lu (Linux 2.6.28引入)

表示经常使用的和非必要不会被回收的匿名内存大小。

<匿名内存就是进程中在堆内存上分配的内存,是用malloc分配的内存。>

2.10 Inactive(anon) %lu (Linux 2.6.28引入)

表示不经常使用的和某种原因更容易被回收的匿名内存大小。

2.11 Active(file) %lu (Linux 2.6.28引入)

表示经常使用的和非必要不会被回收的file-backed内存大小,与匿名页的区别在于物理内存的内容是否与物理磁盘上的文件相关联。

<file-backed内存为磁盘高速缓存的内存空间和“文件映射(将物理磁盘上的文件内容与用户进程的逻辑地址直接关联)”的内存空间,其中的内容与物理磁盘上的文件相对应。Linux内核中使用4类LRU表来分别记录对应的这4类内存页,内存页一般以4K为一页。>

2.12 Inactive(file) %lu (Linux 2.6.28引入)

表示不经常使用的和某种原因更容易被回收的file-backed内存大小,与匿名页的区别在于物理内存的内容是否与物理磁盘上的文件相关联。

2.13 Unevictable %lu (Linux 2.6.28引入)(需打开CONFIG_UNEVICTABLE_LRU内核配置项)

表示不能被释放的内存页,这些内存页不能放在LRU表中,而是记录到Unevictable表中。

2.14 Mlocked %lu (Linux 2.6.28 引入)

2.15 HighTotal %lu (Linux 2.6.19引入, 需使能CONFIG_HIGHMEM配置)  

Hightmem所使用的的内存大小。目前所参与开发的版本中大多数的64G内存,这部分已经不常用了。

2.16 HighFree %lu (Linux 2.6.19引入, 需使能CONFIG_HIGHMEM配置)

Hightmem可用的内存大小。

2.17 LowTotal %lu (Linux 2.6.19引入, 配置项CONFIG_HIGHMEM)  

LowMemeory所使用的的内存大小。

2.18 LowFree %lu (Linux 2.6.19引入, 配置项CONFIG_HIGHMEM)  

LowMmeory中可用的内存大小;

2.19 MmapCopy %lu (Linux 2.6.29引入, 配置项CONFIG_MMU)

待归档

2.20 SwapTotal %lu

交换空间的总大小。

2.21 SwapFree %lu

当前交换空间的剩余容量。

2.22 Dirty %lu

脏数据,在磁盘缓冲区中尚未写入物理磁盘的内存大小

2.23 Writeback %lu

在磁盘缓冲区中要被写入物理磁盘的内存大小

2.24 AnonPages %lu (Linux 2.6.18引入)

映射到用户空间页表的匿名页。

Linux内核中存在一个rmap(reverse mapping)机制,负责管理匿名内存中每一个物理内存页映射到哪个进程的哪个逻辑地址这样的信息。 这个rmap中记录的内存页总和就是AnonPages的值。

2.25 Mapped %lu

通过mmap(2)进行文件映射占用的内存大小;

2.26 Shmem %lu (Linux 2.6.32引入)

tmpfs所使用的内存。

tmpfs即利用物理内存来提供RAM磁盘的功能。在tmpfs上保存文件时,文件系统会暂时将它们保存到磁盘高速缓存上,因此它是属于磁盘高速缓存对应的"buffers+cached"一类。 但是由于磁盘上并没有与之对应的内容,因此它并记录在File-backed内存对应的LRU列表上,而是记录在匿名内存的LRU表上。 这就是 buffers + cached = Active(file) + Inactive(file) + Shmem 公式的由来

2.27 KReclaimable %lu (Linux 4.20引入)

内核分配并在内存紧张的时候的内核将要尝试回收的内存大小。包括SReclaimable 和其他注册了shrinker函数分配的内存。

2.28 Slab %lu

slab分配器分配的内存。

Slab分配器针对一些经常分配并释放的对象(如进程描述符)统计各种数据类型的汇总信息,然后为每种数据类型创建多个由多个内存页组成的Slab(这些Slab组成一个Slab列表)。 再在Slab内部划分成一个个相应数据类型的对象。

当内核要使用某种类型的数据结构时,就从对应的slab列表中分配一个对象出去,而当要释放时,将其重新保存在Slab列表中,从而避免内存碎片。

当可供使用的对象不足时,会使用空闲的内存页来创建并添加新的Slab到对应对象的Slab列表中。 相反,若Slab中所有对象都被内核回收,即所有对象都未使用时,根据需要也可以回收Slab,释放成空闲内存。

2.29 SReclaimable %lu (Linux 2.6.19引入)

Slab分配的内存的一部分,这部分可能会被回收,就像缓存一样。

2.30 SUnreclaim %lu (Linux 2.6.19引入)

Slab分配的内存的一部分,在内存进展的情况下也不会被回收。

2.31 KernelStack %lu (Linux 2.6.32引入)

内核栈使用的内存大小

2.32 PageTables %lu (Linux 2.6.18引入)

PageTables就是页表,用于存储各个用户进程的逻辑地址和物理地址的变换关系,它本身也消耗内存空间。

2.33 Quicklists %lu (Linux 2.6.27引入 CONFIG_QUICKLIST配置项)

待归档

2.34 NFS_Unstable %lu (since Linux 2.6.18)

不稳定页表的大小

2.35 Bounce %lu (since Linux 2.6.18)

在低端内存中分配一个临时buffer作为跳转,把位于高端内存的缓存数据复制到此处消耗的内存

2.36 WritebackTmp %lu (since Linux 2.6.26)

FUSE用于临时写回缓冲区的内存

2.37 CommitLimit %lu (since Linux 2.6.10)

系统实际可分配内存总量

2.38 Committed_AS %lu

当前已分配的内存总量

2.39 VmallocTotal %lu

Linux使用内存时,除了使用Slab中配置的对象外,还能直接将空闲内存页映射到逻辑地址上。

这个容量指的是,理论上内核内部可以用来映射的逻辑地址的范围。这个值非常大,但并非实际使用的物理内存

2.40 VmallocUsed %lu(Linux
                     4.4已不再使用)

Linux将空闲内存页映射到逻辑地址上的容量。

值得说明的是,这个容量除了物理内存上所作的映射外,也包括诸如视频卡这样的外部设备内存所作的映射,这类映射叫做"ioremap"

我们可以通过 /proc/vmallocainfo 查看VmallocUsed中包含内存区域的详情

2.41 VmallocChunk %lu(Linux
                     4.4已不再使用)

从Linux4.4版本开始,VmallocChunk字段不再使用

2.42 HardwareCorrupted %lu (Linux 2.6.32引入,CONFIG_MEMORY_FAILURE配置项)

待归档

2.43 LazyFree %lu (Linux 4.12引入)

madvise(2)标记使用的内存大小 ,实际上我没有理解这个是干嘛用的,待进一步调研。(MADV_FREE)
                     .

2.44 AnonHugePages %lu (Linux 2.6.38引入)(CONFIG_TRANSPARENT_HUGEPAGE配置项)  

表示透明巨页面支持的内存大小。

2.45 ShmemHugePages %lu (Linux 4.8引入) (CONFIG_TRANSPARENT_HUGEPAGE 配置项)

通过shmem和tmpfs(5)分配的巨页的内存大小

2.46 ShmemPmdMapped %lu (since Linux 4.8)(CONFIG_TRANSPARENT_HUGEPAGE配置项)

映射到用户空间巨页的共享内存大小。

2.47 CmaTotal %lu (Linux 3.1引入 CONFIG_CMA配置项)

DMA/CMA (Contiguous Memory Allocator) 预留内存总大小

2.48 CmaFree %lu (Linux 3.1引入 CONFIG_CMA配置项)

剩余(Contiguous Memory Allocator) 内存大小。

2.49 HugePages_Total %lu(CONFIG_HUGETLB_PAGE 配置项)

支持的巨页内存总数量

2.50 HugePages_Free %lu(CONFIG_HUGETLB_PAGE配置项)

剩余还未分配的巨页个数

2.51 HugePages_Rsvd %lu (Linux 2.6.17引入)(CONFIG_HUGETLB_PAGE配置项)

已经被分配预留但是还没有使用的巨页数目。

2.52 HugePages_Surp %lu (Linux 2.6.24引入)(CONFIG_HUGETLB_PAGE配置项)

HugePages_Total减去/proc/sys/vm/nr_hugepages中的值

2.53 Hugepagesize %lu (CONFIG_HUGETLB_PAGE配置项)

每单位的巨页的大小,常常为2M。

三、/proc/zoneinfo

四、/proc/buddyinfo

五、/sys/kernel/debug/dma-buf/bufinfo

六、/proc/slabinfo

七、/proc/vmallocinfo

写在最后

这些调试手段并不是最有效,最完善的调试手段。那么我们还有一种调试手段就是page owner。page owner会跟踪统计所有内存分配的去向,及其调用栈。我们单独成篇来介绍这个终极大杀器。

以上是关于Linux内存从0到1学习笔记(九,内存优化调试之三 - 内存拆解)--- 持续更新的主要内容,如果未能解决你的问题,请参考以下文章

Linux内存从0到1学习笔记(九,内存优化调试之一 - kswapd0)

Linux内存从0到1学习笔记(9.6,内存优化调试之page_owner拆解)

Linux内存从0到1学习笔记(9.5,内存优化调试之记录pid到page_owner)

Linux内存从0到1学习笔记(9.10 内存优化调试之panic_on_oom介绍

Linux内存从0到1学习笔记(9.7 内存优化调试之page_owner内存分配堆栈详解)---更新中

Linux内存从0到1学习笔记(11.2 内存优化方案之内存压缩zram)