定义
PageCache 是一个逻辑上的概念,指定是用于缓存disk数据到内存中的内存页。
数据结构
Page cache的核心结构体是**address_space**。
它是连接文件(inode)和内存页面(page)的桥梁 。每个打开的文件都有一个对应的 address_space,它管理该文件在内存中的所有缓存页。
在include/linux/fs.h文件中
cpp
// PageCache 的核心数据结构
struct address_space {
struct inode *host; // 所属文件
struct xarray i_pages; // cache page们
struct rw_semaphore invalidate_lock;
gfp_t gfp_mask;
atomic_t i_mmap_writable; /* 可写映射计数 */
#ifdef CONFIG_READ_ONLY_THP_FOR_FS
/* number of thp, only for non-shmem files */
atomic_t nr_thps;
#endif
struct rb_root_cached i_mmap; /* 私有映射树 */
struct rw_semaphore i_mmap_rwsem;
unsigned long nrpages; /* 页面总数 */
pgoff_t writeback_index;
const struct address_space_operations *a_ops; /* 操作函数 */
unsigned long flags;
errseq_t wb_err;
spinlock_t private_lock;
struct list_head private_list;
void *private_data;
} __attribute__((aligned(sizeof(long)))) __randomize_layout;
如何关联起来:
一个文件 (inode)
↓
一个 address_space
↓
管理该文件的所有page cache (通过 i_pages)
cpp
struct inode {
// ...
struct address_space *i_mapping; // 文件的主要映射
struct address_space i_data; // 文件的地址空间
};
cpp
// PageCache 页面在内存中的状态
struct page {
struct address_space *mapping; // 属于哪个 PageCache
pgoff_t index; // 在文件中的偏移
struct list_head lru; // ← 链接到 LRU 链表
// ...
};
cpp
struct task_struct
↓ 通过mm_struct
struct mm_struct
↓ 通过VMA链表
struct vm_area_struct // 虚拟内存区域
↓ vm_file指向
struct file
↓ f_mapping指向
struct address_space // ← 我们关注的
↓ host指向
struct inode // 文件inode
↓ i_pages指向
struct address_space // 其实是同一个
↓ page_tree包含
struct page // 物理页面
↓ lru指向
LRU 链表管理
├── LRU_INACTIVE_FILE 链表
└── LRU_ACTIVE_FILE 链表
PageCache 页面的生命周期
首次访问文件页
↓
分配物理页struct page(Buddy System)
↓
读入磁盘数据
↓
加入 PageCache(address_space)
↓
加入 LRU_INACTIVE_FILE
↓
再次访问 → 移到 LRU_ACTIVE_FILE
↓
内存压力 → 页面回收
├── 干净页 → 直接释放
└── 脏页 → 写回后释放