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

Content 0. 序 1. 数组结构 1.1 ngx_array_t结构 1.2 ngx_array_t的逻辑结构 2. 数组操作 2.1 创建数组 2.2 销毁数组 2.3 添加1个元素 3. ...

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

菜鸟nginx源码剖析数据结构篇(四)红黑树ngx_rbtree_t   Author:Echo Chen(陈斌) Email:chenb19870707@gmail.com ...

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

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

Nginx源码分析---数组结构ngx_array_t

0. 序  本文开始介绍nginx的容器,先从最简单的数组开始。  数组实现文件:文件:./src/core/ngx_array.h/.c。.表示nginx-1.0.4代码目录,本文为/u...
  • cywosp
  • cywosp
  • 2011-12-02 14:55
  • 1011

nginx源码那些事之array结构分析

对于nginx来说,包含很多结构体,array便是其中之一。        array结构体声明如下: struct ngx_array_s { void *elts...

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

对应文件为core/ngx_array.{c|h} ngx_array是nginx内部封装的,使用ngx_pool_t对内存池进行分配的数组容器,其中的数据是在一整片内存区中连续存放的。更新数据时只...

7.nginx源码分析之数据结构:ngx_array_t

nginx源码分析之数据结构:ngx_array_t ngx_array_t是一个数组结构,实现的非常精简。结构体的定义如下所示: typedef struct { void ...

文章2:Nginx源码分析-ngx_array_t动态数组

目录 1、为什么要设计ngx_array_t动态数组 2、ngx_array_t的定义 3、操作动态数组的方法 1、为什么要设计ngx_array_t动态数组 数组使用一整块内存,可以根据下标直...

Nginx 数组结构 ngx_array_t

在 Nginx 数组中,内存分配是基于内存池的,并不是固定不变的,也不是需要多少内存就申请多少,若当前内存不足以存储所需元素时,按照当前数组的两倍内存大小进行申请,这样做减少内存分配的次数,提高效率。

nginx 源码学习(六) 基本数据结构 ngx_array_t

ngx_array_t 介绍  ngx_array_t是nginx内部使用的数组结构。显而易见ngx_array_t是一个顺序容器,它以数组的形式存储元素,并能够在数组容量达到上限时动态扩容数组,...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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