在Linux系统中我们进行内存使用定位时,经常使用free命令查看内存的使用情况,但是总有那么两列可能没有含糊不清楚,网上找资料也良莠不齐,很难将问题讲透、讲明白。在翻阅了很多资料后,将我的理解记录如下。这篇文章后面应该会进行更新,因为现在的分析可能还不是准确的。
free命令
首先我们对free命令的输出做一下解读。free命令使用-m -w参数的输出如下:
# free -m -w
total used free shared buffers cache available
Mem: 486 92 103 0 20 270 381
Swap: 0 0 0
其中-m参数表示使用MBytes为单位显示,-w使用wide模式,将buffers和cache分为两列显示。
free命令的数据来源于/proc/meminfo,详细解释可以查看free命令的帮助手册(man free)。
命令输出解读:
输出列名 | /proc/meminfo数据 | 解释 |
---|---|---|
total | MemTotal和SwapTotal | 系统的全部内存,包含物理内存条和交换设备 |
used | 无 | total - free - buffers - cache |
free | MemFree 和 SwapFree | 没有被使用的内存 |
shared | Shmem | 大多数情况下是被tmpfs使用的内存 |
buffers | Buffers | 内核buffers使用的内存 |
cache | Cached 和 SReclaimable | page cache和slab使用的内存 |
available | MemAvailable | 内核计算出可供新程序使用的内存 |
下面是man手册中对buff/cache的解释:
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
对于meminfo中的各个字段的含义,我们可以通过man proc命令来查看,如果使用该命令抱以下错误,则可以通过安装man-pages来解决。
错误:
# man proc
没有 proc 的手册页条目
安装:
# yum install -y man-pages
可以通过搜索直接找到meminfo的部分:
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.
- Buffers:对原始磁盘块的临时存储,通常不会特别大(20M左右)
- Cached:磁盘文件读取的缓存(page cache)
- SReclaimable:Slab的一部分,可回收的部分,比如缓存
通过上面的描述,感觉还是有点模糊,尤其在Buffers和Cached这两块,Buffers是对原始磁盘块的临时存储,那么这个是针对读的还是写的,还是都有?Cached写的是从磁盘读取文件的缓存,那么正常对文件的写操作是Buffers还是Cached?如果Cached的只是针对文件读取,那么Cached中的文件被修改后会发生什么?
为了解决上面的疑问,我们分别设计以下实验:
- 对文件进行读/写操作
- 对磁盘进行读/写操作
文件读写
文件写入
首先我们需要使用以下命令将page cache清掉,然后使用dd命令进行对文件的读写操作。
同时打开终端1和终端2,终端1负责写入,终端2负责使用vmstat命令进行观察buff和cache的变化,如下所示。# echo '3' > /proc/sys/vm/drop_caches
终端1:
终端2:# dd if=/dev/urandom of=/tmp/file bs=2M count=500
记录了500+0 的读入
记录了500+0 的写出
1048576000字节(1.0 GB)已复制,9.59103 秒,109 MB/秒
通过终端2可以看出在进行对文件写入时cache列增长,buff没有基本上没有什么变化,这说明在对文件进行写入时也会使用cache。# vmstat -SM 2
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 337 0 55 0 0 0 0 1359 2977 1 1 98 0 0
0 0 0 337 0 55 0 0 0 0 1367 2988 1 1 99 0 0
3 0 0 337 0 55 0 0 0 0 1381 3001 1 1 98 0 0
5 0 0 235 1 155 0 0 108 32804 1390 2114 0 39 61 0 0
3 1 0 4 0 387 0 0 2 128000 1403 732 0 99 0 1 0
4 0 0 7 0 384 0 0 2 122880 1591 1265 0 86 0 13 0
21 2 0 5 0 386 0 0 2050 100388 1511 1383 0 81 0 19 0
2 0 0 4 0 387 0 0 1798 98328 1617 1517 0 79 0 21 0
0 0 0 7 0 386 0 0 738 29716 1459 2866 1 10 61 28 0
1 0 0 7 0 386 0 0 0 0 1422 3052 1 1 99 0 0
0 0 0 7 0 386 0 0 0 0 1347 2958 1 0 99 0 0
文件读取
首先使用上面提到的方式清理cache:
继续使用dd命令将文件的内容读到系统中,如下所示。# echo '3' > /proc/sys/vm/drop_caches
终端1:
终端2:# dd of=/dev/null if=/tmp/file bs=2M count=500 记录了500+0 的读入 记录了500+0 的写出 1048576000字节(1.0 GB)已复制,9.37269 秒,112 MB/秒
通过中断2 的结果看以看出对文件的读入操作时cache是增加的,但是buff没有增加,由此可以知道对文件的读取确实会走cache。# vmstat -SM 2 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 1 0 0 349 0 42 0 0 0 0 1339 2967 1 1 98 0 0 0 0 0 349 0 42 0 0 0 0 1354 2965 1 1 99 0 0 0 0 0 349 0 43 0 0 2 0 1356 2975 1 1 99 0 0 0 1 0 135 0 255 0 0 108716 32 1625 3100 1 5 10 85 0 0 1 0 6 0 383 0 0 108546 0 1566 2941 1 6 0 94 0 0 1 0 6 0 384 0 0 108544 6 1577 2959 0 6 0 94 0 1 1 0 6 0 383 0 0 107020 0 1607 2976 1 6 0 93 0 0 0 0 7 0 385 0 0 84636 0 1559 2986 1 5 21 74 0 0 0 0 7 0 385 0 0 0 0 1333 2953 1 1 98 0 0 0 0 0 7 0 385 0 0 0 6 1335 2949 0 1 99 1 0 0 0 0 7 0 385 0 0 0 0 1311 2935 1 0 99 0 0
磁盘写入
为了验证对磁盘的写入会走buff还是cache,我们在申请虚拟机的时候多加了一块hdd盘,下面这个操作需要注意下,使用空白磁盘或者分区,否则会导致数据丢失。
首先使用上面提到的命令对cache进行清理:
然后使用dd命令对/dev/vdb进行写入操作。同时打开终端1和终端2,终端1负责写入,终端2负责使用vmstat命令查看内存使用情况,如下所示。# echo '3' > /proc/sys/vm/drop_caches
终端1:
终端2:# dd if=/dev/urandom of=/dev/vdb bs=2M count=500 记录了500+0 的读入 记录了500+0 的写出 1048576000字节(1.0 GB)已复制,9.69532 秒,108 MB/秒
从终端2的输出可以看出,在对磁盘进行写入的时候buff在增长,而cache增长的非常有限,这里我们可以任务在对磁盘进行直接写入时buff会承担缓存的作用。# vmstat -SM 2 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 1 0 0 335 0 57 0 0 0 8 1331 2950 1 0 99 0 0 0 0 0 335 0 57 0 0 0 0 1429 3055 1 1 99 0 0 1 0 0 219 93 75 0 0 38 32768 1391 2096 0 39 61 0 0 3 0 0 8 280 95 0 0 2 110735 1756 1354 0 100 0 0 0 4 1 0 4 282 96 0 0 0 101619 1743 1589 1 99 0 0 0 5 0 0 6 282 95 0 0 2 103268 1916 1790 0 100 0 0 0 5 0 0 6 281 96 0 0 2 104839 2273 2169 0 99 0 0 0 0 0 0 12 281 98 0 0 2018 50608 1485 2436 0 36 44 20 0 0 0 0 12 281 98 0 0 0 0 1348 2970 1 1 98 0 0 0 0 0 6 280 105 0 0 3884 0 1365 3006 1 0 98 1 0
磁盘读取
在验证磁盘读取之前首先使用前面提到的命令对缓存进行清理。
同样是使用两个终端,终端1改为直接从/dev/vdb读取数据,通过终端2观察内存使用情况,如下所示。# echo '3' > /proc/sys/vm/drop_caches
终端1:
终端2:# dd of=/dev/null if=/dev/vdb bs=2M count=500 记录了500+0 的读入 记录了500+0 的写出 1048576000字节(1.0 GB)已复制,9.58241 秒,109 MB/秒
从上面可以看出在对磁盘直接进行读入时,buff在增加。可以看出对磁盘进行直接读取操作会使用buff作为缓存使用。# vmstat -SM 2 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 1 0 0 337 0 55 0 0 0 2 1400 3047 1 1 98 0 0 0 0 0 337 0 55 0 0 0 0 1371 3002 0 1 99 0 0 0 1 0 130 204 55 0 0 104552 0 1621 3076 1 5 7 88 0 1 1 0 6 333 50 0 0 110202 30 1819 3262 2 7 0 91 0 1 1 0 6 333 51 0 0 106496 0 1643 3074 1 6 0 93 0 0 1 0 6 343 40 0 0 104450 0 1602 3013 0 6 0 94 0 0 0 0 8 342 41 0 0 94872 10 1605 3034 1 6 14 80 0 0 0 0 8 342 41 0 0 0 0 1388 3028 1 1 99 0 0 0 0 0 8 342 41 0 0 0 0 1383 3014 1 1 99 0 0
结论
Linux系统中对文件进行读写时会,会使用cached来提高性能;对磁盘进行读写时会使用buffers来提高性能。
参考文档:
https://github.com/firmianay/Life-long-Learner/blob/master/linux-kernel-development/chapter-16.md
https://medium.com/geekculture/linux-memory-buffer-vs-cache-44d8a187f310