《Linux內核設計與實現》讀書筆記——頁高速緩存和頁回寫

頁高速緩存

頁高速緩存是Linux內核實現磁盤緩存,它的主要作用是減少對磁盤的IO操作。

頁高速緩存是由內存中的物理頁組成的,其內容對應磁盤上的物理塊。

當內核開始一個讀操作時,會先檢查需要的數據是否在頁高速緩存中。

寫緩存有幾種策略:

  • 不緩存;
  • 同時更新內存緩存和磁盤文件;
  • 回寫:數據直接寫到內存緩存,而磁盤寫放到回寫進程中稍後處理(由flusher線程完成,用戶進程中可以通過sync()和fsync()系統調用來完成);

頁高速緩存能夠動態調整。

當需要騰出空間給其它地方使用是,會採用的是緩存回收策略回收內存緩存。

Linux採用雙鏈策略。

頁高速緩存緩存任何基於頁的對象,包括各種類型的文件和各種類型的內存映射。(前面有提到主要是爲了磁盤緩存,但是實際上可以緩存的有很多)

 

address_space對象

Linux頁高速緩存使用address_space結構體管理緩存項和頁IO操作。

address_space結構體如下:

struct address_space {
    struct inode        *host;      /* owner: inode, block_device */
    struct radix_tree_root  page_tree;  /* radix tree of all pages */
    spinlock_t      tree_lock;  /* and lock protecting it */
    unsigned int        i_mmap_writable;/* count VM_SHARED mappings */
    struct prio_tree_root   i_mmap;     /* tree of private and shared mappings */
    struct list_head    i_mmap_nonlinear;/*list VM_NONLINEAR mappings */
    spinlock_t      i_mmap_lock;    /* protect tree, count, list */
    unsigned int        truncate_count; /* Cover race condition with truncate */
    unsigned long       nrpages;    /* number of total pages */
    pgoff_t         writeback_index;/* writeback starts here */
    const struct address_space_operations *a_ops;   /* methods */
    unsigned long       flags;      /* error bits/gfp mask */
    struct backing_dev_info *backing_dev_info; /* device readahead, etc */
    spinlock_t      private_lock;   /* for use by the address_space */
    struct list_head    private_list;   /* ditto */
    struct address_space    *assoc_mapping; /* ditto */
} __attribute__((aligned(sizeof(long))));

其中a_ops指向地址空間對象中的操作函數表:

struct address_space_operations {
    int (*writepage)(struct page *page, struct writeback_control *wbc);
    int (*readpage)(struct file *, struct page *);
    void (*sync_page)(struct page *);
    /* Write back some dirty pages from this mapping. */
    int (*writepages)(struct address_space *, struct writeback_control *);
    /* Set a page dirty.  Return true if this dirtied it */
    int (*set_page_dirty)(struct page *page);
    int (*readpages)(struct file *filp, struct address_space *mapping,
            struct list_head *pages, unsigned nr_pages);
    int (*write_begin)(struct file *, struct address_space *mapping,
                loff_t pos, unsigned len, unsigned flags,
                struct page **pagep, void **fsdata);
    int (*write_end)(struct file *, struct address_space *mapping,
                loff_t pos, unsigned len, unsigned copied,
                struct page *page, void *fsdata);
    /* Unfortunately this kludge is needed for FIBMAP. Don't use it */
    sector_t (*bmap)(struct address_space *, sector_t);
    void (*invalidatepage) (struct page *, unsigned long);
    int (*releasepage) (struct page *, gfp_t);
    ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
            loff_t offset, unsigned long nr_segs);
    int (*get_xip_mem)(struct address_space *, pgoff_t, int,
                        void **, unsigned long *);
    /* migrate the contents of a page to the specified target */
    int (*migratepage) (struct address_space *,
            struct page *, struct page *);
    int (*launder_page) (struct page *);
    int (*is_partially_uptodate) (struct page *, read_descriptor_t *,
                    unsigned long);
    int (*error_remove_page)(struct address_space *, struct page *);
};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章