注:本文代码基于linux-3.18.31,此版本中块缓存已经合入页缓存。
写在前面
普通文件和块设备文件都有一个address_space对象,inode中分别维护两个成员指向这两个不同的address_space,分别是i_mapping和i_data。需要注意的是,这两个page cache中可能拥有磁盘上相同的数据(即拥有相同的页数据)。
struct inode {
…………
const struct inode_operations *i_op;
struct super_block *i_sb;
struct address_space *i_mapping; //对应于普通文件的页缓存
…………
struct address_space i_data; //对应于块设备文件的页缓存
struct list_head i_devices;
union {
struct pipe_inode_info *i_pipe;
struct block_device *i_bdev; //块设备inode对应的块设备描述符
struct cdev *i_cdev;
char *i_link;
};
};
普通文件的address space
文件系统读取文件一般会使用do_generic_file_read(),mapping指向普通文件的address space。如果一个文件的某一块不在page cache中,在find_get_page函数中会创建一个page,并将这个page根据index插入到这个普通文件的address space中。这也是我们熟知的过程。
static ssize_t do_generic_file_read(struct file *filp, loff_t *ppos,
struct iov_iter *iter, ssize_t written)
{
struct address_space *mapping = filp->f_mapping;
struct inode *</