本节书摘来自华章出版社《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示意图

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校验。