Nginx源码研究(7)——内存池结构ngx_pool_t

简介

本文主要介绍Nginx内存池结构ngx_pool_t这一重要的数据结构的使用方法和具体实现。同时为了方便学习和研究,还从ngx_pool_t抽取了一个完全独立的cg_pool_t结构,不依赖Nginx,也不依赖任何第三方类库,可以直接将源码拿走集成进现有系统中。

典型的应用场景是这样的,假如你有一个nginx扩展,用到了ngx_pool_t这个数据结构,但是现在有一个需求是需要将这份扩展代码独立出来,不依赖nginx运行,那么这个cg_pool_t是你的好帮手,你几乎只需要将头文件从ngx_palloc.h换为cg_pool.h即可,代码完全不用修改即可完成移植。

Nginx的内存池在大量的小块内存的申请和释放的时候,能更快地进行内存分配(对比malloc和free),同时减少内存碎片,防止内存泄露。尤其是在防止内存泄露方面,Nginx的内存池的设计可谓非常巧妙。调用者可以一直在一个ngx_pool_t上调用ngx_palloc申请内存,而只需在最后释放这个ngx_pool_t对象即可将中途所有申请的内存统统一块释放掉。从而大大减少内存泄露的可能性,也大大简化c程序的开发逻辑流程。

Nginx内存池源代码位置

src/core/ngx_palloc.{h,c}

cg_pool_t内存池的源码位置

https://github.com/zieckey/nginx-research/tree/master/libnginx/pool

源码分析


typedef struct ngx_pool_large_s  ngx_pool_large_t;
//大内存结构
struct ngx_pool_large_s {
    ngx_pool_large_t     *next; //下一个大块内存
    void                 *alloc;//nginx分配的大块内存空间
};

//该结构用来维护内存池的数据块,供用户分配之用
typedef struct {
    u_char               *last;  //当前内存分配结束位置,即下一段可分配内存的起始位置
    u_char               *end;   //内存池结束位置
    ngx_pool_t           *next;  //链接到下一个内存池
    ngx_uint_t            failed;//统计该内存池不能满足分配请求的次数
} ngx_pool_data_t;

//该结构维护整个内存池的头部信息
struct ngx_pool_s {
    ngx_pool_data_t       d;       //数据块
    size_t                max;     //数据块大小,即小块内存的最大值
    ngx_pool_t           *current; //保存当前内存值
    ngx_chain_t          *chain;   //可以挂一个chain结构
    ngx_pool_large_t     *large;   //分配大块内存用,即超过max的内存请求
    ngx_pool_cleanup_t   *cleanup; //挂载一些内存池释放的时候,同时释放的资源
    ngx_log_t            *log;
};

内存结构图

备注:从参考博客5摘录

备注:从参考文档6摘录

测试代码

该测试代码的完整工程的编译和运行方式请参考 https://github.com/zieckey/nginx-research项目。Linux&Windows都测试通过。

TEST_UNIT(ngx_pool) {
    ngx_pool_t* pool = ngx_create_pool(1024, NULL);
    char* p = (char*)ngx_palloc(pool, 32);
    const char* s = "hello world\n";
    strcpy(p, s);
    H_TEST_ASSERT(strcmp(p, s) == 0);

    p = (char*)ngx_palloc(pool, 4096); // alloc a large block

    ngx_destroy_pool(pool);
}

参考:

  1. 淘宝:Nginx开发从入门到精通 http://tengine.taobao.org/book/chapter_02.html#ngx-queue-t-100
  2. nginx源码注释 https://github.com/zieckey/nginx-1.0.14_comment/blob/master/src/core/ngx_palloc.h
  3. nginx源码注释 https://github.com/zieckey/nginx-1.0.14_comment/blob/master/src/core/ngx_palloc.c
  4. Nginx源码剖析之内存池,与内存管理 http://blog.csdn.net/v_july_v/article/details/7040425
  5. nginx源码学习—-内存池 http://www.cnblogs.com/xiekeli/archive/2012/10/17/2727432.html
  6. nginx源码研究 https://code.google.com/p/nginxsrp/wiki/NginxCodeReview