Linux内核技术1 Page Cache基础篇 - 什么是Page Cache

496 阅读5分钟

什么是Page Cache
为了提升对文件的读写效率,Linux 内核会以页大小(4KB)为单位,将文件划分为多数据块。当用户对文件中的某个数据块进行读写操作时,内核首先会申请一个内存页(称为 页缓存 )与文件中的数据块进行绑定。

为什么要使用Page Cache?
减少 I/O,提升应用的 I/O 速度。

Page Cache的读写流程
read

1.检查需要数据的页缓存是否存在

2.存在则直接返回,不存在则申请一个空闲的页缓存

3.从磁盘读取数据到页缓存,并把页缓存的数据返回给用户

write

1.检查需要数据的页缓存是否存在

2.如果存在,直接写入页缓存,不存在则申请一个空闲的页缓存

3.从磁盘读取数据到页缓存,并把新数据写入页缓存

4.直接写入页缓存的修改操作,内核会定时刷新到磁盘中

Tips: 当内存不足时,Linux内核会采取LRU策略删除最近不常访问的页缓存

应用Page Cache产生流程图

Image.png

Page Cache管理不当可能带来的问题:

服务器的 load 飙高;
服务器的 I/O 吞吐飙高;
业务响应时延出现大的毛刺;
业务平均访问时延明显增加。

如何查看Page Cache
1.cat /proc/meminfo

[root@yz117 ~]# cat /proc/meminfo
MemTotal:        3826336 kB
MemFree:          428332 kB
MemAvailable:    3015212 kB
**Buffers**:            4244 kB
**Cached**:          2735372 kB
**SwapCached**:            0 kB
Active:           690720 kB
Inactive:        2451936 kB
Active(anon):        872 kB
Inactive(anon):   397352 kB
**Active(file)** :     689848 kB
**Inactive(file)** :  2054584 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:                32 kB
Writeback:             0 kB
AnonPages:        386156 kB
Mapped:           253896 kB
**Shmem**:              2424 kB
KReclaimable:      93720 kB
Slab:             154160 kB
SReclaimable:      93720 kB
SUnreclaim:        60440 kB
KernelStack:        3904 kB
PageTables:         9084 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     1913168 kB
Committed_AS:    1714332 kB
VmallocTotal:   34359738367 kB
VmallocUsed:           0 kB
VmallocChunk:          0 kB
Percpu:             2584 kB
HardwareCorrupted:     0 kB
AnonHugePages:    237568 kB
ShmemHugePages:        0 kB
ShmemPmdMapped:        0 kB
FileHugePages:         0 kB
FilePmdMapped:         0 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
Hugetlb:               0 kB
DirectMap4k:      176000 kB
DirectMap2M:     4018176 kB
DirectMap1G:     2097152 kB

公式
PG  = Buffers + Cached + SwapCached = Active(file) + Inactive(file) + Shmem +SwapCached

公式拆分\

Active(file)+Inactive(file)
即File-backed page(与文件对应的内存页),是我们最需要关注的部分。因为我们平时用的 mmap() 内存映射方式和 buffered I/O来消耗的内存就属于这部分。

SwapCached
是在打开了 Swap 分区后,把 Inactive(anon)+Active(anon) 这两项里的匿名页给交换到磁盘(swap out),然后再读入到内存(swap in)后分配的内存。 由于读入到内存后原来的 Swap File 还在,所以 SwapCached 也可以认为是 File-backedpage,即属于 Page Cache。这样做的目的也是为了减少 I/O。

Image.png Tips: 建议在生产环境中关闭Swap 分区,因为 Swap 过程产生的 I/O 会很容易引起性能抖动。

Shmem
是指匿名共享映射这种方式分配的内存(free 命令中 shared 这一项,比如 tmpfs(临时文件系统)。

2.free Image.png

公式
buff/cache = Buffers + Cached + SReclaimable

Tips :SReclaimable 是指可以被回收的内核内存,包括 dentry 和 inode 等, 所以可回收的内存会被记入buff/cache

一点补充

VFS
VFS是一个抽象层,其向上提供了统一的文件访问接口,而向下则兼容了各种不同的文件系统。不仅仅是诸如Ext2、Ext4、XFS和Btrfs等常规意义上的文件系统,还包括伪文件系统和设备等等内容。

VFS与文件系统的映射
挂载,也就是具体文件系统(例如Ext2)的挂载 -> user mount
打开文件,我们在访问一个文件之前首先要打开它(open)
文件访问,进行文件的读写操作(read或者write)\

MMAP
mmap 即 memory map,也就是内存映射。
mmap将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。 Image.png

MMAP的特点
mmap使用DMA取代CPU进行内存与其他硬件之间数据的拷贝,但是内存中的数据拷贝还是由CPU完成。
用户空间的mmap file使用虚拟内存,而不是物理内存,只有内核中的buffer cache才占据实际内存。
用户态和内核态共享同一份文件,节省了资源。
mmap使得进程可以使用指针的方式读写该段内存,内核会定期将内存刷新到磁盘上,减少了数据在内核态和用户态之间的拷贝,提升了IO操作的效率。
mmap需要搭配write使用,所以在与内核态交互时至少会有4次上下文的交换。
mmap的内存空间并不是一次性分配的,而是通过缺页异常机制来进行懒加载。
mmap的数据回写依赖于操作系统,有大量写操作时,会带来额外开销。