1. 程式人生 > >block(塊),page(頁),buffer cache(塊緩衝區)之間的關係

block(塊),page(頁),buffer cache(塊緩衝區)之間的關係

原文地址:https://blog.csdn.net/menogen/article/details/32701457

關於blok vs page 的可以參考以下一段描述:

Storing Blocks in the Page Cache

In old versions of the Linux kernel, there were two different main disk caches: the page cache, which stored whole pages of disk data resulting from accesses to the contents of the disk files, and the buffer cache, which was used to keep in memory the contents of the blocks accessed by the VFS to manage the disk-based filesystems. Starting from stable version 2.4.10, the buffer cache does not really exist anymore. In fact, for reasons of efficiency, block buffers are no longer allocated individually; instead, they are stored in dedicated pages called “buffer pages,” which are kept in the page cache.Formally, abuffer pageis a page of data associated with additional descriptors called “buffer heads,” whose main purpose is to quickly locate the disk address of each individual block in the page. In fact, the chunks of data stored in a page belonging to the page cache are not necessarily adjacent on disk.

在 記憶體頁中,有一種叫專門用途的頁面叫“緩衝區頁”,用來放塊緩衝區。而每個塊快取區由兩部分組成:緩衝區首部(用資料結構buffer_head表示)及真正的緩衝區內容(即所儲存的資料,存放在緩衝區頁中)。在緩衝區首部中,有一個指向資料的指標和一個緩衝區長度的欄位。
每個緩衝區與一個塊對應,它相當於磁碟塊在記憶體中的表示。檔案在記憶體中由file結構體表示,而磁碟塊在記憶體中是由緩衝區來進行表示的。由於核心處理塊時需要一些資訊,如塊屬於哪個裝置與塊對應於哪個緩衝區,所以每個緩衝區都有一個緩衝區描述符,稱為buffer_head,它包含了核心操作緩衝區所需要的全部資訊。

struct buffer_head {

    unsigned long b_state;        /* buffer state bitmap (see above) *緩衝區的狀態標誌/

    struct buffer_head *b_this_page;/* circular list of page's buffers *頁面中緩衝區/(一般一個頁面會有多個塊組成,一個頁面中的塊是以一個迴圈連結串列組成在一起的,該欄位指向下一個緩衝區首部的地址。)

    struct page *b_page;        /* the page this bh is mapped to *儲存緩衝區的頁面/(指向擁有該塊的頁面的頁面描述符)

    sector_t b_blocknr;        /* start block number *邏輯塊號/

    size_t b_size;            /* size of mapping *塊大小/

    char *b_data;            /* pointer to data within the page *指向該塊對應的資料的指標/

    struct block_device *b_bdev;       //對應的塊裝置(通常是指磁碟或者是分割槽)

    bh_end_io_t *b_end_io;        /* I/O completion */

     void *b_private;        /* reserved for b_end_io *I/O完成的方法/

    struct list_head b_assoc_buffers; /* associated with another mapping */

    struct address_space *b_assoc_map;    /* mapping this buffer is associated with *緩衝區對應的對映,即address_space/

    atomic_t b_count;        /* users using this buffer_head *表示緩衝區的使用計數/

};

buffer_head中有兩個欄位表示塊的磁碟地址:b_bdev表示包含該塊的塊裝置(通常是磁碟或者分割槽)及b_blocknr存放邏輯塊號,也就是塊在磁碟或分割槽中的編號,b_data欄位表示塊緩衝區資料在緩衝區頁中的位置。b_state存放緩衝區的狀態,例如BH_uptodate(緩衝區包含有效資料時候被置位),Bh_Dirty(緩衝區髒就置位),BH_New(如果相應的塊剛被分配而還沒被訪問過就置位)。

只要核心必須單獨訪問一個塊,就要涉及存放塊緩衝區中的緩衝區頁,並檢查相應的buffer_head

一個應用例項:如果虛擬檔案系統要讀1024個位元組的inode 塊,核心並不是只分配一個單獨的緩衝區,而是必須分配一整個頁,從而存放4個緩衝區(假設頁大小4k),這些緩衝區將存放塊裝置上相鄰的四塊資料。它們之間的關係如下:(假定一個塊是1K ,一個頁是4K )。
在這裡插入圖片描述


在一個緩衝頁內所有塊緩衝區大小必須相同,因此,在80X86體系結構上,根據塊的小大,一個緩衝區頁可以包括1~8個緩衝區。如果一個頁作為緩衝區頁使用,那麼與它的塊緩衝區相關的所有緩衝區首部都被收集在一個單向迴圈連結串列中。page的private欄位指向野種第一個塊的buffer_head,每個buffer_head存放在b_this_page欄位中,該欄位是指向連結串列中的下一個緩衝區首部的指標。此外,每個buffer_head還把page的地址存放在b_page欄位中,如上圖所示。