free 工具用来查看系统可用内存

1
2
3
4
5
/opt/app/tdev1 $ free
total used free shared buffers cached
Mem: 8175320 6159248 2016072 0 310208 5243680
-/+ buffers/cache: 605360 7569960
Swap: 6881272 16196 6865076

解释一下 Linux 上 free 命令的输出。

ree 的输出看成一个二维数组 FO (Free Output)。例如:

1
2
3
4
5
6
7
8
FO [2][1] = 24677460
FO [3][2] = 10321516

1 2 3 4 5 6
1 total used free shared buffers cached
2 Mem: 24677460 23276064 1401396 0 870540 12084008
3 -/+ buffers/cache: 10321516 14355944
4 Swap: 25151484 224188 24927296

free 的输出一共有四行,第四行为交换区的信息,分别是交换的总量(total),使用量(used)和有多少空闲的交换区(free),这个比较清楚,不说太多。

free 输出地第二行和第三行是比较让人迷惑的。这两行都是说明内存使用情况的。第一列是总量(total),第二列是使用量(used),第三列是可用量(free)。

  第一行的输出时从操作系统(OS)来看的。也就是说,从 OS 的角度来看,计算机上一共有:

24677460KB(缺省时 free 的单位为 KB)物理内存,即 FO [2][1]; 在这些物理内存中有 23276064KB(即 FO [2][2])被使用了; 还用 1401396KB(即 FO [2][3])是可用的;

这里得到第一个等式:

FO [2][1] = FO [2][2] + FO [2][3]

FO [2][4] 表示被几个进程共享的内存的,现在已经 deprecated,其值总是 0(当然在一些系统上也可能不是 0,主要取决于 free 命令是怎么实现的)。

FO [2][5] 表示被 OS buffer 住的内存。FO [2][6] 表示被 OS cache 的内存。在有些时候 buffer 和 cache 这两个词经常混用。不过在一些比较低层的软件里是要区分这两个词的,看老外的洋文:

1
2
A buffer is something that has yet to be "written" to disk.
A cache is something that has been "read" from the disk and stored for later use.

也就是说 buffer 是用于存放要输出到 disk(块设备)的数据的,而 cache 是存放从 disk 上读出的数据。这二者是为了提高 IO 性能的,并由 OS 管理。

Linux 和其他成熟的操作系统(例如 windows),为了提高 IO read 的性能,总是要多 cache 一些数据,这也就是为什么 FO [2][6](cached memory)比较大,而 FO [2][3] 比较小的原因。我们可以做一个简单的测试:

释放掉被系统 cache 占用的数据:

1
echo 3>/proc/sys/vm/drop_caches
  1. 读一个大文件,并记录时间;
  2. 关闭该文件;
  3. 重读这个大文件,并记录时间;

第二次读应该比第一次快很多。原来我做过一个 BerkeleyDB 的读操作,大概要读 5G 的文件,几千万条记录。在我的环境上,第二次读比第一次大概可以快 9 倍左右。

free 输出的第二行是从一个应用程序的角度看系统内存的使用情况。

  • 对于 FO [3][2],即 -buffers/cache,表示一个应用程序认为系统被用掉多少内存;
  • 对于 FO [3][3],即 +buffers/cache,表示一个应用程序认为系统还有多少内存;

因为被系统 cache 和 buffer 占用的内存可以被快速回收,所以通常 FO [3][3] 比 FO [2][3] 会大很多。

这里还用两个等式:

1
2
FO [3][2] = FO [2][2] - FO [2][5] - FO [2][6]
FO [3][3] = FO [2][3] + FO [2][5] + FO [2][6]

这二者都不难理解。

free 命令由 procps.*.rpm 提供(在 Redhat 系列的 OS 上)。free 命令的所有输出值都是从 /proc/meminfo 中读出的。

在系统上可能有 meminfo (2) 这个函数,它就是为了解析 /proc/meminfo 的。procps 这个包自己实现了 meminfo () 这个函数。可以下载一个 procps 的 tar 包看看具体实现,现在最新版式 3.2.8。