Nginx中关于缓冲区的相关操作全部在ngx_buf这个源代码文件里, 先来看看buf涉及到的数据结构。
typedef void * ngx_buf_tag_t;
typedef struct ngx_buf_s ngx_buf_t;
struct ngx_buf_s {
u_char *pos;
u_char *last; //buffer当前使用到的位置
off_t file_pos;
off_t file_last;
u_char *start; /* start of buffer */
u_char *end; /* end of buffer */
ngx_buf_tag_t tag;
ngx_file_t *file;
ngx_buf_t *shadow;
/* the buf's content could be changed */
unsigned temporary:1;
/*
* the buf's content is in a memory cache or in a read only memory
* and must not be changed
*/
unsigned memory:1;
/* the buf's content is mmap()ed and must not be changed */
unsigned mmap:1;
unsigned recycled:1;
unsigned in_file:1;
unsigned flush:1;
unsigned sync:1;
unsigned last_buf:1;
unsigned last_in_chain:1;
unsigned last_shadow:1;
unsigned temp_file:1;
/* STUB */ int num;
};
struct ngx_chain_s {
ngx_buf_t *buf;
ngx_chain_t *next;
};
在ngx_buf_t中涉及到多个位域,基本都是用于标志位,这里先不做详细的解释。 先来看看基本基本的函数。
ngx_buf_t *
ngx_create_temp_buf(ngx_pool_t *pool, size_t size)
{
ngx_buf_t *b;
//#define ngx_calloc_buf(pool) ngx_pcalloc(pool, sizeof(ngx_buf_t))
b = ngx_calloc_buf(pool);
if (b == NULL) {
return NULL;
}
//初始化buf的起始指针,为buf申请空降
b->start = ngx_palloc(pool, size);
if (b->start == NULL) {
return NULL;
}
/*
* set by ngx_calloc_buf():
*
* b->file_pos = 0;
* b->file_last = 0;
* b->file = NULL;
* b->shadow = NULL;
* b->tag = 0;
* and flags
*/
b->pos = b->start;
b->last = b->start;
b->end = b->last + size;
b->temporary = 1;
return b;
}
再来看下关于创建buffer链表的接口函数
ngx_chain_t *
ngx_create_chain_of_bufs(ngx_pool_t *pool, ngx_bufs_t *bufs)
{
u_char *p;
ngx_int_t i;
ngx_buf_t *b;
ngx_chain_t *chain, *cl, **ll;
//申请链表所需要的总空间
p = ngx_palloc(pool, bufs->num * bufs->size);
if (p == NULL) {
return NULL;
}
ll = &chain;
//逐个处理各个buf,主要是初始化和建立链表
for (i = 0; i < bufs->num; i++) {
//buf本身需要的空间申请
b = ngx_calloc_buf(pool);
if (b == NULL) {
return NULL;
}
/*
* set by ngx_calloc_buf():
*
* b->file_pos = 0;
* b->file_last = 0;
* b->file = NULL;
* b->shadow = NULL;
* b->tag = 0;
* and flags
*
*/
b->pos = p;
b->last = p;
b->temporary = 1;
//buffer数据区指针初始化
b->start = p;
p += bufs->size;
b->end = p;
//从pool中申请一个ngx_chain_t节点的空间
cl = ngx_alloc_chain_link(pool);
if (cl == NULL) {
return NULL;
}
cl->buf = b;
*ll = cl;
ll = &cl->next;
}
*ll = NULL;
//最后返回链表的头节点。
return chain;
}
上面这个函数里用到了 ngx_alloc_chain_link这函数,这个函数的主要功能是从pool中申请一个ngx_chain_t的结构体空间。
ngx_chain_t *
ngx_alloc_chain_link(ngx_pool_t *pool)
{
ngx_chain_t *cl;
cl = pool->chain;
//当pool中有chain节点的时候,直接拿出来用,就不需要重新申请了。
if (cl) {
pool->chain = cl->next;
return cl;
}
//pool中的chain节点用完了,那么需要从pool中重新申请
cl = ngx_palloc(pool, sizeof(ngx_chain_t));
if (cl == NULL) {
return NULL;
}
return cl;
}
实际上这个函数就是从pool中的chain链表中去拿节点,没有了那么需要从内存池子中去申请。
对应于上一个申请空间的函数,那么还有一个回收空间的函数,不过这里是采用宏定义的方式实现的:
#define ngx_free_chain(pool, cl) \
cl->next = pool->chain; \
pool->chain = cl
这个回收过程很简单,直接将需要回收的节点加入到pool中链表头部就行了。
这个源代码中还有一些其他的数据结构和函数,这里先不分析了,因为还不太清楚或者猜测其用途,等真正遇到了再回头添加。