nginx----array

原创 2015年07月09日 21:25:13

1、array的结构体

ngx_array_t是nginx中定义的数组结构,用于存储数据,其结构体定义如下:

typedef struct {
    void        *elts;   //指向分配给数据存储空间的内存起始地址
    ngx_uint_t   nelts;  //当前数组中存储的元素的个数
    size_t       size;   //每个元素的大小
    ngx_uint_t   nalloc; //数组的大小,即最多可存储的元素个数
    ngx_pool_t  *pool;   //指向该数组所在的内存池
} ngx_array_t;

由于nginx内部的内存都是通过内存池来分配的,因此一般的结构体中都有一个指向内存池的指针,用于内存的回收释放。在为数组分配空间时,通过要分配的元素个数和大小来确定待分配空间的大小,即size * nalloc;然后通过nelts来记录数组中已存在的元素个数,可用来找到数组中下一个空闲空间的起始地址。

2、数组的创建

我们一般为每一类待存放的数据初始化一个数组。

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;
}
首先为ngx_array_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)
{
    array->nelts = 0;   //完成array结构的初始化
    array->size = size;
    array->nalloc = n;
    array->pool = pool;

    array->elts = ngx_palloc(pool, n * size);  //为数据分配的存储空间大小为 n * size
    if (array->elts == NULL) {
        return NGX_ERROR;
    }
    return NGX_OK;
}
这样就创建了一个array数组了,其结构如下:


3、元素的插入

nginx中元素的插入不是直接将某个元素赋值的,而是先找到待插入元素在数组中的起始地址并返回,然后再由用户程序进行赋值的,以同时插入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;  //size为待分配的内存大小
    //首先判断当前数组空间是否足够
    if (a->nelts + n > a->nalloc) {  //case1:当前数组空间不够,需要重新分配资源

        p = a->pool;

        if ((u_char *) a->elts + a->size * a->nalloc == p->d.last
            && p->d.last + size <= p->d.end)  //如果当前数组在该内存块已用空间的尾部,且该内存块的剩余空间足够存放所需空间时,直接将该内存块尾部的size大小的内存分配给数组
        {
            p->d.last += size;
            a->nalloc += n;

        } else {   //case2:否则如果数组内存空间不够,且其所在内存块的空间也不够时,就要重新分配内存
            /* allocate a new array */

            nalloc = 2 * ((n >= a->nalloc) ? n : a->nalloc);  //分配2倍所需大小的空间

            new = ngx_palloc(p, nalloc * a->size);
            if (new == NULL) {
                return NULL;
            }

            ngx_memcpy(new, a->elts, a->nelts * a->size); //将原来数组的数据copy到新的内存空间中
            a->elts = new;   //数组存放数据的空间指向新分配的内存空间
            a->nalloc = nalloc;  //新数组的大小
        }
    }

    elt = (u_char *) a->elts + a->size * a->nelts;  //case3:通过元素个数找到可用空间的起始地址
    a->nelts += n;  //内存中已用元素加n

    return elt;
}

内存示意图如上所示,且left > n*size时,即对应case1 ,直接在内存块尾部的剩余空间中为数组分配所需空间的大小。其它数组空间不够的情况都对应case2,即都需要重新分配内存空间。然后即可通过元素个数找到数组空闲空间的起始地址。

4、数组的销毁

数组的销毁只是简单的将分配的内存空间返回给内存池

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;
    }
}
可以发现,将数组销毁时,只是简单的将数组占用的内存空间归还给了内存池,数组中各个字段的值并没有被置0,因此当我们申请数组时,一定要先调用ngx_array_init()将各字段置0,保证内存空间时干净的。

为了保证不频繁的申请内存,应注意提前规划好要申请的空间大小。


版权声明:本文为博主原创文章,未经博主允许不得转载。

nginx学习七 高级数据结构之动态数组ngx_array_t

1 ngx_array_t结构 ngx_array_t是nginx内部使用的数组结构。nginx的数组结构在存储上与大家认知的C语言内置的数组有相似性,比如实际上存储数据的区域也是一大块连续的内存。但...
  • yanziguilai
  • yanziguilai
  • 2014年09月28日 22:48
  • 1702

Nginx源码分析 - 基础数据结构篇 - 数组结构 ngx_array.c

前面一章我们介绍了Nginx的内存池的数据结构。Nginx的内存管理都是围绕内存池来实现的,包括array数组类型也是基于Nginx的pool来实现数据结构。 Nginx的Array结构设计得非常小巧...
  • initphp
  • initphp
  • 2016年01月28日 16:50
  • 1408

Nginx模块开发(15)—日志模型

参考: http://cjhust.blog.163.com/blog/static/175827157201242182635874/
  • yangguangmeng
  • yangguangmeng
  • 2014年06月06日 13:20
  • 1277

Nginx高效数据结构(1)——数组(ngx_array_t)

Nginx是我们学习编程的一个非常有参考价值的开源项目。良好的编码风格,高效的数据结构、架构设计。...
  • xingdou520
  • xingdou520
  • 2016年11月19日 20:35
  • 285

nginx 源码学习笔记(八)——基本容器——array数组

对应文件为core/ngx_array.{c|h} ngx_array是nginx内部封装的,使用ngx_pool_t对内存池进行分配的数组容器,其中的数据是在一整片内存区中连续存放的。更新数据...
  • huangyimo
  • huangyimo
  • 2015年12月05日 14:54
  • 155

nginx源码分析—数组结构ngx_array_t

ntent 0. 序 1. 数组结构 1.1 ngx_array_t结构 1.2 ngx_array_t的逻辑结构 2. 数组操作 2.1 创建数组 2.2 ...
  • midion9
  • midion9
  • 2015年10月29日 11:35
  • 226

nginx源码分析--数据结构ngx_array_t

Content 0. 序 1. 数组结构 1.1 ngx_array_t结构 1.2 ngx_array_t的逻辑结构 2. 数组操作 2.1 创建数组 2.2 销毁数组 2.3 添加1个元素 3. ...
  • yusiguyuan
  • yusiguyuan
  • 2014年03月09日 17:17
  • 919

解码Nginx:数组(Array)

源码文件 src/core/ngx_array.h src/core/ngx_array.c 设计思路 数组是非常常用的数据结构。为降低使用时的时间开销,Nginx对数组设计做了不...
  • wdt3385
  • wdt3385
  • 2013年08月12日 20:35
  • 658

菜鸟nginx源码剖析数据结构篇(一)动态数组ngx_array_t

菜鸟nginx源码剖析数据结构篇(四)红黑树ngx_rbtree_t   Author:Echo Chen(陈斌) Email:chenb19870707@gmail.com ...
  • chen19870707
  • chen19870707
  • 2014年10月21日 13:54
  • 67017

nginx源码分析—数组结构ngx_array_t

数组实现文件:文件:./src/core/ngx_array.h/.c 1.数组结构 struct ngx_array_s { void *elts; //数组...
  • chanlp129
  • chanlp129
  • 2013年04月23日 23:25
  • 703
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:nginx----array
举报原因:
原因补充:

(最多只允许输入30个字)