《Linux内核设计与实现》学习【11】—— 页高速缓存和页回写

本文详细介绍了Linux系统中为了提高磁盘访问速度的缓存机制,包括页高速缓存和缓冲区高速缓存。页高速缓存采用回写策略,通过address_space结构管理数据,使用LRU和双链策略回收缓存。缓冲区高速缓存对应磁盘块,按页面管理。此外,flusher线程负责在特定条件下将脏页写回磁盘,确保数据一致性。
摘要由CSDN通过智能技术生成

1 缓存

  linux为了提高对磁盘的访问速度,通过把磁盘中的数据缓存到物理内存中,把对磁盘的访问变为对物理内存的访问。
  两个重要因素:
  1)访问磁盘的速度要远低于访问内存的速度,若从处理器L1和L2高速缓存访问则速度更快。
  2)数据一旦被访问,就很有可能短时间内再次访问。

1.1 缓存策略

3种策略:
  1)不缓存:不缓存写操作,当对缓存中的数据进行写操作时,直接写入磁盘,同时使此数据的缓存失效
  2)写透缓存:写数据时同时更新磁盘和缓存
  3)回写:先写到缓存,并将页面标记为“脏”,加入脏页链表,由回写进程周期性将脏页链表中的页写回到磁盘。linux采用此方法。

1.2 缓存回收

(1)最近最少使用LRU:将最近最少使用的页面进行回收
(2)双链策略:内核基于LRU,维护两个链表:活跃链表和非活跃链表,页面会在这两个双向链表中移动,操作系统会根据页面的活跃程度来判断应该把页面放到哪个链表上。

2 页高速缓存

   一个物理页可能由多个不连续的物理磁盘块组成。也正是由于页面中映射的磁盘块不一定连续,所以在页高速缓存中检测特定数据是否已被缓存就变得不那么容易了。
(1)address_space
   用于管理缓存项和页IO操作。文件可以有多个虚拟地址,但是这个文件只能有一个address_space对象。

struct address_space {
    struct inode        *host;        /* 拥有此 address_space 的inode对象 */
    struct radix_tree_root    page_tree;    /* 包含全部页面的 radix 树 */
    spinlock_t        tree_lock;    /* 保护 radix 树的自旋锁 */
    unsigned int        i_mmap_writable;/* VM_SHARED 计数 */
    struct prio_tree_root    i_mmap;        /* 私有映射链表的树 */
    struct list_head    i_mmap_nonlinear;/* VM_NONLINEAR 链表 */
    spinlock_t        i_mmap_lock;    /* 保护 i_map 的自旋锁 */
    unsigned int        truncate_count;    /* 截断计数 */
    unsigned long        nrpages;    /* 总页数 */
    pgoff_t            writeback_index;/* 回写的起始偏移 */
    const struct address_space_operations *a_ops;    /* address_space 的操作表 */
    unsigned long        flags;        /* gfp_mask 掩码与错误标识 */
    struct backing_dev_info *backing_dev_info; /* 预读信息 */
    spinlock_t        private_lock;    /* 私有 address_space 自旋锁 */
    struct list_head    private_list;    /* 私有 address_space 链表 */
    struct address_space    *assoc_mapping;    /* 缓冲 */
    struct mutex        unmap_mutex;    /* 保护未映射页的 mutux 锁 */
} __attribute__((aligned(sizeof(long))));

   一个具体的文件在打开后, 内核会在内存中为之建立一个struct inode结构,其中的i_mapping域指向一个address_space结构。这样,一个文件就对应一个address_space结构。
(2)操作
找数据

page = find_get_page(mapping, index);

(2)基树
  需要高效地检查页是否在页高速缓存中。
  每个address_space对象都有唯一的基树,它保存在page_tree结构体中。
(3)关系
  1)一个inode节点对象对应一个address_space对象。其中inode节点对象的i_mapping和i_data字段指向相应的 address_space对象,而address_space对象的host字段指向对应的inode节点对象。
  2)每个address_space对象对应一颗基树。他们之间的联系是通过address_space对象中的page_tree字段指向该address_space对象对应的基树。
  3)一般情况下一个inode节点对象对应的文件或者是块设备都会包含多个页面的内容,所以一个inode对象对应多个page描述符。同一个文件拥有的所有page描述符都可以再该文件对应的基树中找到。

3 缓冲区高速缓存

缓冲——buffer——对应磁盘块
缓存——cache——按页面管理

4 flusher线程

在以下3种情况发生时,一群flusher进行回写:
  1)当空闲内存低于一个阀值时
  2)当脏页在内存中驻留时间超过一个阀值时
  3.)当用户进程调用 sync() 和 fsync() 系统调用时
(1)2.6以前
  bdflush:一个bdflush线程,在内存过低或缓冲数较大时,将脏缓冲写回磁盘。
  kupdated:周期性地写回脏页。
(2)pdflush
  线程数目是动态的
(3)flusher
  线程的数目不唯一
  基于页面,将脏页写回磁盘
  每个 flusher 线程对应一个磁盘

参考:
Linux 2.6 中的页面回收与反向映射
linux文件系统的页高速缓存page cache中的核心数据结构address_space

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值