如何理解内存的buffer和cache

当我们执行 free 命令时看到有一栏 buffer/cache

1
2
3
4
root@linux:~# free -h
total used free shared buff/cache available
Mem: 7.8G 172M 7.0G 6.1M 656M 7.4G
Swap: 0B 0B 0B

这里的buffer 和cache 是什么意思呢?我们可以通过 man free 查看解释

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
DESCRIPTION
free displays the total amount of free and used physical and swap memory in the system, as well as the buffers and caches used by the kernel. The information is gathered by parsing /proc/meminfo. The displayed columns are:

total Total installed memory (MemTotal and SwapTotal in /proc/meminfo)

used Used memory (calculated as total - free - buffers - cache)

free Unused memory (MemFree and SwapFree in /proc/meminfo)

shared Memory used (mostly) by tmpfs (Shmem in /proc/meminfo)

buffers
Memory used by kernel buffers (Buffers in /proc/meminfo)

cache Memory used by the page cache and slabs (Cached and SReclaimable in /proc/meminfo)

buff/cache
Sum of buffers and cache

available
Estimation of how much memory is available for starting new applications, without swapping. Unlike the data provided by the cache or free fields, this field takes into account page cache and also that not all
reclaimable memory slabs will be reclaimed due to items being in use (MemAvailable in /proc/meminfo, available on kernels 3.14, emulated on kernels 2.6.27+, otherwise the same as free)

可以看到buff和cache 的数据来源都是来自 /proc/meminfo

  • Buffers 是内核缓冲区用到的内存,对应的是 /proc/meminfo 中的 Buffers 值。
  • Cache 是内核页缓存和 Slab 用到的内存,对应的是 /proc/meminfo 中的 Cached 与 SReclaimable 之和。
1
2
3
4
root@linux:~# cat /proc/meminfo | grep SR
SReclaimable: 67024 kB
root@linux:~# cat /proc/meminfo | grep Cac
Cached: 491004 kB

这些数值都来自 /proc/meminfo,但更具体的 Buffers、Cached 和 SReclaimable 的含义,还是没有说清楚。

proc 文件系统

执行 man proc 定位到 meninfo

1
2
3
4
5
6
7
8
9
10
  Buffers %lu
Relatively temporary storage for raw disk blocks that shouldn't get tremendously large (20MB or so).

Cached %lu
In-memory cache for files read from the disk (the page cache). Doesn't include SwapCached.
SReclaimable %lu (since Linux 2.6.19)
Part of Slab, that might be reclaimed, such as caches.

SUnreclaim %lu (since Linux 2.6.19)
Part of Slab, that cannot be reclaimed on memory pressure.

通过这个文档,我们可以看到:

  • Buffers 是对原始磁盘块的临时存储,也就是用来缓存磁盘的数据,通常不会特别大(20MB左右)。这样,内核就可以把分散的写集中起来,统-优化磁盘的写入,比如可以把多次小的写合并成单次大的写等等。

  • Cached是从磁盘读取文件的页缓存,也就是用来缓存从文件读取的数据。这样,下次访问这些文件数据时,就可以直接从内存中快速获取,而不需要再次访问缓慢的磁盘。

  • SReclaimable 是Slab的一部分。Slab 包括两部分,其中的可回收部分,用SReclaimable记录;而不可回收部分,用SUnreclaim记录。

问题

Buffer 的文档没有提到这是磁盘读数据还是写数据的缓存,而在很多网络搜索的结果中都会提到 Buffer 只是对将要写入磁盘数据的缓存。那反过来说,它会不会也缓存从磁盘中读取的数据呢?

Cache 是对从文件读取数据的缓存,那么它是不是也会缓存写文件的数据呢?

案例分析

  1. 清空系统缓存
1
2
3
4
5
6
root@linux:~# cat /proc/sys/vm/drop_caches
0
root@linux:~# echo 3 > /proc/sys/vm/drop_caches
root@linux:~# cat /proc/sys/vm/drop_caches
3
root@linux:~#

查看wmstat 的buff和cache

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
root@linux:~# vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 0 7790168 3492 188780 0 0 314 9 120 94 0 0 99 0 0
0 0 0 7790160 3492 188816 0 0 0 0 76 172 0 0 100 0 0
0 0 0 7790160 3492 188816 0 0 0 0 88 222 0 1 100 0 0
0 0 0 7790160 3492 188816 0 0 0 0 83 199 0 0 100 0 0
0 0 0 7790192 3500 188816 0 0 0 24 87 215 0 0 100 1 0
0 0 0 7790192 3500 188816 0 0 0 0 76 174 0 0 100 0 0
0 0 0 7790192 3500 188816 0 0 0 0 77 205 0 0 100 0 0
0 0 0 7790192 3500 188816 0 0 0 0 125 292 0 0 100 0 0
0 0 0 7790192 3500 188816 0 0 0 344 215 198 0 0 97 3 0
0 0 0 7790192 3500 188816 0 0 0 0 64 182 0 0 100 0 0
1 0 0 7790192 3500 188816 0 0 0 0 82 201 0 1 100 0 0
0 0 0 7790192 3500 188816 0 0 0 0 65 153 0 0 100 0 0
0 0 0 7790192 3500 188816 0 0 0 0 58 144 0 0 100 0 0

输出界面里,内存部分的 buff和cache,以及io部分的bi和bo就是我们要关注的重点。

  • buff和cache就是我们前面看到的Buffers和Cache, 单位是KB。

  • bi和bo则分别表示块设备读取和写入的大小,单位为块/秒。因为Linux中块的大小是1KB,所以这个单位也就等价于KB/s。

正常情况下,空闲系统中,你应该看到的是,这几个值在多次结果中一直保持不变。

我们执行dd 随机写文件

1
2
3
4
5
root@linux:~# dd if=/dev/urandom of=/tmp/file bs=1M count=500
500+0 records in
500+0 records out
524288000 bytes (524 MB, 500 MiB) copied, 2.87644 s, 182 MB/s
root@linux:~#

然后观察vmstat 的变化

会发现,在 dd 命令运行时, Cache 在不停地增长,而 Buffer 基本保持不变。

继续执行

1
2
root@linux:~# echo 3 > /proc/sys/vm/drop_caches
root@linux:~# dd if=/dev/urandom of=/dev/sdc bs=1M count=2048

并没有发现cache 不增长 而buff 增长。

与专栏说的不符合