前言
可以说对于任何网络库(模块)而言,一个缓冲模块都是必不可少的。缓冲模块主要用于缓冲从网络接收到的数据,以及
用户提交的数据(用于发送)。很多时候,我们还需要将网络模块层(非TCP层)的这些缓冲数据拷贝到用户层,而这些内存拷贝
都会消耗时间。
在这里,我简要分析下libevent的相关代码(event.h和buffer.c)。
结构
关于libevent的缓冲模块,主要就是围绕evbuffer结构体展开。先看下evbuffer的定义:
struct evbuffer{
// 当前有效缓冲区的内存起始地址
u_char *buffer;
// 整个分配(realloc)用来缓冲的内存起始地址
u_char *orig_buffer;
// origin_buffer和buffer之间的字节数
size_t misalign;
// 整个分配用来缓冲的内存字节数
size_t totallen;
// 当前有效缓冲区的长度(字节数)
size_t off;
//回到函数,当缓冲区有变化的时候会被调用
void (*cb)(struct evbuffer *, size_t, size_t, void *);
//回调函数的参数
void *cbarg;
};
libevent的缓冲是一个连续的内存区域,其处理数据的方式(写数据和读数据)更像一个队列操作方式:从后写入,从前
读出。evbuffer分别设置相关指针(一个指标)用于指示读出位置和写入位置。其大致结构如图:
区域的大小,misalign表示buffer相对于orig_buffer的偏移,off表示有效数据的长度。
实际运作
这里我将结合具体的代码分析libevent是如何操作上面那个队列式的evbuffer的,先看一些辅助函数:
而该函数正是做这件事的。说白了,该函数就是用于调整缓冲队列的前向指标。