《Ceph源码分析》——第2章,第2节Buffer
本節(jié)書(shū)摘來(lái)自華章出版社《Ceph源碼分析》一書(shū)中的第2章,第2.2節(jié)Buffer,作者常濤,更多章節(jié)內(nèi)容可以訪(fǎng)問(wèn)云棲社區(qū)“華章計(jì)算機(jī)”公眾號(hào)查看
2.2 Buffer
Buffer就是一個(gè)命名空間,在這個(gè)命名空間下定義了Buffer相關(guān)的數(shù)據(jù)結(jié)構(gòu), 這些數(shù)據(jù)結(jié)構(gòu)在Ceph的源代碼中廣泛使用。下面介紹的buffer::raw類(lèi)是基礎(chǔ)類(lèi),其子類(lèi)完成了Buffer數(shù)據(jù)空間的分配,buffer::ptr類(lèi)實(shí)現(xiàn)了Buffer內(nèi)部的一段數(shù)據(jù),buffer::list封裝了多個(gè)數(shù)據(jù)段。
2.2.1 buffer::raw
類(lèi)buffer::raw是一個(gè)原始的數(shù)據(jù)Buffer,在其基礎(chǔ)之上添加了長(zhǎng)度、引用計(jì)數(shù)和額外的crc校驗(yàn)信息,結(jié)構(gòu)如下:
`class buffer::raw {
public:
……
}
下列類(lèi)都繼承了buffer::raw,實(shí)現(xiàn)了data對(duì)應(yīng)內(nèi)存空間的申請(qǐng):
類(lèi)raw_malloc實(shí)現(xiàn)了用malloc函數(shù)分配內(nèi)存空間的功能。
類(lèi)class buffer::raw_mmap_pages實(shí)現(xiàn)了通過(guò)mmap來(lái)把內(nèi)存匿名映射到進(jìn)程的地址空間。
類(lèi)class buffer::raw_posix_aligned調(diào)用了函數(shù)posix_memalign來(lái)申請(qǐng)內(nèi)存地址對(duì)齊的內(nèi)存空間。
類(lèi)class buffer::raw_hack_aligned是在系統(tǒng)不支持內(nèi)存對(duì)齊申請(qǐng)的情況下自己實(shí)現(xiàn)了內(nèi)存地址的對(duì)齊。
類(lèi)class buffer::raw_pipe實(shí)現(xiàn)了pipe做為Buffer的內(nèi)存空間。
類(lèi)class buffer::raw_char使用了C++的new操作符來(lái)申請(qǐng)內(nèi)存空間。
2.2.2 buffer::ptr
類(lèi)buffer::ptr就是對(duì)于buffer::raw的一個(gè)部分?jǐn)?shù)據(jù)段。結(jié)構(gòu)如下:
`class CEPH_BUFFER_API ptr {
raw *_raw;
unsigned _off, _len;
……
}`
ptr是raw里的一個(gè)任意的數(shù)據(jù)段,_off是在_raw里的偏移量,_len是ptr的長(zhǎng)度。raw和ptr的示意圖如圖2-1所示。
圖2-1 raw和ptr示意圖
2.2.3 buffer::list
類(lèi)buffer::list是一個(gè)使用廣泛的類(lèi),它是多個(gè)buffer::ptr的列表,也就是多個(gè)內(nèi)存數(shù)據(jù)段的列表。結(jié)構(gòu)如下:
`class CEPH_BUFFER_API list {
std::list _buffers; //所有的ptr
unsigned _len; //所有的ptr的數(shù)據(jù)總長(zhǎng)度
unsigned _memcopy_count; //當(dāng)調(diào)用函數(shù)rebuild用來(lái)內(nèi)存對(duì)齊時(shí),需要內(nèi)存拷貝的數(shù)據(jù)量
ptr append_buffer; //當(dāng)有小的數(shù)據(jù)就添加到這個(gè)buffer里
mutable iterator last_p; //訪(fǎng)問(wèn)list的迭代器
……
}`
buffer::list的重要的操作如下所示。
添加一個(gè)ptr到list的頭部:
`void push_front(ptr& bp) {
if (bp.length() == 0)
_buffers.push_front(bp);
_len += bp.length();
}`
添加一個(gè)raw到list頭部中,先構(gòu)造一個(gè)ptr,后添加list中:
`void push_front(raw *r) {
ptr bp(r);
push_front(bp);
}`
判斷內(nèi)存是否以參數(shù)align對(duì)齊,每一個(gè)ptr都必須以align對(duì)齊:
`bool buffer::list::is_aligned(unsigned align) const
{
for (std::list::const_iterator it = _buffers.begin();
}`
添加一個(gè)字符到list中,先查看append_buffer是否有足夠的空間,如果沒(méi)有,就新申請(qǐng)一個(gè)4KB大小的空間:
``void buffer::list::append(char c)
{
// 檢查當(dāng)前的append_buffer是否有足夠的空間
unsigned gap = append_buffer.unused_tail_length();
if (!gap) {
append_buffer = create_aligned(CEPH_BUFFER_APPEND_SIZE,
CEPH_BUFFER_APPEND_SIZE); append_buffer.set_length(0); //到目前為止,沒(méi)有用到}`
append(append_buffer, append_buffer.append(c) - 1, 1); // 把該數(shù)據(jù)段添加到append_buffer中}``
內(nèi)存對(duì)齊:有些情況下,需要內(nèi)存地址對(duì)齊,例如當(dāng)以directIO方式寫(xiě)入數(shù)據(jù)至磁盤(pán)時(shí),需要內(nèi)存地址按內(nèi)存頁(yè)面大小(page)對(duì)齊,也即buffer::list的內(nèi)存地址都需按page對(duì)齊。函數(shù)rebuild用來(lái)完成對(duì)齊的功能。其實(shí)現(xiàn)的方法也比較簡(jiǎn)單,檢查沒(méi)有對(duì)齊的ptr,申請(qǐng)一塊新對(duì)齊的內(nèi)存,把數(shù)據(jù)拷貝過(guò)去,釋放內(nèi)存空間就可以了。
buffer::list還集成了其他額外的一些功能:
把數(shù)據(jù)寫(xiě)入文件或從文件讀取數(shù)據(jù)的功能。
計(jì)算數(shù)據(jù)的crc32校驗(yàn)。
總結(jié)
以上是生活随笔為你收集整理的《Ceph源码分析》——第2章,第2节Buffer的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Java 软件安装流程详解
- 下一篇: protues软件仿真-LCD1602