概述
为什么80%的码农都做不了架构师?>>>
Nginx有很多封装好的内部结构,实现诸如数组、链表、队列、哈希表等这样的容器。和STL一样,它们定义了自己的逻辑、功能及API。
ngx_array_t数组
ngx_array_t
是nginx内部封装的使用ngx_pool_t
对内存池进行分配的数组容器,其中的数据是在一整片内存区中连续存放的。更新数组时只能在尾部压入1个或多个元素,定义在nginx/src/core/ngx_array.h
中。
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数组
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
指向的内存池分配内存。
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数组
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增加元素
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;
}
数组使用方法如下:
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 addedn", n);
}
}
ngx_array_push(arr)
在数组arr上新追加一个元素,并返回指向新元素的指针(ele
)。需要把返回的指针使用类型转换,转换为具体的类型,然后再给新元素赋值*ele = n
。
##参考
https://code.google.com/p/nginxsrp/wiki/NginxCodeReview
转载于:https://my.oschina.net/lvyi/blog/422626
最后
以上就是天真天空为你收集整理的Nginx源码分析(2)的全部内容,希望文章能够帮你解决Nginx源码分析(2)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复