nginx源码分析—数组结构ngx_array_t
2013-04-23 23:25
633 查看
数组实现文件:文件:./src/core/ngx_array.h/.c
但实际的添加操作并不在这两个函数中完成,例如ngx_array_push返回可以在该数组数据区中添加这个元素的位置,ngx_array_push_n则返回可以在该数组数据区中添加n个元素的起始位置,而添加操作即在获得添加位置之后进行
1.数组结构
struct ngx_array_s { void *elts; //数组数据区起始位置 ngx_uint_t nelts; //实际存放的元素个数 size_t size; //每个元素的大小 ngx_uint_t nalloc; //数组分配的空间个数,即实际饭分配的小空间个数 ngx_pool_t *pool; //该数组在内存中的分配 };
2.数组的基本操作(5个)
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); //数组的初始化操作 static ngx_inline ngx_int_t ngx_array_init(ngx_array_t *array, ngx_pool_t *pool, ngx_uint_t n, size_t size)
2.1创建数组
创建数组的操作实现过程,首先分配数组头(20B),然后分配数组数据区,两次分配均在传入的内存池(pool指向的内存池)中进行。然后简单初始化数组头并返回数组头的起始位置。(分配分两个阶段完成,注意和释放过程对应)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; } a->elts = ngx_palloc(p, n * size); //分配大小为*size的内存作为数组数据区 if (a->elts == NULL) { return NULL; } a->nelts = 0; //初始化 a->size = size; a->nalloc = n; a->pool = p; return a; //返回内存起始位置 }
2.2数组销毁
销毁数组的操作实现过程,包括销毁数组数据区和数组头。这里的销毁动作实际上就是修改内存池的last指针,并没有调用free等释放内存的操作,显然,这种维护效率是很高的。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; //释放数组的数据区,只是修改内存池的last指针 } if ((u_char *) a + sizeof(ngx_array_t) == p->d.last) { p->d.last = (u_char *) a; //释放数组头, 再次修改内存池的last指针 } }
2.3添加元素到数组
向数组添加元素的操作有两个,ngx_array_push和ngx_array_push_n,分别添加一个和多个元素。但实际的添加操作并不在这两个函数中完成,例如ngx_array_push返回可以在该数组数据区中添加这个元素的位置,ngx_array_push_n则返回可以在该数组数据区中添加n个元素的起始位置,而添加操作即在获得添加位置之后进行
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 //条件:内存池的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; //last指针后移一位 a->nalloc++; //数组元素总数+1 } else { /* allocate a new array */ new = ngx_palloc(p, 2 * size); //重新分配2倍空间 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++; //总数+1 return elt; }
void * ngx_array_push_n(ngx_array_t *a, ngx_uint_t n) { void *elt, *new; size_t size; ngx_uint_t nalloc; ngx_pool_t *p; size = n * a->size; if (a->nelts + n > a->nalloc) { /* the array is full */ p = a->pool; if ((u_char *) a->elts + a->size * a->nalloc == p->d.last && p->d.last + size <= p->d.end) { /* * the array allocation is the last in the pool * and there is space for new allocation */ p->d.last += size; a->nalloc += n; } else { /* allocate a new array */ nalloc = 2 * ((n >= a->nalloc) ? n : a->nalloc); new = ngx_palloc(p, nalloc * a->size); if (new == NULL) { return NULL; } ngx_memcpy(new, a->elts, a->nelts * a->size); a->elts = new; a->nalloc = nalloc; } } elt = (u_char *) a->elts + a->size * a->nelts; a->nelts += n; return elt; }测试demo
#include <stdio.h> #include "ngx_config.h" #include "ngx_conf_file.h" #include "nginx.h" #include "ngx_core.h" #include "ngx_string.h" #include "ngx_palloc.h" #include "ngx_array.h" volatile ngx_cycle_t* ngx_cycle; void ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, const char *fmt, ...) { } void dump_pool(ngx_pool_t* pool) { while(pool) { printf("pool = 0x%x\n", pool); printf(" .d\n"); printf(".last = 0x%x\n", pool->d.last); printf(".end = 0x%x\n", pool->d.end); printf(".next = 0x%x\n", pool->d.next); printf(".failed = %d\n", pool->d.failed); printf(".max = %d\n", pool->max); printf(".current = 0x%x\n", pool->current); printf(".chain = 0x%x\n", pool->chain); printf(".large = 0x%x\n", pool->large); printf(".cleanup = 0x%x\n", pool->cleanup); printf(".log = 0x%x\n", pool->log); printf("available pool memory = 0x%x\n\n", pool->d.end - pool->d.last); pool = pool->d.next; } } void dump_array(ngx_array_t *a) { if(a) { printf("array = 0x%x\n", a); printf(" .elts = 0x%x\n", a->elts); printf(" .nelts = %d\n", a->nelts); printf(" .size = %d\n", a->size); printf(" .nalloc = %d\n", a->nalloc); printf(" .pool = 0x%x\n", a->pool); printf("elements: "); int* ptr = (int*)(a->elts); for(; ptr < (int*)(a->elts + a->nalloc*a->size);) { printf("0x%x ", *ptr++); } printf("\n"); } } int main() { ngx_pool_t *pool; int i; printf("*************************************************\n"); printf("create a new pool:\n"); printf("*************************************************\n"); pool = ngx_create_pool(1024, NULL); dump_pool(pool); printf("-------------------------------------------------\n"); printf("alloc an array from the pool:\n"); printf("-------------------------------------------------\n"); ngx_array_t *a = ngx_array_create(pool, 10, sizeof(int)); dump_pool(pool); for(i = 0; i < 1000; i++) { int *ptr = ngx_array_push(a); *ptr = i + 1; } dump_array(a); size_t iLen = sizeof(ngx_array_t); printf("sizeof(ngx_array_t) == == 0x%x\n", iLen); ngx_array_destroy(a); ngx_destroy_pool(pool); return 0; }测试结果
************************************************* create a new pool: ************************************************* pool = 0x9b6b020 .d .last = 0x9b6b048 .end = 0x9b6b420 .next = 0x0 .failed = 0 .max = 984 .current = 0x9b6b020 .chain = 0x0 .large = 0x0 .cleanup = 0x0 .log = 0x0 available pool memory = 0x3d8 ------------------------------------------------- alloc an array from the pool: ------------------------------------------------- pool = 0x9b6b020 .d .last = 0x9b6b084 .end = 0x9b6b420 .next = 0x0 .failed = 0 .max = 984 .current = 0x9b6b020 .chain = 0x0 .large = 0x0 .cleanup = 0x0 .log = 0x0 available pool memory = 0x39c array = 0x9b6b048 .elts = 0x9b6b05c .nelts = 10 .size = 4 .nalloc = 10 .pool = 0x9b6b020 elements: 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa sizeof(ngx_array_t) == == 0x14 sizeof(ngx_pool_t) === == 0x28 sizeof(ngx_pool_data_t) === === 0x10
相关文章推荐
- nginx源码分析—数组结构ngx_array_t
- Nginx源码分析—数组结构ngx_array_t
- Nginx源码分析 - 基础数据结构篇 - 数组结构 ngx_array.c
- nginx源码分析—数组结构ngx_array_t
- nginx源码分析—数组结构ngx_array_t
- Nginx源码分析---数组结构ngx_array_t
- nginx源码分析—数组结构ngx_array_t
- nginx源码分析—队列结构ngx_queue_t
- nginx源码分析之ngx_array_t
- Nginx源码分析---hash结构ngx_hash_t(v1.0.4)
- nginx源码分析—内存池结构ngx_pool_t及内存管理(精辟)
- Nginx源码分析 - 基础数据结构篇 - 链表结构 ngx_queue.c
- Nginx源码分析之ngx_array_t
- nginx数组代码分析[ngx_array.c]
- Nginx源码分析 - 基础数据结构篇 - hash表结构 ngx_hash.c
- nginx源码分析—内存池结构ngx_pool_t及内存管理
- nginx源码那些事之array结构分析
- nginx源码分析—内存池结构ngx_pool_t及内存管理
- ngnix源码分析----ngx_array_s 内存数组
- 文章2:Nginx源码分析-ngx_array_t动态数组