linux 系统 内存中的 Buffer 和 Cache 解释
1. page cache 和 buffer cache 定义
在 Linux 2.4 及以后的内核版本中,page cache 和 Buffer Cache 的定义
什么是 page cache
Page Cache 包含 code 和 data,即 file’s IO block pages。实际上,我们所有的应用程序都驻留在 page cache pool。
当cpu访问 page 时候,new pages将立即更新到缓存中。下次访问时,CPU首先检查page cache,如果不可用再从磁盘访问。他从磁盘缓存数据,以加快后续I/O的速度。
什么是 Buffer Cache
保留 buffer cache 是为了当内核仍需要执行 block I/O 操作时使用。块通常代表的是文件的数据。因此,大多数 buffer cache 都指向/链接到 page cache。但是,还是会有少量的 block data 需要保存在 buffer cache 而不是 page cache.
2. buffer cache 和 page cache 的区别
Linux 内核版本 2.4 之前 Page Cache 和 Buffer Cache 是不同的,从2.4内核开始,这两个缓存已合并。今天,只有一个缓存,即 Page Cache。但是在两者的理解上还是略有不同。怎么合并的看上面的定义。
page cache 存储 pages of files 以优化 file I/O
buffer cache 存储 disk blocks 以优化 block I/O.
从内核版本2.4之前
Files' cache 存储在 page cache,,disk blocks 存储在 buffer cache。有时 disk blocks 通常引用相同的 file data,因此,数据在每个缓存中都存在,被引用两次。
为了避免这种行为,Page & Buffer cache 在 2.4 内核版本中进行了修改。从内核版本2.4开始,page caches 和 buffer caches 合并了。
Virtual machine subsystem 现在通过在 page cache 中缓存 files' data 和 pages。如果缓存的数据同时包含 file 和 block,需要缓存在 buffer 时,buffer 仅将简单地指向/链接到页面缓存中的数据即可。
3. 写数据
如果需要写入数据,则首先将其写入 Page Cache 并作为其 dirty pages 之一进行管理。Dirty 意味着数据存储在 Page Cache ,而不是立马写入底层的存储设备。这些 dirty pages 的内容会定期(或者调用 sync 或 fsync 手动立马同步)写入到底层的存储设备。
示例:
下面的示例将显示一个10 MB的文件的创建过程,该文件将首先写入页面缓存中。这样做会增加脏页的数量,直到它们被写入基础固态驱动器(SSD)为止,在这种情况下,它们是根据sync命令手动写入的。
[root@localhost ~]# sync [root@localhost ~]# cat /proc/meminfo | grep Dirty Dirty: 0 kB [root@localhost ~]# dd if=/dev/zero of=laojia.txt bs=1M count=10 10+0 records in 10+0 records out 10485760 bytes (10 MB) copied, 0.00733209 s, 1.4 GB/s [root@localhost ~]# cat /proc/meminfo | grep Dirty Dirty: 10240 kB [root@localhost ~]# sync [root@localhost ~]# cat /proc/meminfo | grep Dirty Dirty: 0 kB
pdflush 和 flush
这两个线程是确保将脏页定期写入底层存储设备
2.6.31- 之前是 pdfulsh
2.6.32+ 是 flush
他们的不同是 flush 为每个底层存储设置启用一个线程,以提高性能。
root@pc:~# ls -l /dev/sda brw-rw---- 1 root disk 8, 0 2011-09-01 10:36 /dev/sda root@pc:~# ls -l /dev/sdb brw-rw---- 1 root disk 8, 16 2011-09-01 10:36 /dev/sdb root@pc:~# ps -eaf | grep -i flush root 935 2 0 10:36 ? 00:00:00 [flush-8:0] root 936 2 0 10:36 ? 00:00:00 [flush-8:16]
现在:未找到flush线程。未知!
[root@localhost ~]# uname -r 3.10.0-957.1.3.el7.x86_64 [root@localhost ~]# ps -eaf |grep -v grep |grep -i flush [root@localhost ~]#
4. 读数据
File blocks不仅在写入过程中会使用 Page Cache,而且在读取文件时也会写入Page Cache。
譬如当您两次读取一个100 MB的文件时,第二次访问会更快,因为文件块直接来自内存中的Page Cache,而不必再次从硬盘中读取。
示例:
我们读取一个 13M 的文件来看看 cache 的变化
[root@localhost ~]# ls -lh /tmp/file3.log -rw-r--r--. 1 root root 13M Jan 14 15:32 /tmp/file3.log [root@localhost ~]# cat /tmp/file3.log # 另外一个终端,查看 cache 的变化 80-67 = 13M 正好是 file3 的大小 [root@localhost ~]# free -m -s 1 total used free shared buff/cache available Mem: 487 73 345 16 67 362 Swap: 2047 1 2046 total used free shared buff/cache available Mem: 487 73 345 16 67 362 Swap: 2047 1 2046 total used free shared buff/cache available Mem: 487 74 343 16 69 362 Swap: 2047 1 2046 total used free shared buff/cache available Mem: 487 74 341 16 71 362 Swap: 2047 1 2046 total used free shared buff/cache available Mem: 487 74 341 16 71 362 Swap: 2047 1 2046 total used free shared buff/cache available Mem: 487 74 337 16 75 362 Swap: 2047 1 2046 total used free shared buff/cache available Mem: 487 74 337 16 75 362 Swap: 2047 1 2046 total used free shared buff/cache available Mem: 487 74 332 16 80 362 Swap: 2047 1 2046 total used free shared buff/cache available Mem: 487 74 332 16 80 362 Swap: 2047 1 2046 total used free shared buff/cache available Mem: 487 74 332 16 80 362 Swap: 2047 1 2046
5. Buffer 和 Cache 的 误解
两个疑问:
第一个问题:Buffer 的文档没有提到这是磁盘读数据还是写数据的缓存,而在很多网络搜索的结果中都会提到 Buffer 只是对将要写入磁盘数据的缓存。那反过来说,它会不会也缓存从磁盘中读取的数据呢?
第二个问题:文档中提到,Cache 是对从文件读取数据的缓存,那么它是不是也会缓存写文件的数据呢?
答案:
简单来说,Buffer 是对磁盘数据的缓存,而 Cache 是文件数据的缓存,它们既会用在读请求中,也会用在写请求中。
6. 扩展:proc 文件系统对 buffers 和 cached 的解释
/proc 是 Linux 内核提供的一种特殊文件系统,是用户跟内核交互的接口。用户可以从 /proc 中查询内核的运行状态和配置选项,查询进程的运行状态、统计数据等,当然,你也可以通过 /proc 来修改内核的配置。
proc文件系统同时也是很多性能工具的数据来源,比如我们刚看到的free,就是通过读取/proc/meminfo ,得到内存的使用情况。在 /proc/meminfo,有字段 Buffers、Cached、SReclaimable 这几个字段。执行 man proc ,你就可以得到详细文档
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 记录。
参考:
Difference between buffer and page cache in Linux ?
共 0 条评论