您的位置:首页 > 运维架构 > Nginx

nginx数组代码分析[ngx_array.c]

2014-01-23 14:19 417 查看

代码路径

\nginx-1.4.4\src\core\ngx_array.c

数据结构

typedef struct {
void        *elts;    //array首地址
ngx_uint_t   nelts;   //已分配块数
size_t       size;	  //每块大小
ngx_uint_t   nalloc;  //总块数
ngx_pool_t  *pool;	  //内存池
} ngx_array_t;

主要接口

ngx_array_t *ngx_array_create(ngx_pool_t *p, ngx_uint_t n, size_t size);
void ngx_array_destroy(ngx_array_t *a);
void *ngx_array_push(ngx_array_t *a);
void *ngx_array_push_n(ngx_array_t *a, ngx_uint_t n);

函数分析

创建array
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)从p里面申请一块大小为sizeof(ngx_array_t)的内存
2)初始化这块内存,实际初始化过程如下:
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;
}
3)创建完数组array后,ngx_array_t结构体各成员得到了初始化,其中elts指向实际数组的起始地址。

使用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 */

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
*/

p->d.last += a->size;
a->nalloc++;

} else {
/* allocate a new array */

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;
}
1)如果现在已经分到的块数nelts还没到最大块数nalloc时,直接分出一个数组单元。
2)如果数组已经满了,内存池还有点的话,就从内存池里分一块。
3)如果数组已经满了,内存池也不够的话,就再开一个2倍size的数组,把之前的arry拷贝到new开辟的2倍size的数组中。

销毁array
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;
}
}
1)回退p->d.last指针a->size * a->nmalloc大小

2)回退p->d.last指针sizeof(ngx_array_t)大小
3)回退之后就和没有开辟array一样
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  nginx array 数组