ngx_array是Nginx中一个基础数据结构,是对c语言中基础数据结构数组——数据的扩展,在接口上增加了一些其他特性。
typedef struct {
void *elts; //数据链表,空间待分配
ngx_uint_t nelts; //数组中元素个数
size_t size; //每个元素的大小
ngx_uint_t nalloc; //分配的空间大小
ngx_pool_t *pool; //本数组空间的来源pool,不够了可以继续从pool中申请。
} ngx_array_t;
这面这个结构体定义就是ngx_array_t的结构体,从其成员变量来看这个数组具有更多的灵活性了,至少空间是可以动态的增加了。下面解析下各个函数。
ngx_array_t *
ngx_array_create(ngx_pool_t *p, ngx_uint_t n, size_t size)
{
ngx_array_t *a;
//先申请结构体本省所需要的空间
a = ngx_palloc(p, sizeof(ngx_array_t));
if (a == NULL) {
return NULL;
}
//申请数组存放数据所需要的空间,并对数组结构体进行初始化
if (ngx_array_init(a, p, n, size) != NGX_OK) {
return NULL;
}
return a;
}
这是数组创建函数,这个函数负责两个事:
1,为结构体本身申请空间,并初始化。
2,为数据申请空间。
然后在看看这个ngx_array_init这个函数的实现
static ngx_inline ngx_int_t
ngx_array_init(ngx_array_t *array, ngx_pool_t *pool, ngx_uint_t n, size_t size)
{
/*
* set "array->nelts" before "array->elts", otherwise MSVC thinks
* that "array->nelts" may be used without having been initialized
*/
array->nelts = 0;
array->size = size;
array->nalloc = n;
array->pool = pool;
//申请数据空间
array->elts = ngx_palloc(pool, n * size);
if (array->elts == NULL) {
return NGX_ERROR;
}
return NGX_OK;
}
这个函数主要是初始化数组结构体本身的各个字段,并为数据申请内存空间。
void
ngx_array_destroy(ngx_array_t *a)
{
ngx_pool_t *p;
p = a->pool;
//先释放数据占用的空间给内存池
if ((u_char *) a->elts + a->size * a->nalloc == p->d.last) {
p->d.last -= a->size * a->nalloc;
}
//在释放数组结构体本身所占用的空间
if ((u_char *) a + sizeof(ngx_array_t) == p->d.last) {
p->d.last = (u_char *) a;
}
}
这个函数主要是为了销毁array并释放空间。
void *
ngx_array_push(ngx_array_t *a)
{
void *elt, *new;
size_t size;
ngx_pool_t *p;
if (a->nelts == a->nalloc) {
/* the array is full */
//当前数组a中数据所占用的空间总大小
size = a->size * a->nalloc;
p = a->pool;
if ((u_char *) a->elts + size == p->d.last
&& p->d.last + a->size <= p->d.end)
{
/*
* the array allocation is the last in the pool
* and there is space for new allocation
*/
//这里的意思就是说,当前数组所在pool中的位置刚刚好是出于尾巴上
//而且空间还够,所以可以继续往后扩展
p->d.last += a->size;
a->nalloc++;
} else {
/* allocate a new array */
//数组数据空间在pool中的位置不是最后,再往后扩展就会覆盖其他数据
//或者说空间不够了,那么久需要诚信申请空间,直接在pool中再开辟一个2倍原数组大小的空间
//这个地方需要注意,频繁的这么做可能会产生太多碎片。
new = ngx_palloc(p, 2 * size);
if (new == NULL) {
return NULL;
}
ngx_memcpy(new, a->elts, size);
a->elts = new;
a->nalloc *= 2;
}
}
elt = (u_char *) a->elts + a->size * a->nelts;
a->nelts++;
return elt;
}
这个函数的功能是在已存在的一个数组中添加一个元素,这个函数只负责空间的准备,具体数据的初始化需要在这个函数外面提供。函数 ngx_array_push_n这个函数和上面这个函数处理逻辑基本一致,只是这里需要push的是n个元素。