天天看點

《Ceph源碼分析》——第2章,第2節Buffer

本節書摘來自華章出版社《ceph源碼分析》一書中的第2章,第2.2節buffer,作者常濤,更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視

2.2 buffer

buffer就是一個命名空間,在這個命名空間下定義了buffer相關的資料結構, 這些資料結構在ceph的源代碼中廣泛使用。下面介紹的buffer::raw類是基礎類,其子類完成了buffer資料空間的配置設定,buffer::ptr類實作了buffer内部的一段資料,buffer::list封裝了多個資料段。

2.2.1 buffer::raw

類buffer::raw是一個原始的資料buffer,在其基礎之上添加了長度、引用計數和額外的crc校驗資訊,結構如下:

`class buffer::raw {

public:

……

}

下列類都繼承了buffer::raw,實作了data對應記憶體空間的申請:

類raw_malloc實作了用malloc函數配置設定記憶體空間的功能。

類class buffer::raw_mmap_pages實作了通過mmap來把記憶體匿名映射到程序的位址空間。

類class buffer::raw_posix_aligned調用了函數posix_memalign來申請記憶體位址對齊的記憶體空間。

類class buffer::raw_hack_aligned是在系統不支援記憶體對齊申請的情況下自己實作了記憶體位址的對齊。

類class buffer::raw_pipe實作了pipe做為buffer的記憶體空間。

類class buffer::raw_char使用了c++的new操作符來申請記憶體空間。

2.2.2 buffer::ptr

類buffer::ptr就是對于buffer::raw的一個部分資料段。結構如下:

`class ceph_buffer_api ptr {

raw *_raw;

unsigned _off, _len;

}`

ptr是raw裡的一個任意的資料段,_off是在_raw裡的偏移量,_len是ptr的長度。raw和ptr的示意圖如圖2-1所示。

圖2-1 raw和ptr示意圖

《Ceph源碼分析》——第2章,第2節Buffer

2.2.3 buffer::list

類buffer::list是一個使用廣泛的類,它是多個buffer::ptr的清單,也就是多個記憶體資料段的清單。結構如下:

`class ceph_buffer_api list {

std::list _buffers; //所有的ptr

unsigned _len; //所有的ptr的資料總長度

unsigned _memcopy_count; //當調用函數rebuild用來記憶體對齊時,需要記憶體拷貝的資料量

ptr append_buffer; //當有小的資料就添加到這個buffer裡

mutable iterator last_p; //通路list的疊代器

buffer::list的重要的操作如下所示。

添加一個ptr到list的頭部:

`void push_front(ptr& bp) {

if (bp.length() == 0)

_buffers.push_front(bp);

_len += bp.length();

添加一個raw到list頭部中,先構造一個ptr,後添加list中:

`void push_front(raw *r) {

ptr bp(r);

push_front(bp);

判斷記憶體是否以參數align對齊,每一個ptr都必須以align對齊:

`bool buffer::list::is_aligned(unsigned align) const

{

for (std::list::const_iterator it = _buffers.begin();

添加一個字元到list中,先檢視append_buffer是否有足夠的空間,如果沒有,就新申請一個4kb大小的空間:

``void buffer::list::append(char c)

// 檢查目前的append_buffer是否有足夠的空間

unsigned gap = append_buffer.unused_tail_length();

if (!gap) {

append_buffer = create_aligned(ceph_buffer_append_size,

}``

記憶體對齊:有些情況下,需要記憶體位址對齊,例如當以directio方式寫入資料至磁盤時,需要記憶體位址按記憶體頁面大小(page)對齊,也即buffer::list的記憶體位址都需按page對齊。函數rebuild用來完成對齊的功能。其實作的方法也比較簡單,檢查沒有對齊的ptr,申請一塊新對齊的記憶體,把資料拷貝過去,釋放記憶體空間就可以了。

buffer::list還內建了其他額外的一些功能:

把資料寫入檔案或從檔案讀取資料的功能。

計算資料的crc32校驗。