聊聊 Linux 的内存统计

本文主要分析 linux 系统内存统计的一些指标以及进程角度内存使用监控的一些方法 。
开始阅读这篇文章前,请先简单阅读下面的几篇文章 。

  • 《进程眼中的线性地址空间》
  • 《线程眼中的线性地址空间》
  • 《聊聊内存管理》
想必这几篇文章过后,基本概念就不需要再赘述了 。所以下文直接就找一台 Intel x86_64 架构下安装了 64bit Linux 系统的服务器作为例进行相关的实验和结果分析 。Linux 的内存管理从物理内存管理到虚拟内存管理涉及的概念和统计项实在太多,本文从实用和系统运维的角度出发,只列举一些最实用的统计 。
 
从 free 命令开始上面的背景介绍文章把内存相关的基础概念讲的差不多了,这里不再赘述 。本文定位是内存统计,所以从最基础的内存统计的命令—free命令开始 。执行free命令,可以看到如下的输出:
聊聊 Linux 的内存统计

文章插图
纵向是内存和Swap分区,横向是统计项 。纵向的含义以及Swap不需要解释,我们看横向的统计项:
  • total — 系统总内存(其实就是从 /proc/meminfo获取的)
  • used — 已使用内存
  • free — 未使用的内存
  • shared — 共享内存的大小,主要是 tmpfs
  • buff / cache — bufferscache使用的内存之和
  • available — 可用内存,可以简单理解为未使用的内存和可释放的内存之和(buffer、cache 可以释放大部分,所以这里近似等于 free + buffer / cache 的大小)
这台机器的系统和内核稍微新一点,这个输出可能和你看到的不一样,早先的free命令的输出是这样:
聊聊 Linux 的内存统计

文章插图
这里的shared为0,因为这台服务器没用共享内存 。这里多解释下-/+ buffer/cache这行,字面意思就是used - buffers/cacheused + buffers/cache 。前者指的是从应用程序角度系统被用掉了多少内存,后者指的是从应用程序角度看系统还有多少内存能用 。听起来很复杂,其实说白了就是因为bufferscached可以被释放出来,多几个指标看看系统还能用多少内存而已 。
下面用几个公式来解释这个输出:
1234567891011# 内存总量 = 已使用内存 + 空闲内存`total` = `used` + `free`# 系统被用掉的内存`-buffers/cache` = `used` - `buffers` - `cached`# 系统还能用的内存`+buffers/cache` = `free` + `buffers` + `cached`# 所以,其实还有下面的公式`total` = `-buffers/cache` + `+buffers/cache` buffers/cached不是100%都能释放出来使用的,上面的“可用内存”其实就是个近似值 。最上面新版本系统的输出中有一个available项目表示可用内存,值小于free + buff/cache,内核 3.14 之后支持该特性(虽然也不是绝对意义上的精确的可用内存大小,囧) 。
这里稍微多说一点bufferscached 。Linux 2.4.10 内核之前,磁盘的缓存有两种,即Buffer CachePage Cache 。前者缓存管理磁盘文件系统时读取的块,后者存放访问具体文件内容时生成的页 。在 2.4.10 之后,Buffer Cache这个概念就不存在了,这些数据被放在Page Cache中(这种Page被称为Buffer Pages) 。
简而言之,现在磁盘的 cache 只有 Page Cache一种,在Page Cache中,有一种PageBuffer Page,这种Page都与一个叫buffer_head的数据结构关联,这些页也就在内存统计中用buffers这个指标来单独统计了 。
 
/proc/meminfo 详解很多命令的内存统计都是从/proc/meminfo读取的 。鉴于/proc/meminfo的 man 文档(man proc)写的实在不够清晰,很多条目居然还是To be documented状态,所以这里逐一列举出来常见的统计项解释一下 。
首先明确一点,内核目前并没有绝对精确的统计所有的内存使用量,比如alloc_pages接口申请的内存不一定被统计在内(除非所有调用alloc_pages的代码主动进行统计,如果某些不讲究的驱动程序没有主动统计的话统计值就肯定对不上了) 。
先看这三项全局统计: