`
Poechant
  • 浏览: 227503 次
博客专栏
Bebe66e7-3a30-3fc9-aeea-cfa3b474b591
Nginx高性能Web服务...
浏览量:24243
5738817b-23a1-3a32-86de-632d7da73b1e
Cumulus实时媒体服务...
浏览量:22050
社区版块
存档分类
最新评论

Nginx源码完全注释(2)ngx_array.h / ngx_array.c

 
阅读更多

Nginx源码完全注释(2)ngx_array.h / ngx_array.c

  • 作者:柳大·Poechant(钟超)
  • 邮箱:zhongchao.ustc#gmail.com(# -> @)
  • 博客:Blog.CSDN.net/Poechant
  • 日期:August 15th, 2012

数组头文件ngx_array.h


#include <ngx_config.h>
#include <ngx_core.h>

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

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)
{
    /*
     * 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;
    }

    return NGX_OK;
}

数组源文件ngx_array.c


#include <ngx_config.h>
#include <ngx_core.h>

/* 创建一个 Nginx 数组,内存池地址为 p,元素个数为 n,每个元素大小为 size */
ngx_array_t *
ngx_array_create(ngx_pool_t *p, ngx_uint_t n, size_t size)
{
    ngx_array_t *a;

    // 调用 ngx_palloc,从 内存池 p,为 Nginx 数组 a 分配内存
    a = ngx_palloc(p, sizeof(ngx_array_t));
    if (a == NULL) {
        return NULL;
    }

    // 调用 ngx_palloc,为 Nginx 数组 a 的 elts 分配内存,大小为 n * size
    a->elts = ngx_palloc(p, n * size);
    if (a->elts == NULL) {
        return NULL;
    }
    
    // 注意,上面是先分配定义结构区,再定义数据存储区

    // 其他初始化项
    a->nelts = 0; // 已存元素数
    a->size = size; // 每个元素大小(字节)
    a->nalloc = n; // 最大元素数
    a->pool = p; // 内存池地址

    return a;
}


void
ngx_array_destroy(ngx_array_t *a)
{
    ngx_pool_t  *p;

    // 数组 a 的内存池地址
    p = a->pool;

    // 数组 a 的最大存储区的末尾,到了内存池的已用区域的末尾(可用区的开头)
    // 即表示内存池目前最后一段存储的是一个数组的存储区
    if ((u_char *) a->elts + a->size * a->nalloc == p->d.last) {
        // 内存池已用区域末尾向前挪(每个元素大小 x 最大元素个数)字节
        p->d.last -= a->size * a->nalloc; 
    }

    // 数组 a 结构体所占用内存的末尾,为内存池的可用区的开头
    // 即表示内存池目前最后一段存储的是一个数组的结构体
    if ((u_char *) a + sizeof(ngx_array_t) == p->d.last) {
        p->d.last = (u_char *) a;
    }
    
    // 上面先剪掉数据存储区,再剪掉定义结构区
}


void *
ngx_array_push(ngx_array_t *a)
{
    void        *elt, *new;
    size_t       size;
    ngx_pool_t  *p;

    // 数组满了,即已存储元素数 nelts 已达到最大容纳数 nalloc
    if (a->nelts == a->nalloc) {

        /* the array is full */
        // size 为数组的最大容量(最大容纳数 x 每个元素大小)
        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
             */

            // 分配一个元素,就得把 last 往下挪一个,即已用区域往下挪一个
            p->d.last += a->size;
            
            // 分配一个元素,且内存池没满,就得把“最大元素数”加1
            a->nalloc++;

        } else { // 内存池剩余空间不够
            /* allocate a new array */

            // 分配一个两倍的空间(原来空间的两倍)
            new = ngx_palloc(p, 2 * size);
            if (new == NULL) {
                return NULL;
            }

            // 把 a->elts 的东东拷贝到 new 里,拷贝 size 字节个数据
            ngx_memcpy(new, a->elts, size);
            a->elts = new; // 新地址
            a->nalloc *= 2; // 新最大容量
            
            // size 不变(最大容量,即单个元素大小 x 最大元素数)
            // pool 不变
            // nelts 已用元素数不变
        }
    }

    // elt 为已用数据区的末尾
    elt = (u_char *) a->elts + a->size * a->nelts;
    
    // 已存数据个数加 1
    a->nelts++;

    // 返回这个已用数据区的末尾(可用数据区的开头,或者说是下一个元素可以用的位置)
    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;

    // 要放的 n 个元素所占的总字节数
    size = n * a->size;

    // 已存元素数 + 要存的 n 个元素 > 最大容量(最大元素数)
    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
             */

            // 分配 n 个元素,就得把 last 往后挪 size = n * a->size
            p->d.last += size;
            
            // 分配 n 个元素,且内存池没满,就得把“最大元素数(最大容量)”加 n
            a->nalloc += n;

        } else { // 内存池剩余空间不够
            /* allocate a new array */

            // 准备分配一个两倍的空间,nalloc是新空间的大小
            // (如果原来最大容量大,则分配原来空间的两倍;如果新要的n个元素更多,则分配n的两倍)
            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);
            
            // elts 新空间地址
            a->elts = new;
            
            // nalloc 数组最大容量
            a->nalloc = nalloc;
        }
    }

    // 要放入的 n 个元素的起始位置
    elt = (u_char *) a->elts + a->size * a->nelts;
    
    // 已用元素数加 n
    a->nelts += n;

    // 返回n个东东的位置
    return elt;
}

Reference

  1. http://blog.csdn.net/v_july_v/article/details/7040425
  2. http://www.cnblogs.com/sld666666/archive/2010/06/27/1766255.html
  3. http://www.cnblogs.com/jzhlin/archive/2012/06/05/Nginx_pool.html
  4. http://code.google.com/p/nginxsrp/wiki/NginxCodeReview#ngx的内存池

-

转载请注明来自柳大Poechant(钟超Michael)的CSDN博客:

钟超Michael的博客:Blog.CSDN.net/Poechant

钟超Michael的微博:钟超Michael的新浪微博

-

分享到:
评论

相关推荐

    nginx-1.18.0-2.el7.ngx.x86-64.rpm安装包(含有部署手册)

    nginx-1.18.0-2.el7.ngx.x86_64.rpm安装包(含有部署手册) nginx-1.18.0-2.el7.ngx.x86_64.rpm安装包(含有部署手册) nginx-1.18.0-2.el7.ngx.x86_64.rpm安装包(含有部署手册) nginx-1.18.0-2.el7.ngx.x86_64.rpm...

    Nginx的SQLite模块ngx_sqlite.zip

    ngx_sqlite 是嵌入 sqlite 数据库的 nginx 模块。通过强大的nginx server,可以使用http协议访问sqlite数据库。环境- sqlite 3- nginx-1.6.3 安装```sh $ git clone https://github.com/rryqszq4/ngx_sqlite.git...

    ngx_stream_module.so

    nginx1.20.2

    ngx_cache_purge_2.4.2.tar.gz

    ./configure --add-module=../ngx_cache_purge-2.4.2 ``` 4. 编译并安装Nginx,这将同时编译ngx_cache_purge模块。 5. 在Nginx的配置文件中启用该模块,并设置相应的清理规则,如: ``` http { cache_path /...

    ngx_http_dav_ext_module.so

    ngx_http_dav_ext_module.so centos7 nginx 1.18 可以作为模块加载

    nginx的php模块ngx_php.zip

    ngx_php功能是为nginx模块嵌入php脚本语言。别名为php-nginx-module。 特性 * 支持加载php.ini配置文件 * 支持原生php的全局变量$_GET, $_POST, $_COOKIE, $_SERVER, $_FILES, $_SESSION... * 支持运行php代码...

    ngx_devel_kit-0.3.0

    ngx_devel_kit(通常缩写为 NDK)是一个针对Nginx的模块开发工具集,它为构建自定义Nginx模块提供了便利。在Nginx生态系统中,NDK是一个重要的扩展工具,允许开发者利用C语言直接操作Nginx的内部结构,以实现更高级...

    ngx_http_proxy_connect_module.zip

    3. 编译和安装:运行`./configure`,然后`make`和`make install`以编译并安装带有新模块的Nginx。 4. 配置Nginx服务器块:在Nginx的配置文件(如nginx.conf)中,为需要启用代理服务的域或端口定义一个新的服务器块...

    嵌入Python脚本的Nginx模块ngx_python.zip

    ngx_python 是为 nginx 嵌入 python 脚本的模块。环境- python 2.7.*- nginx-1.6.3 安装```sh git clone https://github.com/rryqszq4/ngx_python.git wget 'http://nginx.org/download/nginx-1.6.3.tar.gz' ...

    nginx-1.21.6-1.el7-rtmp.ngx.x86_64.tar.gz

    2. **nginx-1.21.6-1.el7.ngx.x86_64.rpm**:这是 Nginx 服务器的核心 RPM 包,包含了 Nginx 的可执行文件和其他必要的系统文件。安装这个包后,Nginx 将可以在 CentOS 7 系统上运行。 **安装与配置** 在 Linux ...

    nginx-1.22.0-1.el7.ngx.x86_64_ngx_rtmp_ipv6.rpm

    2022年5月30日 官方当前最新稳定版本nginx 二进制rpm包 适用于x86架构centos7 rhel7版本操作系统升级安装nginx 该包开启了ipv6支持,添加了nginx-rtmp模块支持

    nginx-1.22.1-1.sles12.ngx.x86-64.rpm文件(分享给需要的同学)

    nginx-1.22.1-1.sles12.ngx.x86_64.rpm文件 nginx-1.22.1-1.sles12.ngx.x86_64.rpm文件 nginx-1.22.1-1.sles12.ngx.x86_64.rpm文件 nginx-1.22.1-1.sles12.ngx.x86_64.rpm文件 nginx-1.22.1-1.sles12.ngx.x86_64.rpm...

    nginx-1.20.0-1.el7.ngx.x86_64.rpm

    nginx-1.20.0-1.el7.ngx.x86_64

    nginx缓存清除插件ngx_cache_purge.zip

    ngx_cache_purge 是 nginx 模块,此模块可以清理 nginx 的 FastCGI、proxy、 SCGI 和 uWSGI 的缓存。配置指令(相同位置语法)fastcgi_cache_purgesyntax: fastcgi_cache_purge on|off|&lt;method&gt; [from all|&lt;ip&gt; [.....

    nginx-1.6.2-1.el7.centos.ngx.x86_64.rpm

    很难找的 centos7 nginx-1.6.2-1.el7.centos.ngx.x86_64.rpm 包

    ngx_devel_kit-0.2.19.tar.gz

    4. 使用Nginx的configure脚本,通过指定--add-module选项添加NDK模块,例如:`./configure --add-module=路径/ngx_devel_kit-0.2.19`。 5. 编译并安装Nginx:`make && make install`。 6. 更新Nginx配置文件,启用...

    nginx-1.14.0-1.el7_4.ngx.x86_64.rpm

    nginx rpm package for centos7 nginx rpm package for centos7 nginx rpm package for centos7 nginx rpm package for centos7 nginx rpm package for centos7 nginx rpm package for centos7 nginx rpm package ...

    nginx流媒体安装包(nginx_mod_h264_streaming,yamdi)

    ./configure --add-module=path/to/nginx_mod_h264_streaming make sudo make install ``` 3. 配置Nginx - 在Nginx的配置文件(如/etc/nginx/nginx.conf)中,添加流媒体服务器的相关配置。例如,创建一个新的...

    ngx_http_mytest_module.zip_nginx_world

    2. **定义模块配置结构体**:在“ngx_http_mytest_module.c”中,你需要定义一个结构体来存储模块的配置信息。这些信息可以在配置文件中设置,并在处理请求时使用。 3. **解析配置指令**:使用`ngx_conf_handler_t`...

    lua-upstream-nginx-module, Nginx C 模块将Lua向ngx_lua公开,用于 Nginx upstreams.zip

    lua-upstream-nginx-module, Nginx C 模块将Lua向ngx_lua公开,用于 Nginx upstreams 电子邮件名称ngx_http_lua_upstream - Nginx MODULE,用于向 Nginx upstreams公开Lua到 ngx_lua目录NAME状态概要说明函数get_...

Global site tag (gtag.js) - Google Analytics