1,概念
页缓存:以页为单位的操作,负责大部分块设备的缓存工作
块缓存:以块为单位的IO操作,块大小与设备文件系统设置相关
缓冲区:将页按照块大小划分为大小相等的存储空间,每个存储空间称为缓冲区,每个缓冲区是文件块在内存中的映射
2,查看页缓存和块缓存
查看命令:free,top,也可以在sysfs文件系统中查看,以free为例
图中bufer/cache:buffer即为buffer cache,cache即为page cache
3,数据结构
struct page:物理页帧
struct address_space:实现缓存的重要数据结构
struct address_space {
struct inode *host;
// 从内核4.20-rc1版本开始使用struct xarray数据结构
struct radix_tree_root *page_tree;
const struct address_space_operations *a_ops; //特定文件系统与块子系统交互接口
... ...
}
在新的内核版本中存放页缓存的数据结构已经改为xarray,所以此处不对基数树进一步讨论
struct radix_tree_root:基数树,缓存页存放的数据结构
struct radix_tree_node:基数树的节点
struct buffer_head:缓冲区头,表示一个块大小的缓冲区
4,文件系统,页缓存,块缓存,块设备之间示意图:
5,页缓存API
页缓存的实现是基于基数树的增删改查:
分配页缓存:page_cache_alloc
查询缓存页:find_get_page
删除缓存页:delete_from_page_cache
6,块缓存
块缓存有两种:用于实现页缓存的块缓存,直接使用块缓存的部分
用于实现页缓存的块缓存实现如下示意图:
块缓冲区操作API:
创建块缓冲区:create_page_buffers
查询块缓冲区:_ext4_get_block 创建缓冲区与硬盘上文件块的映射
删除块缓冲区:free_buffers/try_to_free_buffers
文件系统与块子系统通过address_space交互流程:
ext4文件系统中的address_space_operations 数据结构实例:
当VFS在address_space的页缓存中获取存储了偏移量为index的文件数据时如下三种情况会使用特定文件系统的address_space_operations读取磁盘文件数据到指定的物理页帧:
1,从address_space的页缓存没有获取到物理页帧
2,获取到的物理页帧数据不是最新的
3,获取到的物理页帧中的部分块数据不是最新的
ext4文件系统与块子系统交互示意图如下图(以ext4为例):
直接使用块缓存的场景:
例如:挂在文件系统的时候读取文件系统的super_block块数据,接口:sb_getblk
7,页缓存与块缓存的联系
8,代码导读:以ext4文件系统的read系统调用为例
generic_file_buffered_read核心部分分析:
page_cache_async_readahead函数的核心实现分析: