《Ceph源码分析》——第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:

char *data;      //数据指针
unsigned len;    //数据长度
atomic_t nref;   //引用计数`

mutable RWLock crc_lock;   //读写锁,保护crc_map
map<pair<size_t, size_t>, pair<uint32_t, uint32_t> > crc_map;
//crc校验信息,第一个pair为数据段的起始和结束(from,to),第二个pair是crc32校验码,pair的第一字段为base crc32校验码,第二个字段为加上数据段后计算出的crc32校验码。

……
}
下列类都继承了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)

return;

_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();

it != _buffers.end();
++it)
  if (!it->is_aligned(align))
return false;
return true;

}`
添加一个字符到list中,先查看append_buffer是否有足够的空间,如果没有,就新申请一个4KB大小的空间:
``void buffer::list::append(char c)
{
// 检查当前的append_buffer是否有足够的空间
unsigned gap = append_buffer.unused_tail_length();
if (!gap) {

// 如果没有空间,就申请一个append_buffer!

append_buffer = create_aligned(CEPH_BUFFER_APPEND_SIZE,

                             CEPH_BUFFER_APPEND_SIZE);
append_buffer.set_length(0);   //到目前为止,没有用到

}`

append(append_buffer, append_buffer.append(c) - 1, 1);
// 把该数据段添加到append_buffer中

}``
内存对齐:有些情况下,需要内存地址对齐,例如当以directIO方式写入数据至磁盘时,需要内存地址按内存页面大小(page)对齐,也即buffer::list的内存地址都需按page对齐。函数rebuild用来完成对齐的功能。其实现的方法也比较简单,检查没有对齐的ptr,申请一块新对齐的内存,把数据拷贝过去,释放内存空间就可以了。
buffer::list还集成了其他额外的一些功能:
把数据写入文件或从文件读取数据的功能。
计算数据的crc32校验。

时间: 2024-08-02 12:25:07

《Ceph源码分析》——第2章,第2节Buffer的相关文章

《Ceph源码分析》——导读

目 录序言第1章 Ceph整体架构1.1 Ceph的发展历程1.2 Ceph的设计目标1.3 Ceph基本架构图1.4 Ceph客户端接口 1.4.1 RBD 1.4.2 CephFS1.4.3 RadosGW 1.5 RADOS 1.5.1 Monitor 1.5.2 对象存储1.5.3 pool和PG的概念1.5.4 对象寻址过程1.5.5 数据读写过程1.5.6 数据均衡1.5.7 Peering 1.5.8 Recovery和Backfill 1.5.9 纠删码1.5.10 快照和克隆1

《Ceph源码分析》——第3章,第1节Ceph网络通信框架

第3章Ceph网络通信本章介绍Ceph网络通信模块,这是客户端和服务器通信的底层模块,用来在客户端和服务器之间接收和发送请求.其实现功能比较清晰,是一个相对较独立的模块,理解起来比较容易,所以首先介绍它. 3.1 Ceph网络通信框架一个分布式存储系统需要一个稳定的底层网络通信模块,用于各节点之间的互联互通.对于一个网络通信系统,要求如下:高性能.性能评价的两个指标:带宽和延迟.稳定可靠.数据不丢包,在网络中断时,实现重连等异常处理.网络通信模块的实现在源代码src/msg的目录下,其首先定义了

《Ceph源码分析》——第1章,第5节RADOS

1.5 RADOS RADOS是Ceph存储系统的基石,是一个可扩展的.稳定的.自我管理的.自我修复的对象存储系统,是Ceph存储系统的核心.它完成了一个存储系统的核心功能,包括:Monitor模块为整个存储集群提供全局的配置和系统信息:通过CRUSH算法实现对象的寻址过程:完成对象的读写以及其他数据功能:提供了数据均衡功能:通过Peering过程完成一个PG内存达成数据一致性的过程:提供数据自动恢复的功能:提供克隆和快照功能:实现了对象分层存储的功能:实现了数据一致性检查工具Scrub.下面分

《Ceph源码分析》——第2章,第7节本章小结

2.7 本章小结 本章介绍了src/common目录下的一些公共库中比较常见的类的实现.BufferList在数据读写.序列化中使用比较多,它的各种不同成员函数的使用方法需要读者自己进一步了解.对于ShardedThreadPool,本章只介绍了实现的原理,具体实现在不同的场景会有不同,需要读者面对具体的代码自己去分析.

《Ceph源码分析》——第1章,第2节Ceph的设计目标

1.2 Ceph的设计目标Ceph的设计目标是采用商用硬件(Commodity Hardware)来构建大规模的.具有高可用性.高可扩展性.高性能的分布式存储系统.商用硬件一般指标准的x86服务器,相对于专用硬件,性能和可靠性较差,但由于价格相对低廉,可以通过集群优势来发挥高性能,通过软件的设计解决高可用性和可扩展性.标准化的硬件可以极大地方便管理,且集群的灵活性可以应对多种应用场景.系统的高可用性指的是系统某个部件失效后,系统依然可以提供正常服务的能力.一般用设备部件和数据的冗余来提高可用性.

《Ceph源码分析》——第3章,第2节Simple实现

3.2 Simple实现Simple在Ceph里实现比较早,目前也比较稳定,是在生产环境中使用的网络通信模块.如其名字所示,实现相对比较简单.下面具体分析一下,Simple如何实现Ceph网络通信框架的各个模块. 3.2.1 SimpleMessager类SimpleMessager实现了Messager接口.class SimpleMessenger : public SimplePolicyMessenger { Accepter accepter; //用于接受客户端的链接请求 Dispa

《Ceph源码分析》——第3章,第3节本章小结

3.3 本章小结本章介绍了Ceph的网络通信模块的框架,及目前生产环境中使用的Simple实现.它对每个链接都会有一个发送线程和接收线程用来处理发送和接收.实现的难点还在于网络链接出现错误时的各种错误处理.

《Ceph源码分析》——第2章,第1节Object

第2章Ceph通用模块本章介绍Ceph源代码通用库中的一些比较关键而又比较复杂的数据结构.Object和Buffer相关的数据结构是普遍使用的.线程池ThreadPool可以提高消息处理的并发能力.Finisher提供了异步操作时来执行回调函数.Throttle在系统的各个模块各个环节都可以看到,它用来限制系统的请求,避免瞬时大量突发请求对系统的冲击.SafteTimer提供了定时器,为超时和定时任务等提供了相应的机制.理解这些数据结构,能够更好理解后面章节的相关内容. 2.1 Object对象

《Ceph源码分析》——第1章,第一节Ceph的发展历程

第1章Ceph整体架构本章从比较高的层次对Ceph的发展历史.Ceph的设计目标.整体架构进行简要介绍.其次介绍Ceph的三种对外接口:块存储.对象存储.文件存储.还介绍Ceph的存储基石RADOS系统的一些基本概念.各个模块组成和功能.最后介绍了对象的寻址过程和数据读写的原理,以及RADOS实现的数据服务等. 1.1 Ceph的发展历程Ceph项目起源于其创始人Sage Weil在加州大学Santa Cruz分校攻读博士期间的研究课题.项目的起始时间为2004年,在2006年基于开源协议开源了