课程连接https://time.geekbang.org/column/intro/100020901
这里是学习课程的时候记录的一些学习笔记
free -mh
total used free shared buff/cache available
Mem: 1.8G 291M 745M 8.3M 802M 1.3G
Swap: 0B 0B 0B
这个界面包含了物理内存 Mem 和交换分区 Swap 的具体使用情况,比如总内存、已用内存、缓存、可用内存等。其中缓存是 Buffer 和 Cache 两部分的总和 。这里的大部分指标都比较容易理解,但 Buffer 和 Cache 可能不太好区分。从字面上来说,Buffer 是缓冲区,而 Cache 是缓存,两者都是数据在内存中的临时存储。
从 free 的手册中,你可以看到 buffer 和 cache 的说明。
/proc 是 Linux 内核提供的一种特殊文件系统,是用户跟内核交互的接口。比方说,用户可以从 /proc 中查询内核的运行状态和配置选项,查询进程的运行状态、统计数据等,当然,你也可以通过 /proc 来修改内核的配置。
proc 文件系统同时也是很多性能工具的最终数据来源。比如我们刚才看到的 free ,就是通过读取/proc/meminfo,得到内存的使用情况。
执行 man proc,查看 proc 文件系统的详细文档。
通过这个文档,我们可以看到:
# 清理文件页、目录项、Inodes等各种缓存
$ echo 3 > /proc/sys/vm/drop_caches
这里的 /proc/sys/vm/drop_caches ,就是通过 proc 文件系统修改内核行为的一个示例,写入 3 表示清理文件页、目录项、Inodes 等各种缓存。
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
3 0 0 1444884 396 139636 0 0 65 27 231 540 0 0 99 0 0
0 0 0 1444884 396 139628 0 0 0 0 339 690 1 0 99 0 0
0 0 0 1444884 396 139628 0 0 0 0 291 633 0 0 100 0 0
0 0 0 1436836 4232 142080 0 0 6288 0 1017 1265 4 3 78 15 0
0 0 0 1436836 4232 142084 0 0 0 0 290 633 0 1 99 0 0
输出界面里, 内存部分的 buff 和 cache ,以及 io 部分的 bi 和 bo 就是我们要关注的重点。
buff 和 cache 就是我们前面看到的 Buffers 和 Cache,单位是 KB。
bi 和 bo 则分别表示块设备读取和写入的大小,单位为块 / 秒。因为 Linux 中块的大小是 1KB,所以这个单位也就等价于 KB/s。
正常情况下,空闲系统中,你应该看到的是,这几个值在多次结果中一直保持不变。接下来,到第二个终端执行 dd 命令,通过读取随机设备,生成一个 500MB 大小的文件:
dd if=/dev/urandom of=/tmp/file bs=1M count=500
然后再回到第一个终端,观察 Buffer 和 Cache 的变化情况:
0 0 0 1436836 4240 142080 0 0 0 28 296 645 0 0 100 0 0
0 0 0 1436836 4240 142084 0 0 0 0 274 607 0 0 100 0 0
0 0 0 1436836 4240 142084 0 0 0 0 270 599 1 0 99 0 0
1 0 0 1436836 4240 142084 0 0 0 0 264 594 0 1 99 0 0
0 0 0 1436836 4240 142084 0 0 0 0 271 608 0 0 100 0 0
0 0 0 1436836 4240 142084 0 0 0 0 274 599 1 0 99 0 0
0 0 0 1436836 4240 142084 0 0 0 4 267 596 0 0 100 0 0
0 0 0 1436836 4240 142084 0 0 0 0 267 598 0 0 100 0 0
0 0 0 1436836 4240 142084 0 0 0 0 272 607 1 0 99 0 0
4 0 0 1433224 4524 144168 0 0 360 0 572 605 0 25 75 0 0
5 0 0 1421720 4524 155728 0 0 0 0 1283 427 0 100 0 0 0
2 0 0 1411192 4536 166256 0 0 4 19532 1247 433 0 98 0 2 0
1 0 0 1400556 4536 176740 0 0 0 0 1258 414 0 100 0 0 0
1 0 0 1390044 4536 187244 0 0 0 0 1246 413 0 100 0 0 0
2 0 0 1378540 4536 198812 0 0 0 0 1233 403 0 100 0 0 0
2 0 0 1368152 4536 209300 0 0 0 0 1228 413 0 100 0 0 0
1 0 0 1357640 4544 219792 0 0 0 20 1223 424 0 100 0 0 0
1 0 0 1346136 4544 231372 0 0 0 0 1205 404 0 100 0 0 0
1 0 0 1335500 4544 241872 0 0 0 0 1201 404 0 100 0 0 0
4 0 0 1324988 4544 252360 0 0 0 0 1247 409 0 100 0 0 0
2 0 0 1313520 4544 263928 0 0 0 0 1223 411 0 100 0 0 0
10 0 0 1302968 4552 274424 0 0 0 12 1231 416 0 100 0 0 0
2 0 0 1292428 4552 284936 0 0 0 0 1200 411 0 100 0 0 0
3 0 0 1282012 4552 295436 0 0 0 0 1226 409 0 100 0 0 0
3 0 0 1270356 4552 307008 0 0 0 0 1221 420 0 100 0 0 0
1 0 0 1259812 4552 317492 0 0 0 53272 1223 410 0 100 0 0 0
2 0 0 1249300 4560 328000 0 0 0 20 1203 423 0 100 0 0 0
2 0 0 1238912 4560 338496 0 0 0 0 1203 430 0 100 0 0 0
2 0 0 1227408 4560 350024 0 0 0 0 1197 399 0 100 0 0 0
1 0 0 1216908 4560 360600 0 0 0 0 1192 410 0 100 0 0 0
3 0 0 1206220 4564 371264 0 0 4 148480 1231 420 0 100 0 0 0
通过观察 vmstat 的输出,我们发现,在 dd 命令运行时, Cache 在不停地增长,而 Buffer 基本保持不变。再进一步观察 I/O 的情况,你会看到,在 Cache 刚开始增长时,块设备 I/O 很少,bi 只出现了一次 488 KB/s,bo 则只有一次 4KB。而过一段时间后,才会出现大量的块设备写,比如 bo 变成了 122880。当 dd 命令结束后,Cache 不再增长,但块设备写还会持续一段时间,并且,多次 I/O 写的结果加起来,才是 dd 要写的 500M 的数据。
下面的命令对环境要求很高,需要你的系统配置多块磁盘,并且磁盘分区 /dev/sdb1 还要处于未使用状态。如果你只有一块磁盘,千万不要尝试,否则将会对你的磁盘分区造成损坏。如果你的系统符合标准,就可以继续在第二个终端中,运行下面的命令。清理缓存后,向磁盘分区 /dev/sdb1 写入 2GB 的随机数据:
# 首先清理缓存
$ echo 3 > /proc/sys/vm/drop_caches
# 然后运行dd命令向磁盘分区/dev/sdb1写入2G数据
$ dd if=/dev/urandom of=/dev/sdb1 bs=1M count=2048
然后回到终端1 查看io状态
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 7584780 153592 97436 0 0 684 0 31 423 1 48 50 2 0
1 0 0 7418580 315384 101668 0 0 0 0 32 144 0 50 50 0 0
1 0 0 7253664 475844 106208 0 0 0 0 20 137 0 50 50 0 0
1 0 0 7093352 631800 110520 0 0 0 0 23 223 0 50 50 0 0
1 1 0 6930056 790520 114980 0 0 0 12804 23 168 0 50 42 9 0
1 0 0 6757204 949240 119396 0 0 0 183804 24 191 0 53 26 21 0
1 1 0 6591516 1107960 123840 0 0 0 77316 22 232 0 52 16 33 0
从这里你会看到,虽然同是写数据,写磁盘跟写文件的现象还是不同的。
写磁盘时(也就是 bo 大于 0 时),Buffer 和 Cache 都在增长,但显然 Buffer 的增长快得多。这说明,写磁盘用到了大量的 Buffer,这跟我们在文档中查到的定义是一样的。
对比两个案例,我们发现,写文件时会用到 Cache 缓存数据,而写磁盘则会用到 Buffer 来缓存数据。所以,回到刚刚的问题,虽然文档上只提到,Cache 是文件读的缓存,但实际上,Cache 也会缓存写文件时的数据。
我们回到第二个终端,运行下面的命令。清理缓存后,从文件 /tmp/file 中,读取数据写入空设备:
# 首先清理缓存
$ echo 3 > /proc/sys/vm/drop_caches
# 运行dd命令读取文件数据
$ dd if=/tmp/file of=/dev/null
终端一查看状态
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 1 0 7724164 2380 110844 0 0 16576 0 62 360 2 2 76 21 0
0 1 0 7691544 2380 143472 0 0 32640 0 46 439 1 3 50 46 0
0 1 0 7658736 2380 176204 0 0 32640 0 54 407 1 4 50 46 0
0 1 0 7626052 2380 208908 0 0 32640 40 44 422 2 2 50 46 0
观察 vmstat 的输出,你会发现读取文件时(也就是 bi 大于 0 时),Buffer 保持不变,而 Cache 则在不停增长。这跟我们查到的定义“Cache 是对文件读的页缓存”是一致的。
首先,回到第二个终端,运行下面的命令。清理缓存后,从磁盘分区 /dev/sda1 中读取数据,写入空设备:
# 首先清理缓存
$ echo 3 > /proc/sys/vm/drop_caches
# 运行dd命令读取文件
$ dd if=/dev/sda1 of=/dev/null bs=1M count=1024
然后,再回到终端一,观察内存和 I/O 的变化情况:
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 7225880 2716 608184 0 0 0 0 48 159 0 0 100 0 0
0 1 0 7199420 28644 608228 0 0 25928 0 60 252 0 1 65 35 0
0 1 0 7167092 60900 608312 0 0 32256 0 54 269 0 1 50 49 0
0 1 0 7134416 93572 608376 0 0 32672 0 53 253 0 0 51 49 0
0 1 0 7101484 126320 608480 0 0 32748 0 80 414 0 1 50 49 0
观察 vmstat 的输出,你会发现读磁盘时(也就是 bi 大于 0 时),Buffer 和 Cache 都在增长,但显然 Buffer 的增长快很多。这说明读磁盘时,数据缓存到了 Buffer 中。
简单来说,Buffer 是对磁盘数据的缓存,而 Cache 是文件数据的缓存,它们既会用在读请求中,也会用在写请求中。
Buffer 和 Cache 分别缓存磁盘和文件系统的读写数据。
磁盘是一个块设备,可以划分为不同的分区;在分区之上再创建文件系统,挂载到某个目录,之后才可以在这个目录中读写文件。
其实 Linux 中“一切皆文件”,而文章中提到的“文件”是普通文件,磁盘是块设备文件,这些大家可以执行 “ls -l <路径>”
查看它们的区别(输出的含义如果不懂请 man ls 查询)。在读写普通文件时,会经过文件系统,由文件系统负责与磁盘交互;而读写磁盘或者分区时,就会跳过文件系统,也就是所谓的“裸I/O“。这两种读写方式所使用的缓存是不同的,也就是文中所讲的
Cache 和 Buffer 区别。