struct ngx_chain_s {ngx_buf_t *buf;ngx_chain_t *next;
};
buf: 缓冲区指针
next 下一个链表节点
注意:
必须有一种结构来管理缓冲区(最好是链表),不然无法回收
内存池上的chain字段 ,被清空的ngx_chain_t结构都会放在pool->chain缓冲链上
ngx_chain_t *ngx_alloc_chain_link(ngx_pool_t *pool)
{{ngx_chain_t *cl;cl = pool->chain;if (cl) {pool->chain = cl->next;return cl;}cl = ngx_palloc(pool, sizeof(ngx_chain_t));if (cl == NULL) {return NULL;}return c
} ngx_free_chain()用来从内存池里获取释放ngx_chain_t对象,声明是:
#define ngx_free_chain(pool, cl) \cl->next = pool->chain; \pool->chain = cl
typedef struct {
ngx_int_t num;size_t size;
} ngx_bufs_t 1.节点数量
2.缓冲区的大小
// 创建多个buf
/*typedef struct {ngx_int_t num;size_t size;} ngx_bufs_t;
*/
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;// @param2 分配大小 = num * sizep = ngx_palloc(pool, bufs->num * bufs->size);if (p == NULL) {return NULL;}ll = &chain;for (i = 0; i < bufs->num; i++) {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;b->start = p;p += bufs->size;b->end = p;cl = ngx_alloc_chain_link(pool); // 创建链表结构if (cl == NULL) {return NULL;}cl->buf = b;// 尾插法// ll记录前一次循环的&cl->next// 下一次循环 *ll = cl 将 &cl->next 上的值改为 cl// 这样就将上一次循环的next指向当前循环的cl*ll = cl;ll = &cl->next; }*ll = NULL;return chain;
} 编程技巧:尾插法(实现 cl=cl->next)
这里重点说下代码后部分的尾插法。
ll是二级指针
ll记录前一次循环的&cl->next (记录了这次循环的cl的next的地址)
下一次循环 *ll = cl 将 &cl->next 上的值改为 cl (改变了上一次循环的cl的next的地址上的值,也就是改变了上一次循环cl的next的值,就是改变了上一次循环的next,让其指向当前的cl)
这样就将上一次循环的next指向当前循环的cl
ngx_int_t ngx_chain_add_copy(ngx_pool_t *pool, ngx_chain_t **chain,
ngx_chain_t *in);
chain->in
ngx_int_t
ngx_chain_add_copy(ngx_pool_t *pool, ngx_chain_t **chain, ngx_chain_t *in)
{ngx_chain_t *cl, **ll;ll = chain;for (cl = *chain; cl; cl = cl->next) {ll = &cl->next; // 拿到*chain链表最后一个节点的地址}while (in) {cl = ngx_alloc_chain_link(pool);if (cl == NULL) {*ll = NULL;return NGX_ERROR;}cl->buf = in->buf;*ll = cl;ll = &cl->next;in = in->next;}*ll = NULL;return NGX_OK;
』
获取一个空闲buf
获取一个空闲buf
ngx_chain_t *
ngx_chain_get_free_buf(ngx_pool_t *p, ngx_chain_t **free)
{ngx_chain_t *cl;if (*free) {cl = *free;*free = cl->next;cl->next = NULL;return cl;}cl = ngx_alloc_chain_link(p);if (cl == NULL) {return NULL;}cl->buf = ngx_calloc_buf(p);if (cl->buf == NULL) {return NULL;}cl->next = NULL;return cl; 释放掉的cl归还到 pool->chain 上
/*
#define ngx_free_chain(pool, cl) \cl->next = pool->chain; \pool->chain = cl
*/// 释放缓冲区链表
void
ngx_chain_update_chains(ngx_pool_t *p, ngx_chain_t **free, ngx_chain_t **busy,ngx_chain_t **out, ngx_buf_tag_t tag) // free 空闲的 busy 忙碌的 out 待处理的
{ngx_chain_t *cl;// 判断out应该放到什么位置// 如果busy == NULL 则*busy = *out// 否则将*out放到*busy的末尾if (*out) {if (*busy == NULL) {*busy = *out;} else {for (cl = *busy; cl->next; cl = cl->next) { /* void */ }cl->next = *out;}*out = NULL;}// 检查busy// 如果busy中的buf还存在需要处理的内存空间,则停止处理// 否则将buf置空(处理pos last)while (*busy) {cl = *busy;if (ngx_buf_size(cl->buf) != 0) {break;}if (cl->buf->tag != tag) {*busy = cl->next;ngx_free_chain(p, cl);continue;}cl->buf->pos = cl->buf->start;cl->buf->last = cl->buf->start;*busy = cl->next;cl->next = *free;*free = cl;}
}