天天看點

[深入了解檔案系統之三] Buffer Cache

  由于通路記憶體的速度比通路磁盤的速度快了幾個數量級,如果能對經常用到的或者最近可能要用到的磁盤上的資料提前讀出來,存放在記憶體當中,就能明顯縮短讀寫完成的時間,顯著提高性能。為此在檔案系統中緩存機制在許多地方得到了應用。總結起來,常用到的有buffer cache、 page cache、 和DNLC(Directory name look-up cache)三種,分别用在對meta-data、data讀寫以及路徑名解析的場景。 下面重點介紹下buffer cache。

    為了能對buffer cache有些基本的感性認識,将從unix和linux系統分别看看buffer cache。

Unix系統中buffer的概念,當然需要結合它的資料結構去了解。剛開始本人的了解是有點類似于Linux中的

BIO的原型,後來才明白BIO主要是用來記錄從上層傳遞到底層的io請求的 ,而buffer cache是和page 

cache相對的,主要是用來緩存對meta data (blkptr/inde/等) 的通路的。buffer cache中buffer具體

的資料結構如下:

buf如何初始化: 核心啟動的時候初始化,在unix中是初始化NBUF個buffers。

Buf cache如何實作:在IO完成、buffer釋放之後,被釋放的buf會被放到av_forw/av_back指向的buf空

閑清單裡面去,但此時它的identifier(device ID + block offset)會在被重放被别的請求申請、使用之前

一直保留,是以後面的讀隻需要直接從記憶體裡讀出就好了。

基于buf的兩個最主要的接口函數:(對應于buffer cache的主要操作)

bread():

a. call getblk(device ID, block offset); (check whether the buffer is already in buffer caches),

return if true;

b. call iowait() if cache missed

bwrite():和bread()類似,也是調用那連個函數。

而在Linux中buffer cache又是如何實作、怎麼使用的呢?

    Linux中的Buffer cache顧名思義,buffer cache也是緩沖區組成的磁盤高速緩存。

在linux中,每個緩沖區都存放一個單獨的磁盤塊,塊IO操作依靠buffer cache來減小對磁盤的慢速訪

問,比如讀ext2超級塊、inode節點。

    在linux中buffer cache同樣提供了接口函數,包括:bread()

和unix的差別是bwrite():不存在專門的bwrite(), 這是因為隻需要設定磁盤塊對應buffer的dirty位置為

1, 就可以被後續的核心線程寫會到磁盤。

Linux如何辨別一個buffer to cache: 塊裝置ID/major/minor device ID / + 塊内偏移

何時加入cache:在通過bread()讀索引節點或者超級塊的時候

a. getblk() 根據參數中的裝置标示符、塊号以及塊大小,在buffer cache 中查找;如命中就傳回該buffer; 如果不命中傳回一個新的buffer;

b.調用mark_page_accessed()來标記這個新的buffer 

c.如果緩沖區已有有效資料,則終止;

d.調用ll_rw_block()開始從磁盤讀資料;

e.通過wait_on_buffer()等待,直到資料傳送完畢。原理是這個函數會把核心current()程序、線程放到那

個新的buffer的緩沖區首部的strucut wait_queue * b_wait 字段隊列中。

如何判斷命中:根據上面的描述,不難看到是在buffer cache 數組中找到了指定id的buffer頭部

何時從cache中調出:(替換政策) LRU  

針對磁盤上的哪些資料:inode/ 超級塊

本文轉自存儲之廚51CTO部落格,原文連結:http://blog.51cto.com/xiamachao/1901799 ,如需轉載請自行聯系原作者

繼續閱讀