一、Nginx中链表(ngx_list_t)的结构图
ngx_list_t 作为一个链表的结构体,里面是一些链表的信息,ngx_list_part_t 是链表的节点。 ngx中的链表并不是将内存简单串起来,而是将内存组织成块(chunck,在ngx中叫part),然后将这些块通过链表串起来。 每个块划分为nalloc 片区域,每片区域的大小为size ,因此一个chunck的大小为n*nalloc 。 一个chunck中已分配的区域片数为nelts 。
二、源码阅读
1、ngx_list_part_s
struct ngx_list_part_s {
void *elts;
ngx_uint_t nelts;
ngx_list_part_t *next;
};
2、ngx_list_t
链表的结构体,包含一些链表的信息,用于将(chunck)part组织起来
typedef struct {
ngx_list_part_t *last;
ngx_list_part_t part;
size_t size;
ngx_uint_t nalloc;
ngx_pool_t *pool;
} ngx_list_t;
3、ngx_list_create
创建一个链表,首先要从内存池中分配一块数据给list结构体,然后再交给ngx_list_init去初始化具体信息,和分配数据区域空间。
ngx_list_t *
ngx_list_create(ngx_pool_t *pool, ngx_uint_t n, size_t size)
{
ngx_list_t *list;
list = ngx_palloc(pool, sizeof(ngx_list_t));
if (list == NULL) {
return NULL;
}
if (ngx_list_init(list, pool, n, size) != NGX_OK) {
return NULL;
}
return list;
}
4、ngx_list_init
初始化list结构体的信息,并分配一块chunck
static ngx_inline ngx_int_t
ngx_list_init(ngx_list_t *list, ngx_pool_t *pool, ngx_uint_t n, size_t size)
{
list->part.elts = ngx_palloc(pool, n * size);
if (list->part.elts == NULL) {
return NGX_ERROR;
}
list->part.nelts = 0;
list->part.next = NULL;
list->last = &list->part;
list->size = size;
list->nalloc = n;
list->pool = pool;
return NGX_OK;
}
5、ngx_list_push
通过list来获取一块空间的首地址。
取一块数据为什么叫push呢?因为数据是通过list组织起来的,分配的空间通过list来组织,也就是要push到list中的。
void *
ngx_list_push(ngx_list_t *l)
{
void *elt;
ngx_list_part_t *last;
last = l->last;
if (last->nelts == l->nalloc) {
last = ngx_palloc(l->pool, sizeof(ngx_list_part_t));
if (last == NULL) {
return NULL;
}
last->elts = ngx_palloc(l->pool, l->nalloc * l->size);
if (last->elts == NULL) {
return NULL;
}
last->nelts = 0;
last->next = NULL;
l->last->next = last;
l->last = last;
}
elt = (char *) last->elts + l->size * last->nelts;
last->nelts++;
return elt;
}
|