Page Cache

page cache,又稱pcache,其中文名稱為頁高速緩衝存儲器,簡稱頁高緩。在從外存的一頁到記憶體的一頁的映射過程中,page cache與buffer cache、swap cache共同實現了高速快取功能。

一、page cache簡介
page cache,又稱pcache,其中文名稱為頁高速緩衝存儲器,簡稱頁高緩。page cache的大小為一頁,通常為4K。在linux讀寫檔案時,它用於快取檔案的邏輯內容,從而加快對磁碟上映像和數據的訪問。
二、page cache的功能詳解
在從外存的一頁到記憶體的一頁的映射過程中,page cache與Buffer Cache、swap cache共同實現了高速快取功能,以下是其簡單映射圖,
外存的一頁(分解為幾塊,可能不連續)
|
|
物理磁碟的磁碟塊
|
|
記憶體的buffer cache
|
|
記憶體的一頁(由一個頁框劃分的幾個連續buffer cache構成)
|
|
頁高緩系統
在這個過程中,記憶體管理系統和VFS與page cache互動,記憶體管理系統負責維護每項page cache的分配和回收,同時在使用memory map方式訪問時負責建立映射;VFS負責page cache與用戶空間的數據交換。
三、page cache的管理
在Linux核心中,檔案的每個數據塊最多只能對應一個page cache項,它通過兩個數據結構來管理這些cache項,一個是radix tree,另一個是雙向鍊表
Radix tree是一種搜尋樹,Linux核心利用這個數據結構,快速查找髒的(dirty)和回寫的(writeback)頁面,得到其檔案內偏移,從而對page cache進行快速定位。圖1是radix tree的一個示意圖,該radix tree的分叉為4(22),樹高為4,用來快速定位8位檔案內偏移。
另一個數據結構是雙向鍊表,Linux核心為每一片物理記憶體區域(zone)維護active_list和 inactive_list兩個雙向鍊表,這兩個list主要用來實現物理記憶體的回收。這兩個鍊表上除了檔案Cache之外,還包括其它匿名 (Anonymous)記憶體,如進程堆疊等。
四、page cache相關API及其實現
Linux核心中與檔案Cache操作相關的API有很多,按其使用方式可以分成兩類:一類是以拷貝方式操作的相關接口,如read/write/sendfile等,其中sendfile在2.6系列的核心中已經不再支持;另一類是以地址映射方式操作的相關接口,如mmap等。
第一種類型的API在不同檔案的Cache之間或者Cache與應用程式所提供的用戶空間buffer之間拷貝數據,其實現原理如圖2所示。
第二種類型的API將Cache項映射到用戶空間,使得應用程式可以像使用記憶體指針一樣訪問檔案,Memory map訪問Cache的方式在核心中是採用請求頁面機制實現的,其工作過程如圖3所示。
首先,應用程式調用mmap(圖中1),陷入到核心中後調用do_mmap_pgoff(圖中2)。該函式從應用程式的地址空間中分配一段區域作為映射的記憶體地址,並使用一個VMA(vm_area_struct)結構代表該區域,之後就返回到應用程式(圖中3)。當應用程式訪問mmap所返回的地址指針時(圖中4),由於虛實映射尚未建立,會觸發缺頁中斷(圖中5)。之後系統會調用缺頁中斷處理函式(圖中6),在缺頁中斷處理函式中,核心通過相應區域的 VMA結構判斷出該區域屬於檔案映射,於是調用具體檔案系統的接口讀入相應的Page Cache項(圖中7、8、9),並填寫相應的虛實映射表。經過這些步驟之後,應用程式就可以正常訪問相應的記憶體區域了。

加入/離開page cache還涉及到如下幾個函式:

add_page_to_hash_queue /*加入pache cache hash表*/
add_page_to_inode_queue /*加入inode queue即address_space*/
remove_page_from_inode_queue
remove_page_from_hash_queue
__remove_inode_page /*離開inode queue和hash 表*/
remove_inode_page /*同上*/
add_to_page_cache_locked /*加入inode queue,hash 和lru cache*/
__add_to_page_cache /*同上*/
僅羅列函式add_page_to_hash_queue,以示完整:
color=green>
static void add_page_to_hash_queue(struct page * page, struct page **p)
{
struct page *next = *p;
*p = page; /* page->newNode */
page->next_hash = next; /* +-----+ */
page->pprev_hash = p; /* p--> |hashp|-->|oldNode| */
if (next) /* next----+ */
next->pprev_hash = &page->next_hash;
if (page->buffers)
PAGE_BUG(page); /*證明page 不會同時存在於page cache
和 buffer cache*/
/*2.6 已經與此不同了*/
atomic_inc(&page_cache_size);
}

page cache 和 inode

page cache 在代碼中又稱 inode page cache, 足以顯示page cache 和inode緊密關聯.加入page cache 和加入inode cache是同一個意思.加入page cache意味著同時加入page cache hash表和inode queue(也建立了page和addr sapce的關係). 見函式add_to_page_cache_locked,__add_to_page_cache即可取證.從page cache 刪除在程式中叫__remove_inode_page,再次顯示inode 和page cache的"一體化".

相關詞條

相關搜尋

熱門詞條

聯絡我們