原文:Linux内存参数详细说明(free+/proc/meminfo) - 付杰博客
思考:linux内存占用率多少?linux内存使用率多少?以及还剩下多少内存?哪个程序应用占得最多?......等等。
一般我们用 free+/proc/meminfo 就基本上可以了解以上所有的东西了。因此,这里重点就以这两个命令为主了。就算你用其它命令也一样,原理也都是相同的,参数结果意思也是一样的。
一、Linux内存命令:free 参数详细解释
在 Linux 下 free 命令可以看出系统当前内存状况。以某台 Linux Ecs 为例,运行 free -m 后的输出如下:
[root@localhost ~]# free -m
total used free shared buff/cache available
Mem: 3789 229 621 0 2937 3261
Swap: 0 0 0
1、首先看行:
Mem :表示物理内存统计
Swap :表示硬盘上交换分区的使用情况
注意:系统的总物理内存:3789M,但系统当前真正可用的内存并不是第一行 free 标记的 621M,它仅代表未被分配的内存。
2、接下来看列:
total :总计物理内存的大小。
used :已使用多大。
free :可用有多少。
Shared :多个进程共享的内存总额。
Buffers/cached :磁盘缓存的大小。
二、Linux内存命令:/proc/meminfo 参数详细解释
我们还可以查看Linux内存更加复杂的东西,例如:
cat /proc/meminfo MemTotal: 3880404 kB //总内存 MemFree: 637548 kB //空闲内存 MemAvailable: 3340664 kB Buffers: 178760 kB //给文件的缓冲大小 Cached: 2535436 kB //高速缓冲存储器使用的大小 SwapCached: 0 kB //被高速缓冲存储用的交换空间大小 Active: 1370440 kB //活跃使用中的高速缓冲存储器页面文件大小 Inactive: 1506936 kB //不经常使用的高速缓冲存储器页面文件大小 Active(anon): 163452 kB Inactive(anon): 216 kB Active(file): 1206988 kB Inactive(file): 1506720 kB Unevictable: 0 kB Mlocked: 0 kB SwapTotal: 0 kB //交换空间总大小 SwapFree: 0 kB //空闲交换空间 Dirty: 76 kB //等待被写回到磁盘的大小 Writeback: 0 kB //正在被写回的大小 AnonPages: 163320 kB //未映射的页的大小 Mapped: 65100 kB //设备和文件映射的大小 Shmem: 492 kB Slab: 294180 kB //内核数据结构缓存的大小,可减少申请和释放内存带来的消耗 SReclaimable: 278620 kB //可收回slab的大小 SUnreclaim: 15560 kB //不可收回的slab的大小15560 + 278620 = 294180 KernelStack: 2624 kB PageTables: 5720 kB //管理内存分页的索引表的大小 NFS_Unstable: 0 kB //不稳定页表的大小 Bounce: 0 kB WritebackTmp: 0 kB CommitLimit: 1940200 kB Committed_AS: 586464 kB VmallocTotal: 34359738367 kB //虚拟内存大小 VmallocUsed: 14160 kB //已经被使用的虚拟内存大小 VmallocChunk: 34359715580 kB HardwareCorrupted: 0 kB AnonHugePages: 10240 kB CmaTotal: 0 kB CmaFree: 0 kB HugePages_Total: 0 //大页面的分配 HugePages_Free: 0 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 2048 kB DirectMap4k: 98176 kB DirectMap2M: 4096000 kB DirectMap1G: 2097152 kB |
1、MemTotal:内存总数
系统从加电开始到引导完成,BIOS等要保留一些内存,内核要保留一些内存,最后剩下可供系统支配的内存就是MemTotal。这个值在系统运行期间一般是固定不变的。
2、MemFree:空闲内存数
表示系统尚未使用的内存。MemUsed=MemTotal-MemFree 就是已被用掉的内存。
3、MemAvailable:可用内存数
应用程序可用内存数。系统中有些内存虽然已被使用但是可以回收的,比如cache/buffer、slab都有一部分可以回收,所以MemFree不能代表全部可用的内存,这部分可回收的内存加上MemFree才是系统可用的内存,即:MemAvailable≈MemFree+Buffers+Cached,它是内核使用特定的算法计算出来的,是一个估计值。它与MemFree的关键区别点在于,MemFree是说的系统层面,MemAvailable是说的应用程序层面。
通过cat /proc/meminfo取得物理内存信息
/proc/meminfo信息打印的地方在[kernel/msm-5.4/fs/proc/meminfo.c]的meminfo_proc_show函数当中;其中主要是调用show_val_kb()函数将字符串和具体的数值凑成一个字符串,然后把这些字符串打印出来。
MemTotal
物理内存大小。MemTotal并不等于所有内存条内存容量之和,是因为在系统加电之后,firmware和kernel本身需要占用一些内存,这些占用的内存不会被统计到meminfo文件当中,因此MemTotal表示的内存大小是去掉了这些内存之后剩余可供系统使用的物理内存总大小,在系统运行过程中,MemTotal的值固定不变。
MemFree
当前系统的空闲内存大小,是完全没有被使用的内存
MemAvailable
可用内存大小。MemFree表示的是当前系统的空闲内存大小,而MemAvailable表示的是当前系统的可用内存大小,这两个的含义是不同的。MemFree表示完全没有被使用的内存。但是实际上来说我们能够使用的内存不仅仅是现在还没有被使用的内存,还包括目前已经被使用但是可以被回收的内存,这部分内存加上MemFree才是我们实际可用的内存,cache、buffer、slab等其中都有一部分内存可以被回收,MemAvailable就是MemFree加上这部分可回收的内存之后的结果,当然因为这部分可回收的内存当前还没有被回收,因此只能够通过算法来估算出这部分内存的大小,所以MemAvailable是一个估算值,并不是真实的统计值。
Buffers
直接对块设备进行读写操作使用的缓存。主要包括:直接读写块设备,文件系统元数据(比如superblock,不包括文件系统中文件的元数据)。它与Cached的区别在于,Cached表示的普通文件的缓存。
Buffers占用的内存存在于lru list中,会被统计到Active(file)或者Inactive(file)中。
Cached
Cached是所有的文件缓存,Cached是Mapped的超集。Cached中不仅包含了mapped的页面,也包含了unmapped的页面。当一个文件不再和进程关联之后,在pagecache中的页面不会被马上回收,仍然存在于Cached中,还保留在lru list上,但是Mapped不再统计这部分内存。
Cached还包含tmpfs中文件,以及shared memory,因为shared memory在内核中也是基于tmpfs来实现的。
SwapCached
匿名页在必要的情况下,会被交换到Swap中,shared memory和tmpfs虽然不是匿名页,但是它们没有磁盘文件,所以也是需要交换分区的,为了方便说明,在这里我们将匿名页、shared memory和tmpfs统称为匿名页。因此SwapCached中可能包含有AnonPages和Shmem。SwapCached可以理解为是交换区设备的page cache,只不过page cache对应的是一个个的文件,而swapcached对应的是一个个交换区设备。
并不是每一个匿名也都在swap cache中,只有以下情况中匿名页才在swap cache中:
1)匿名页即将被交换到swap分区上,这只存在于很短的一个时间段中,因为紧接着就会发生pageout将匿名页写入交换分区,并且从swap cache中删除;
2)曾经被写入到swap分区现在又被加载到内存中的页会存在与swap cache,直到页面中的内容发生变化,或者原来用过的交换分区空间被回收。
SwapCached实际的含义是:系统中有多少匿名页曾经被swap-out,现在又被swap-in并且swap-in之后页面中的内容一直没有发生变化。也就是说,如果这些页需要被重新swap-out的话,是不需要进行IO操作的。
需要注意的是,SwapCached和Cache是互斥的,二者没有交叉。当然SwapCached也是存在于lru list中的,它和AnonPages或者Shmem有交集。
Active
lru list组中active list对应的内存大小,这主要包括pagecache和用户进程的内存,不包括kernel stack和hugepages。active list中是最近被访问的内存页。
Active(anon)和Active(file)分别对应LRU_ACTIVE_ANON和LRU_ACTIVE_FILE这两个lru list,分别表示活跃的文件内存页和匿名页,它们的加和等于Active。文件页对应着进程的代码、映射的文件,匿名页对应的是如进程的堆、栈等内存。文件页在内存不足的情况下可以直接写入到磁盘上,直接进行pageout,不需要使用到交换分区swap,而匿名页在内存不足的情况下因为没有硬盘对应的文件,所以只能够写入到交换区swap中,称为swapout。
Inactive
lru list组中inactive list对应的内存大小,也是包括pagecache和用户进程使用的内存,不包括kernel stack和hugepages。Inactive list中是最近没有被访问的内存页,也是内存自动回收机制能够回收的部分。
Inactive(anon)和Inactive(file)分别对应LRU_INACTIVE_ANON和LRU_INACTIVE_FILE这两个例如list,分别表示最近一段时间没有被访问的匿名页和文件页内存,他们的加和等于Inactive。
Unevictable
Unevictable对应的是LRU_UNEVICTABLE链表中内存的大小,unevictable lru list上是不能够pageout和swapout的内存页。
Mlocked
Mlocked统计的是被mlock()系统调用锁定的内存大小,被锁定的内存因为不能够pageout/swapout,它是存在于LRU_UNEVICTABLE链表上。当然LRU_UNEVICTABLE链表上不仅包含Mlocked的内存。
Dirty
Dirty并未完全包括系统中所有的dirty pages,系统上所有的dirty pages应该还包括NFS_Unstable和Writeback,NFS_Unstable是发送给了NFS Server当时没有写入磁盘的缓存页,Writeback是正准备写磁盘的缓存。
AnonPages
AnonPages统计了匿名页。需要注意的是,shared memory和tmpfs不属于匿名页,而是属于Cached。Anonymous pages是和用户进程相关联的,一旦进程退出了,匿名页也就被释放了,不像是page cache,进程退出后仍然可以存在于缓存中。
AnonPages中包含了THP使用的内存。
Mapped
Mapped是Cached的一个子集。Cache中包含了文件的缓存页,这些缓存页有一些是与正在运行的进程相关联的,如共享库、可执行文件等,有一些是当前不在使用的文件。与进程相关联的文件使用的缓存页就被统计到Mapped中。
进程所占的内存分为anonymous pages和file backed pages,所以理论上来讲:
所有进程占用的PSS之和 = Mapped + AnonPages
Shmem
Shmem统计中的内存是shared memory和tmpfs、devtmpfs之和,所有的tmpfs文件系统使用的空间都算入共享内存中。devtmpfs是/dev文件系统类型,也属于一种内存文件系统。
shared memory存在于shmget、shm_open和mmap(…MAP_ANONYMOUS|MAP_SHARED…)系统调用。
由于shared memory也是基于tmpfs实现的,所以这部分内存不算是匿名内存,虽然mmap使用了匿名内存标识符,因此shmem这部分内存被统计到了Cached或者Mapped中。但是shmem这部分内存存在于anon lru list中或者在unevictable lru list中,而不是在file lru list中,这一点需要注意。
Slab
Slab是分配块内存时使用的,详细的slab信息可以在/proc/slabinfo中看到,SReclaimable和SUnreclaim中包含了slab中可回收内存和不可回收内存,它们的加和应该等于Slab的值。
KernelStack
KernelStack是操作系统内核使用的栈空间,每一个用户线程都会被分配一个内核栈,内核栈是属于用户线程的,但是只有通过系统调用进入内核态之后才会使用到。KernelStack的内存不在LRU list中管理,也没有包含进进程的RSS和PSS中进行统计。
PageTables
PageTables用于记录虚拟地址和物理地址的对应关系,随着内存地址分配的增多,PageTables占用的内存也会增加。
NFS_Unstable
NFS_Unstable记录了发送给NFS server但是还没有写入硬盘的缓存。
Bounce
有些老设备只能够访问低端内存,比如16M以下的内存,当应用程序发出一个IO请求,DMA的目的地址却是高端内存时,内核将低端内存中分配一个临时buffer作为跳转,把位于高端内存的缓存数据复制到bounce中,这种额外的数据拷贝会降低性能,同时也会占用额外的内存。
AnonHugePages
AnonHugePages统计的是THP内存,而不是Hugepages内存。AnonHugePages占用的内存是被统计到进程的RSS和PSS中的。
CommitLimit
Commit相关内存涉及到进程申请虚拟内存溢出的问题。
当进程需要使用物理内存的时候,实际上内核给分配的仅仅是一段虚拟内存,只有当进程需要对内存进行操作的时候才会在缺页中断处理中对应分配物理内存,进程使用的物理内存是有限的,虚拟内存也是有限的,当操作系统使用了过多的虚拟内存的时候,也会差生问题,这个时候需要通过overcommit机制来判断。在/proc/sys/vm/下面有几个相关的参数:
overcommit_memory:overcommit情况发生时的处理策略,可以设置为0,1,2
0:OVERCOMMIT_GUESS 根据具体情况进行处理
1:OVERCOMMIT_ALWAYS 无论进程使用了多少虚拟内存都不进行控制,即允许overcommit出现
2:OVERCOMMIT_NEVER 不允许overcommit出现
在overcommit_memory中如果设置为2,那么系统将不会允许overcommit存在,如何判断当前是否发生了overcommit呢?就是判断当前使用内存是否超过了CommitLimit的限制。
当用户进程在申请内存的时候,内核会调用__vm_enough_memory函数来验证是否允许分配这段虚拟内存
Committed_AS
当前已经申请的虚拟内存的大小。
VmallocTotal:可用虚拟内存总大小,内核中常量
VmallocUsed:内核常量0
VmallocChunk:内核常量0
可以在/proc/vmallocinfo中看到所有的vmalloc操作。一些驱动或者模块都有可能会使用vmalloc来分配内存。
grep vmalloc /proc/vmallocinfo | awk ‘{total+=$2}; END {print total}’
HardwareCorrupted
当系统检测到内存的硬件故障时,会把有问题的页面删除掉,不再使用,/proc/meminfo中的HardwareCorrupted统计了删除掉的内存页的总大小。相应的代码参见 mm/memory-failure.c: memory_failure()
AnonHugePages
AnonHugePages统计的是透明大页的使用。它和大页不同,大页不会被统计到RSS/PSS
中,而AnonHugePages则存在于RSS/PSS中,并且它完全包含在AnonPages中
HugePages_Total、HugePages_Free、HugePages_Rsvd、HugePages_Surp
Hugepages在/proc/meminfo中是独立统计的,既不会进入rss/pss中,也不计入lru active/inactive, 也不会被计入cache/buffer。如果进程使用hugepages,它的rss/pss也不增加。
THP和hugepages是不同的,THP的统计值是在/proc/meminfo中的AnonHugePages,在/proc/pid/smaps中也有单个进程的统计,这个统计值和进程的rss/pss是有重叠的,如果用户进程使用了THP,那么进程的RSS/PSS也会增加,这和Hugepages是不同的。
HugePages_Total对应内核参数vm.nr_hugepages,也可以在运行的系统之上直接修改,修改的结果会立即影响到空闲内存的大小,因为HugePages在内核上是独立管理的,只要被定义,无论是否被使用,都不再属于free memory。当用户程序申请Hugepages的时候,其实是reserve了一块内存,并没有被真正使用,此时/proc/meminfo中的HugePages_Rsvd会增加,并且HugePages_Free不会减少。只有当用户程序真正写入Hugepages的时候,才会被消耗掉,此时HugePages_Free会减少,HugePages_Rsvd也会减少。
简要说明:
(1)MemTotal: 所有可用RAM大小。(即物理内存减去一些预留位和内核的二进制代码大小)
(2)MemFree: LowFree与HighFree的总和,被系统留着未使用的内存。
(3)Buffers: 用来给文件做缓冲大小。
(4)Cached: 被高速缓冲存储器(cache memory)用的内存的大小(等于diskcache minus SwapCache)。
(5)SwapCached:被高速缓冲存储器(cache memory)用的交换空间的大小。已经被交换出来的内存,仍然被存放在swapfile中,用来在需要的时候很快的被替换而不需要再次打开I/O端口。
(6)Active: 在活跃使用中的缓冲或高速缓冲存储器页面文件的大小,除非非常必要,否则不会被移作他用。
(7)Inactive: 在不经常使用中的缓冲或高速缓冲存储器页面文件的大小,可能被用于其他途径。
(8)SwapTotal: 交换空间的总大小。
(9)SwapFree: 未被使用交换空间的大小。
(10)Dirty: 等待被写回到磁盘的内存大小。
(11)Writeback: 正在被写回到磁盘的内存大小。
(12)AnonPages:未映射页的内存大小。
(13)Mapped: 设备和文件等映射的大小。
(14)Slab: 内核数据结构缓存的大小,可以减少申请和释放内存带来的消耗。
(15)SReclaimable:可收回Slab的大小。
(16)SUnreclaim:不可收回Slab的大小(SUnreclaim+SReclaimable=Slab)。
(17)PageTables:管理内存分页页面的索引表的大小。
(18)NFS_Unstable:不稳定页表的大小。
问题:Buffer与Cache的区别?
这里说下buffer与cache的区别,首先,从字面意义上讲,buffer是缓冲的意思,cache是缓存的意思。举个现实中的例子,比说铁道头上像弹簧一样的东西,就叫缓冲;部署在森林里的存应急物资的保管箱,名叫“Food Cache”,类似一种保存箱。其次,常见的说法,叫write-buffer和read-cache,buffer一般用作写操作上,cache一般用在读操作上,不过也不是一成不变的; 举例说明,每秒要写100次硬盘,对系统冲击很大,浪费了大量时间在忙着处理开始写和结束写这两件事嘛。用buffer暂存起来,变成每10秒写一次硬盘,对系统的冲击就很小,写入效率高了;Cache 是为了弥补高速设备和低速设备的鸿沟而引入的中间层,最终起到加快取速度的作用。比如你一个很复杂的计算做完了,下次还要用结果,就把结果放手边一个好拿的地方存着,下次不用再算了,加快了数据取用的速度。
三、Linux内存计算公式:
参照 free 的输出结果,这里有几个计算公式:
[root@localhost ~]# free
total used free shared buffers cached
Mem: 16433020 1827360 14605660 740 203540 1051400
-/+ buffers/cache: 572420 15860600
Swap: 8388604 0 8388604
为了直观说明,简述:
第2行,Mem 行,这里称作 OS Mem;
第3行,buffers/cache 行,称作 APP buffer/cache:
OS Mem total = OS Mem used + OS Mem free APP buffers/cache used = OS Mem used - OS Mem buffers - OS Mem cached APP buffers/cache free = OS Mem free + OS Mem buffers + OS Mem cached APP buffers/cache total = APP buffers/cache used + APP buffers/cache free = OS Mem total |
举例:系统设置可用为52.11GB
可知:52.11*1024*1024=54641295.36(kb)
结果参考cat /proc/meminfo值,对应项。