Linux運用一個功能廣泛的緩沖和緩存框架來提高系統的速度。緩沖和緩存利用一部分系統物理內存,確保最重要、最常使用的塊設備數據在操作時可直接從主內存獲取,而無需從低速設備讀取。物理內存還用於存儲從快設備讀取的數據,使得隨後對該數據的訪問可直接在物理內存進行,而無需從外部設備再次取用。考慮系統中多種因素然後延遲寫回在總體上改進了系統的性能。前面分析的部分,例如內存管理的slab緩存是一個內存到內存的緩存,其目地不是加速對低速設備的操作,而是對現有資源進行更簡單、更高效的使用。文件系統的Dentry緩存也用於減少對低速塊設備的訪問,但他無法推廣到通用場合,因為他是專門用於處理單一數據類型的。
內核為塊設備提供了兩種通用的緩存方案:
1) 頁緩存,針對以頁為單位的所有操作,並考慮了特定體系結構上的頁長度。一個主要的例子是內存映射技術。因為其他類型的文件訪問也是基於內核中的這一技術實現的。所以頁緩存實際上負責了塊設備的大部分緩存工作。
2) 塊緩存,以塊為操作單位。在進行I/O操作時,存取的單位是設備的各個塊,而不是整個內存頁。盡管頁長度對所有文件系統都是相同的,但塊長度取決於特定的文件系統或其設置。因而,塊緩存必須能夠處理不同長度的塊。
目前用於塊傳輸的標准數據結構已經演變為struct bio。用這種方式進行塊傳輸更為高效,因為他可以合並同一請求中後續的塊,加速處理的進行。在許多場合下,頁緩存和塊緩存是聯合使用的。例如,一個緩存的頁在寫操作期間可以劃分為不同的緩沖區,這樣可以在更細的力度下,識別出頁被修改的部分。好處在於,在將數據寫回時,只需要回寫被修改的部分,無需將這個頁面傳輸回底層的塊設備。
頁面緩存結構
[cpp]
- /*高速緩存的核心數據結構,對塊設備的讀寫操作都放在該結構體裡*/
- struct address_space {
- /*與地址空間所管理的區域之間的關聯數據結構之一
- inode結構指定了後備存儲器*/
- struct inode *host; /* owner: inode, block_device */
- /*與地址空間所管理的區域之間的關聯之二
- ,page_tree列出了地址空間中所有的物理內存頁*/
- struct radix_tree_root page_tree; /* radix tree of all pages */
- spinlock_t tree_lock; /* and lock protecting it */
- /*所有用VM_SHARED屬性創建的映射*/
- unsigned int i_mmap_writable;/* count VM_SHARED mappings */
- /*基數根節點,該樹包含了與該inode相關的所有
- 普通內存映射。該樹的任務在於,支持查找包含了
- 給定區間中至少一頁的所有內存區域*/
- 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 */
- /*集主要用於保存映射頁所來自的GFP內存區
- 的有關信息*/
- 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 */
- /*用於將包含文件系統元數據(通常是間接塊)的buffer_head
- 實例彼此連接起來*/
- struct list_head private_list; /* ditto */
- /*指向相關的地址空間的指針*/
- struct address_space *assoc_mapping; /* ditto */
- } __attribute__((aligned(sizeof(long))));
後備存儲信息
[cpp]
- struct backing_dev_info {
- struct list_head bdi_list;
- struct rcu_head rcu_head;
- /*最大預讀數量,單位為PAGE_CACHE_SIZE*/
- unsigned long ra_pages; /* max readahead in PAGE_CACHE_SIZE units */
- /*對該成員,總是使用原子操作,指定了後備存儲器的狀態*/
- unsigned long state; /* Always use atomic bitops on this */
- /*設備能力*/
- unsigned int capabilities; /* Device capabilities */
- congested_fn *congested_fn; /* Function pointer if device is md/dm */
- void *congested_data; /* Pointer to aux data for congested func */
- void (*unplug_io_fn)(struct backing_dev_info *, struct page *);
- void *unplug_io_data;
-
- char *name;
-
- struct percpu_counter bdi_stat[NR_BDI_STAT_ITEMS];
-
- struct prop_local_percpu completions;
- int dirty_exceeded;
-
- unsigned int min_ratio;
- unsigned int max_ratio, max_prop_frac;
-
- struct bdi_writeback wb; /* default writeback info for this bdi */
- spinlock_t wb_lock; /* protects update side of wb_list */
- struct list_head wb_list; /* the flusher threads hanging off this bdi */
- unsigned long wb_mask; /* bitmask of registered tasks */
- unsigned int wb_cnt; /* number of registered tasks */
-
- struct list_head work_list;
-
- struct device *dev;
-
- #ifdef CONFIG_DEBUG_FS
- struct dentry *debug_dir;
- struct dentry *debug_stats;
- #endif
- };
下圖為地址空間與內核其他部分的關聯。