天天看點

資料緩沖區高速緩沖區學習總結1

轉載:http://blog.chinaunix.net/uid-20729583-id-1884567.html

下面所分析是linux早期核心的緩沖區結構,這裡僅僅是為了用來了解緩沖區的基本應用,對于目前的2.6核心有着很大的差別,但是,從這裡可以逐漸地對linux核心進行深入學習。這裡僅僅是一個簡單的介紹。

    一個緩沖頭結構中标志了對應緩沖塊的相關性質,采用緩沖頭結構組來對整個緩沖區的緩沖塊進行管理,操作友善。在緩沖區中,低端存儲區存放的是對應緩沖頭結構,高端區對應的是緩沖區資料結構,這是在進行緩沖區初始化過程中,初始化程式從整個緩沖區的兩端開始,分别同時設定緩沖區頭結構和對應的緩沖區。即第一個緩沖區頭結構所對應的是最後一個緩沖資料塊,如此遞推下去。(緩沖塊是1024個位元組的塊)

緩沖頭結構的結構分析:

裝置号、塊号、狀态(含有目前緩沖區狀态)以及其他一些算法所需要的資料。

高速緩沖塊采用hash表和包含所有緩沖區塊的連結清單來進行管理操作。

1塊緩沖區即1024個位元組,低端(對應各緩沖塊的緩沖頭結構)分别建立起對應各緩沖塊的緩沖頭結構buffer_head,這些緩沖頭連接配接成連結清單,進而對整個緩沖區進行操控。

下面這個是linux0.11核心中所定義的緩沖區頭結構:

struct buffer_header{

    char *b_data;

    unsigned short b_dev;

    unsigned char b_uptodate;

    unsigned char b_dirt;

    unsigned chart b_count;

    unsigned char b_lock;

    struct task_struct * b_wait;    

    struct buffer_head *b_prev;

    struct buffer_head *b_next;

    struct buffer_head *b_prev_free;

    struct buffer_head *b_next_free;

}

(我們所研究的緩沖區是磁盤塊在主存中的拷貝,一個緩沖區的資料與檔案系統上一個邏輯磁盤塊中的資料想對應,并且核心是通過考察緩沖區頭部中的辨別字元來識别緩沖區内容的。緩沖區的内容并不是永久存在的,而是每隔一定時間間斷就會發生更新的區域。)

b_block鎖定标志,表示驅動程式正在對該緩沖區内容進行操作,此時該緩沖區不能被第二者通路。這裡可以發現,對緩沖區的直接操作是驅動程式,而不是應用程式,應用程式通過調用系統調用來對緩沖區進行相應的操作。

思考:向緩沖塊中寫資料的寫操作不由CPU控制,CPU起到 的隻是控制管理功能而已。而緩沖塊中寫資料寫操作則是由硬體來完成,如何為完成???

b_count緩沖buffer使用之計數值,表示相應緩沖塊正被各個程序使用的次數,主要用于對緩沖塊的程式引用計數管理,所謂空閑塊指b_count=0的塊。

b_update是資料更新标志,說明緩沖塊中資料是否有效。b_dirt和b_update标志的應用是很重要的,同時一很容易弄混淆,b_dirt所起到的作用是當緩沖區中的資料被改變時,相應的b_dir被指派為1,表明此時緩沖區中的資料與磁盤塊中的資料是不同的,這就意味着磁盤中的資料需要重新寫,即更新,所使用的是延遲寫。而b_update說明緩沖塊中的資料是否有效。當我們将釋放塊時,這兩個值被賦為0,表明該緩沖區中的資料無效,這裡的釋放塊指的是将緩沖區的資料進行了釋放更新,緩沖區中的資料已經不再被目前程序使用,而磁盤中的資料并沒有丢失,隻是緩沖區中的資料丢失了而已。當b_dir比指明為1時,用通俗的話說這個塊髒了,需要将其中的内容寫入磁盤塊中,但是此時還沒有将其放入到磁盤中,是以資料是無效的。隻有當資料被寫入到磁盤裝置或者是從塊裝置中讀入緩沖塊時,資料才是變為有效的。

接下來,來看看緩沖頭結構buffer_head結構中字段類型為buffer_head的幾個字段的用法,下面這個函數是從linux0.11核心代碼中摘錄下來的,主要是使用了buffer_head這幾個字段來進行操作,很容易了解:

函數的功能是:将緩沖塊插入空閑連結清單尾部,同時放入hash隊列中。

static inline void insert_info_queues(struct buffer_head * bh)

{

   bh->b_next_free=free_list;//将bh指向的下一個節點指定為free_list,即空閑表的頭指針;

   bh->b_prev_free=free_list->b_prev_free;//将bh的後指針指向為之前空閑表的最後一個節點;

   free_list->b_prev_free->b_next_free=bh;

   free_list->b_prev_free=bh;

   bh->b_prev=NULL;

   bh->b_next=NULL;

   if(!bh->b_dev)

          return;

   bh->b_next=hash(bh->b_dev,bh->b_blocknr);

   hash(bh->b_dev,bh->b_blocknr)=bh;

   bh->b_next->b_prev=bh;

}

以上的代碼程式就是對buffer_head中buffer_head字段的使用,這就是這些字段作用之一,有趣吧!

現在來分析緩沖區所使用的兩個資料結構:散清單和空閑表。

緩沖區中的所有塊是通過散清單進行管理和操作的,對于磁盤而言,如果要使用散清單來進行管理,其散清單是不變的。但是,高速緩沖區中的散清單是變化着的。散清單的控制操作是由對應的散列函數進行實施的。要注意的是,緩沖塊所存在的散清單并不是規定的,可以結合實際來安排,當然,系統所追求的是一種均衡的配置設定方式,這樣做隻是為了更好地對緩沖塊進行管理,同時效率也是很高的!

一個緩沖塊可以存在于兩個連結清單中:散清單或者是空閑表。如果我們需要尋找一個特定的緩沖塊,我們可以在散清單中尋找,舉個例子:在一個作業系統中,有多個程序在執行着,現在程序1在使用一個緩沖塊,此時程序2也需要通路相應的塊,那麼程序2就會在散清單中進行尋找,而不是到空閑表中尋找。

而buffer_head結構的字段:b_next、b_prev、b_prev_free、b_next_free就是用來對散清單和空閑表進行操作的。

這僅僅是對緩沖區頭結構進行的一個簡單的學習總結,還有相應算法會頻繁使用到這些字段,相應的總結将在後面的總結中列出。

如果相對高速緩沖有更直接的認識,了解記憶體結構是很有好處的,是以,要把記憶體管理弄明白。呵呵!

繼續閱讀