1、iobuf用来收发数据时候使用的缓冲区,由iobuf_pool来管理使用。
在iobuf.h中定义了如下几个机构体:
struct iobuf           是用来存储数据的内存块;
struct iobuf_arena  是一个大内存块,切分成N个,每个小块给iobuf的ptr指针使用;
iobuf_init_config     用来表示每个类型iobuf大小和数目
struct iobuf_init_config {
        size_t   pagesize;
        int32_t  num_pages;
};
在iobuf.c开头定义了一个数组,此数组作为全局变量,定义了有8种大小的iobuf。
每一个记录表示某类型iobuf的页面大小以及在anena中的数量,
也就是说某个类型iobuf_arena的pagesize 和 page_count和此表中某一个行对应。
struct iobuf_init_config gf_iobuf_init_config[] = {
        /* { pagesize, num_pages }, */
        {128, 1024},
        {512, 512},
        {2 * 1024, 512},
        {8 * 1024, 128},
        {32 * 1024, 64},
        {128 * 1024, 32},
        {256 * 1024, 8},
        {1 * 1024 * 1024, 2},
};
 此全局变量,没有硬编码个数的值,但是可以通过计算得到是8个。
在iobuf.c中,iobuf_pool_new 函数用来初始化整个缓冲池:
struct iobuf_pool *iobuf_pool_new (void)
初始化iobuf_pool池过程中中,将根据这个表,分配8个iobuf_arena,并建立为一个链表。如下图:

而参照全局变量,调用iobuf_pool_add_arena(), 经内部调用__iobuf_arena_init_iobufs (struct iobuf_arena *iobuf_arena)
函数用来初始化8个不同的  arena:
其中每个arena 分配方法如下:
1)__iobuf_arena_alloc() 函数将 为arena分配一大块内存:
// 大小和个数对应全局变量里面的一条记录
iobuf_arena->arena_size = rounded_size * num_iobufs;     
                        
// 使用内存映射获取大块内存
iobuf_arena->mem_base = mmap (NULL, iobuf_arena->arena_size,
                                      PROT_READ|PROT_WRITE,
                                      MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2)__iobuf_arena_alloc() 函数内部调用 __iobuf_arena_init_iobufs()
对iobufs进行初始化:
为iobuf_arena->iobufs  分配了大小为page_count * sizeof(struct iobuf)的一块内存,用来切块存储   iobuf  头结构。
分配的内存块切分。
   
再将iobuf_arena->mem_base指向的大内存块切成小块,大小为iobuf_arena->page_size,
个数为iobuf_arena->page_count。
8个类型的arena 分配完成后,逻辑结构如下图:

3)在iobuf_pool中添加一个更大的arena 来满足上层需求:
iobuf_create_stdalloc_arena (iobuf_pool);
该函数并没有为arena分配缓冲区用的大块内存空间。如果在用的时候找不到合适大小的iobuf,则动态建立一个。
2、iobuf_pool的使用,主要是两个函数:
struct iobuf * iobuf_get2 (struct iobuf_pool *iobuf_pool, size_t page_size);
void iobuf_put (struct iobuf *iobuf)
而在具体应用中还用到一个结构体:
struct iobref {
        gf_lock_t          lock;
        gf_atomic_t        ref;
        struct iobuf     **iobrefs;  // iobuf指针数组
	int                alloced;  // 数组个数
	int                used;     // 使用了几个单元
};
这个结构用来把几个具体逻辑操作中用的多个缓冲区放在一起统一管理。
结构体的初始化操作为:struct iobref * iobref_new ()。
iobref->iobrefs = GF_CALLOC (sizeof (*iobref->iobrefs), 16, gf_common_mt_iobrefs);
这个函数 iobrefs 数组初始值为16个,用来存放iobuf指针,后期如果不够用,再增加。
原文:https://www.cnblogs.com/robinfox/p/8934194.html