頁高速緩存
頁高速緩存是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 *);
};