你真的了解缓冲区和缓存的区别吗?
假设您已经知道 "缓冲区 "和 "缓存 "的定义。
- 缓冲区是对原始磁盘块的临时存储,也就是写到磁盘上的缓存数据,通常不是很大(大约20MB)。通过这种方式,内核可以将分散的写操作集中起来,统一优化磁盘写操作。例如,多个小写可以合并成一个大写,等等。
- 缓存是一个用于从磁盘上读取文件的页面缓存,它用于缓存从文件中读取的数据。这样,下次访问这些文件数据时,就可以直接从内存中快速获取,而不必再次访问缓慢的磁盘。
但是我想问一下,既然Buffer只是对将写入磁盘的数据进行缓存。反过来,它是否也会缓存从磁盘上读到的数据?或者说Cache是读取文件数据的缓存,那么它是否也会缓存写入文件的数据呢?
如果你能回答以上两个问题,你可以跳过这篇文章,我想你已经对 "缓冲区 "和 "缓存 "有了一定的了解。但如果你不能,请留下,让我进一步解释。
"free "命令
要检查系统内存的使用情况,你脑海中出现的第一个命令可能是free ,例如。
$ free -h
total used free shared buff/cache available
Mem: 1.9G 1.0G 394M 2.6M 491M 728M
Swap: 0B 0B 0B
很明显,这个输出包含了物理内存Mem 和Swap 的具体使用情况,如总内存、已用内存、缓存、可用内存等。缓存是Buffer 和Cache 两部分的总和。
让我们看看buffers 和cache 的定义,在free man page。
buffers
内核缓冲区使用的内存(Buffers in /proc/meminfo)
cache
页面缓冲区和板块使用的内存(Cached and SReclaimable in /proc/meminfo)
buff/cache
缓冲区和cache的总和
我们可以看到,free 命令的源数据实际上是在proc/meminfo 文件中。正如我前面提到的,/proc 是一个由Linux内核提供的特殊文件系统,它就像一个接口,供用户与内核进行交互。
/proc 文件系统也是许多性能工具的最终数据来源。在man proc ,buffer 和Cached 的定义如下。
缓冲区(Buffers) %lu
相对临时的存储原始磁盘块,不应该变得非常大(20MB左右)。
缓存(Cached) %lu
从磁盘上读取文件的内存缓存(页面缓存)。
不包括SwapCached。 ...
SReclaimable %lu (自Linux 2.6.19起)
Slab的一部分,可能被回收,比如缓存。
SUnreclaim %lu (自Linux 2.6.19起)
Slab的一部分,在内存压力下不能被回收。
在这一点上,你可能认为你已经找到了我问题的答案,"Buffer"只是一个将被写入磁盘的数据的缓存,而 "Cache"只是一个从文件中读取数据的缓存。但是,事实上,"Buffer"也可以用于读取,"Cache"也可以用于写入。
实验
我们将在这里做两个实验,写的缓存和读的缓冲区。
写入缓冲区
让我们登录我们的Linux主机,准备好两个终端。在第一终端,我们先清理一下缓存。

这里/proc/sys/vm/drop_caches ,是一个通过proc 文件系统修改内核行为的例子。写3意味着清理各种缓存,如文件页、目录条目和Inodes。
还是在第一终端,让我们启动vmstat 2 命令。

buff和cache是我们前面看到的缓冲区和缓存,单位是KB。bi和bo分别代表块设备读写的大小,单位是块/秒。由于Linux中的块大小是1KB,这个单位相当于KB/s。
接下来,转到终端二,运行以下命令。

现在切换回终端一,观察buff 和cache 的变化。

通过观察vmstat 的输出,我们发现,当dd命令运行时,Cache 一直在增长,而Buffer 基本上没有变化。
读取的缓冲区
现在,让我们来做第二个实验。再次,清除第一终端的缓存。

再次启动vmstat 2 命令,也是在第一终端。

你可以看到,在这一点上,buff 是0。现在在终端二,运行以下命令。

然后,回到第一终端进行观察。

观察vmstat 的输出,你会发现当读磁盘时(也就是bi大于0时),Buffer和Cache都在增长,但显然Buffer的增长要快得多。这意味着当从磁盘读取数据时,数据被缓存在Buffer中。
现在我们几乎可以断定。
读取文件时数据会被缓存在Cache中,而读取磁盘时数据会被缓存在Buffer中。
结论
在这里你应该发现,虽然文档中对Buffer和Cache进行了描述,但仍然不能涵盖所有的细节。例如,我们今天学到的这两点。
- 缓冲区既可以作为 "写入磁盘的数据的缓存",也可以作为 "从磁盘读取数据的缓存"。
- 缓存既可以作为 "从文件中读取数据的页面缓存",也可以作为 "写入文件的页面缓存"。