nginx中的数组处理

nginx是用c开发的,在C中缺少像C++标准库之类的对数据结构进行包装的东西,

所以一切都得自己来。

nginx中自己定义了数组,在ngx_array.h和ngx_array.c文件中。这个数组是

可以动态扩展的,俗称“动态数组”(vector抗议了: 你抢了我的名字)。

自己重新定义数组而不用原生数组有如下几个好处:

1. 方便管理。

2. 安全,防止数组越界。

3.容量可扩展,效率高(只要不改变整个数组的总大小,对比vector中的capacity)。

看了相关代码,发现nginx中的动态数组对STL中vector有很重的模仿痕迹,当然两者

不是一个重量级的东西了。

1. ngx_array_t代码分析

1.1 ngx_array_t的定义

首先看一下ngx_array_t结构体的定义:

typedef  unsigned __int64 ngx_uint_t;
typedef struct ngx_array_s  ngx_array_t;


struct ngx_array_s 
{
    void*       elts;//数据块
    ngx_uint_t  nelts;//已经使用的个数
    size_t      size;//每个数据的大小
    ngx_uint_t  nalloc;//已经分配的区域
    ngx_pool_t* pool; //内存池

};

其中

elts表示这个数组的数据块,

nelts便是已经使用的个数,

size 表示每个数据的大小(int, double),

nalloc表示分配内存的大小

关于nelts和nalloc,可以对比一下STL中的size和capacity,两者是完全一样的概念。

ngx_pool_t就便是内存池了,elts的内存是从内存池中提取出来的, 在这里为了

给出源代码方便, 我屏蔽掉内存池,让其用malloc代替,所以就有了如下代码:

struct ngx_pool_t
{
    void*   Nothing;
};

nginx提供了如下5个函数来控制、使用ngx_array_st:

nginx中的数组处理nginx中的数组处理代码

1 //未创建 ngx_array_t结构体时,创建数组 2  ngx_array_t *ngx_array_create(ngx_pool_t *p, ngx_uint_t n, size_t,size); 3  4  5  //已创建ngx_array_t结构体时,创建数组 6   7  static inline int ngx_array_init(ngx_array_t *array, ngx_pool_t *pool, ngx_uint_t n, size_t size); 8  9 10  //delete 数组11  12  void ngx_array_destroy(ngx_array_t *a);13 14 15  //增加一个数组元素16  17  void *ngx_array_push(ngx_array_t *a);18 19 20  //增加N个数组元素21  22  void *ngx_array_push_n(ngx_array_t *a, ngx_uint_t n);

下面逐一解释个个函数。

1.2 ngx_array_create

要使用一个动态数组,前提是创建它。函数ngx_array_create 表示

未创建 ngx_array_t结构体时,创建数组。它的实现非常简单,

首先创建一块内存区域,然后标志已经使用的和未尝使用的。

代码如下所示:
**nginx中的数组处理nginx中的数组处理代码

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));    a = (ngx_array_t*)malloc(sizeof(ngx_array_t));    if (a == NULL)        return NULL;    a->elts = (void*)malloc(n*size);    if (a->elts == NULL)        return NULL;    a->nelts = 0;    a->size = size;    a->nalloc = n;    a->pool = p;    return a;}

当我们使用的时候,直接
*
ngx_array_t
parray = ngx_array_create(NULL, 10, sizeof(int));

这里用NULL是因为我屏蔽掉了内存池。

1.3 ngx_array_push

创建了数组的有效地址之后,我们就要使用它了,有两函数:
ngx_array_push 和 ngx_array_push_n,因为这两个函数

非常相似, 所以这里只提取其中一个ngx_array_push来分析。

ngx_array_push的代码非常简单:


nginx中的数组处理nginx中的数组处理代码

void *ngx_array_push(ngx_array_t *a){    void        *elt, *pNew;//这个原来是new,因为我用.cpp所以改成这个    size_t    size;    ngx_pool_t *p;    if (a->nelts == a->nalloc)    {        //当分配的个数等与已经用掉的个数        //即这个array 满了        size = a->size * a->nalloc;        pNew = (void* )malloc(2*size);        if (pNew == NULL)            return NULL;        memcpy(pNew, a->elts, size);        a->elts = pNew;        a->nalloc *= 2;        //整一个array扩大2陪,vector也是这样的        //然后用原来的数据初始化新申请的区域    }    elt = (u_char* ) a->elts + a->size * a->nelts;    a->nelts++;    return elt;//返回的是当前的新增加的数据}

这个函数干了一件事:得到数组中下一个未使用的地址,如果这个数组满了,



就扩大一倍。所以上层的调用代码可以为这样:int pTest = (int)ngx_array_push(parray);(pTest )= 10;int pTest = (int)ngx_array_push(parray);(pTest )= 10;

1.4 ngx_array_destroy

看完了创建,使用以后,在来看怎么删除它:nginx中的数组处理nginx中的数组处理代码

void ngx_array_destroy(ngx_array_t *a){    if (a == NULL)        return ;    free (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;//     }}

然后呢?怎么使用?一个伪列子如下

ngx_array_t* parray = ngx_array_create(NULL, 2, sizeof(int));int* pTest = (int*)ngx_array_push(parray);ngx_array_destroy(parray);

2. 小结

好了,nginx的数组管理就分析到这里,个人感觉其不管是功能还是易用程度都与C++标准库中的vector不是一个档次的, 打算在下一篇分析下STL种的vector作为对比。原文链接: https://www.cnblogs.com/sld666666/archive/2010/07/04/1770938.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/12474

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月7日 上午11:27
下一篇 2023年2月7日 上午11:30

相关推荐