Nginx有很多封装好的内部结构,实现诸如数组、链表、队列、哈希表等这样的容器。和STL一样,它们定义了自己的逻辑、功能及API。
ngx_array_t数组
ngx_array_t
是nginx内部封装的使用ngx_pool_t
对内存池进行分配的数组容器,其中的数据是在一整片内存区中连续存放的。更新数组时只能在尾部压入1个或多个元素,定义在nginx/src/core/ngx_array.h
中。
1 2 3 4 5 6 7 8 |
typedef struct { void *elts; ngx_uint_t nelts; size_t size; ngx_uint_t nalloc; ngx_pool_t *pool; } ngx_array_t; |
其中elts
指向数组元素所在的内存地址,nelts
为实际元素个数,size
是单个元素大小,nalloc
为数组容量。
pool
指向要使用的实例化的内存池。
- 创建ngx_array_t数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
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; } |
a
是一个nginx数组指针,使用p
指向的内存池分配内存。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
static ngx_int_t ngx_array_init(ngx_array_t *array, ngx_pool_t *pool, ngx_uint_t n, size_t size) { 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; } |
传进去实例化的内存池p、数组大小n和单个元素大小size。使用ngx_array_init
来初始化数组,其中array->elts
指向使用内存池p分配n * size
大小的内存。
图示如下:
- 删除ngx_array_t数组
1 2 3 4 5 6 7 8 9 10 11 12 13 |
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; } |
数组删除分为两步,第一个if
中将标示数组空内存起始地址的last
更新到上图的data(m)
结尾;第二个if
中将last
更新到上图的ngx_pool_t
结尾。
- ngx_array_push增加元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
void * ngx_array_push(ngx_array_t *a) { void *elt, *new; size_t size; ngx_pool_t *p; if (a->nelts == a->nalloc) { //数组已满 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) { p->d.last += a->size; a->nalloc++; } else { //分配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; } |
数组使用方法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
int main() { int n; int* ele; //创建一个内存池 ngx_pool_t* pool = ngx_create_pool(4000, NULL); //创建一个数组 ngx_array_t* arr = ngx_array_create(pool, 10, sizeof(ngx_uint_t));; for (n=0; n < 5; n++) { ele = (int*) ngx_array_push(arr); *ele = n; printf("new element %d added\n", n); } } |
ngx_array_push(arr)
在数组arr上新追加一个元素,并返回指向新元素的指针(ele
)。需要把返回的指针使用类型转换,转换为具体的类型,然后再给新元素赋值*ele = n
。
0