nginx--源码分析 array(实现动态数组)
创始人
2024-02-14 17:41:31
0

1.基本数据结构

typedef struct {void        *elts;ngx_uint_t   nelts;size_t       size;ngx_uint_t   nalloc;ngx_pool_t  *pool;
} ngx_array_t;

结构成员定义

1.void* elts :数组的内存位置, 即数组首地址

采用void* 近似使用模板技术,可以通过类型转化实现各种类型 例如 char*等

2. ngx_uint_t   nelts; 数组当前元素数量

(ngx_uint_t)为无符号指针

3.size_t    size   数组元素大小(已经在数组里面)

4.ngx_uint_t nalloc 数组可使用的最多元素数量

5 ngx_pool_t* pool 数组使用的内存池

图形解释

1.ngx_array_t的nalloc虽然表示了总容量,但并不意味着只能容纳nalloc个元素。如果数组内的元素不断增加,当nelts > nalloc时将会引发数组扩容,ngx_array_t会向内存池pool申请一块两倍原大小的空间-—这个策略是和std : : vector一样的。 2.但ngx_array_t的扩容成本较高,不仅要重新分配内存,而且要拷贝原有元素到新的位置,所以我们在使用ngx_array_t时最好一次性分配足够的空间,尽量避免动态扩容。

2.操作函数

初始化 static ngx_inline ngx_int_t 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;}

1. 解释一下 ngx_inline 

#ifndef ngx_inline
#define ngx_inline      inline
#endif

在c中,为了解决一些频繁调用的小函数大量消耗栈空间或是叫栈内存的问题,特别的引入了inline修饰符,表示为内联函数。

栈空间就是指放置程式的局部数据也就是函数内数据的内存空间,在系统下,栈空间是有限的,假如频繁大量的使用就会造成因栈空间不足所造成的程式出错的问题,函数的死循环递归调用的最终结果就是导致栈内存空间枯竭。

2.分配一个内存池给ngx_array_init

 ngx_array_t * ngx_array_create(ngx_pool_t *p, ngx_uint_t n, size_t size)

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;
}

void ngx_array_destroy(ngx_array_t *a)

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;}
}


建议阅读 Nginx源码分析--内存池_编程界的谢菲尔德的博客-CSDN博客

销毁是通过内存池覆盖的方式

插入 

 void * ngx_array_push(ngx_array_t *a)

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.判断情况 是否over capacity 

2.如果内存池还有空间就开辟内存池空间

3.如果没有就要扩容两倍!!!(并且还要移动数据位置!!!)

4.return是一个elt就是一个空指针(//数据区中实际已经存放数据的子区的末尾)需要类型转换

void *
ngx_array_push_n(ngx_array_t *a, ngx_uint_t n)

 

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;
}

类似与push

3.测试用例

/*** ngx_array_t test, to test ngx_array_create, ngx_array_push*/#include 
#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 = %d\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 < 10; i++){int *ptr = ngx_array_push(a);*ptr = i + 1;}dump_array(a);ngx_array_destroy(a);ngx_destroy_pool(pool);return 0;}

结果:

# ./ngx_array_t_test
-------------------------------- create a new pool:
-------------------------------- pool = 0x860b020 .d .last = 0x860b048.end = 0x860b420.next = 0x0.failed = 0 .max = 984.current = 0x860b020.chain = 0x0.large = 0x0.cleanup = 0x0.log = 0x0 available pool memory = 984
-------------------------------- alloc an array from the pool:
-------------------------------- pool = 0x860b020 .d .last = 0x860b084.end = 0x860b420.next = 0x0.failed = 0 .max = 984.current = 0x860b020.chain = 0x0.large = 0x0.cleanup = 0x0.log = 0x0 available pool memory = 924
array = 0x860b048 .elts = 0x860b05c.nelts = 10.size = 4.nalloc = 10.pool = 0x860b020 elements: 0x1  0x2  0x3  0x4  0x5  0x6  0x7  0x8  0x9  

相关内容

热门资讯

人民监督员制度把民意融入检察工... 2015年2月,习近平总书记主持召开中央全面深化改革领导小组会议,审议通过《深化人民监督员制度改革方...
美法官驳回H-1B签证费涨价起... 新华社华盛顿12月23日电(记者杨伶 熊茂伶)美国一名联邦法官23日驳回美国商会和美国大学协会就特朗...
构建完善无人机管理法规体系 护... “十五五”规划建议稿明确提出“建设现代化产业体系,巩固壮大实体经济根基”,并将低空经济纳入未来五年重...
无人机“黑飞”的危害及法律责任 如今,无人机已不是专业玩家的专属装备,从旅游航拍到物流配送,从农业植保到电力巡检,从应急救援到地理测...
一次性信用修复彰显政策温度 中国人民银行日前发布一次性信用修复政策有关安排,对于2020年1月1日至2025年12月31日期间,...
最高检:立足检察公益诉讼职能定... 12月25日,全总召开2025年劳动法律监督“一函两书”典型案例新闻发布会。会上,最高人民检察院公益...
筑牢低空安全根基:无人机法规教... 低空经济作为国家战略性新兴产业,正以技术创新为引擎、应用场景为载体,加快重塑航空产业格局,成为推动经...
规范幼儿园收费 确保普惠政策精... 近日,国家发展改革委、教育部、财政部联合印发《关于完善幼儿园收费政策的通知》,明确幼儿园可收取保育教...
三部门发文:完善幼儿园收费政策 12月23日,由国家发展改革委、教育部、财政部联合印发的《关于完善幼儿园收费政策的通知》(以下简称《...
三部门联合发布2025年劳动法... 中新网12月25日电 据最高人民检察院微信公众号25日消息,中华全国总工会、最高人民法院、最高人民检...