nginx源码分析----内存池ngx_palloc分析

  1. NGinx内存池主要结构体说明

主要说明内存池相关结构体的字段内容说明。

struct ngx_pool_cleanup_s {
    ngx_pool_cleanup_pt   handler;/* 清理的回调函数一般是ngx_pool_cleanup_file和ngx_pool_delete_file */
    void                 *data;  /* 指向存储的数据地址一般是ngx_pool_cleanup_file_t */
    ngx_pool_cleanup_t   *next;/* 下一个ngx_pool_cleanup_t */
};

typedef struct ngx_pool_large_s  ngx_pool_large_t;

struct ngx_pool_large_s {
    ngx_pool_large_t     *next; /* 指向下一个存储地址 通过这个地址可以知道当前块长度 */ 
    void                 *alloc;   /* 数据块指针地址 */
};

typedef struct {
    u_char               *last;/* 内存池中未使用内存的开始节点地址 */
    u_char               *end; /* 内存池的结束地址 */
    ngx_pool_t           *next;/* 指向下一个内存池 */
    ngx_uint_t            failed;/* 失败次数,主要用于记录current后面内存池挂接的数量 考虑查找性能*/
} ngx_pool_data_t;

struct ngx_pool_s {
    ngx_pool_data_t       d;          /* 内存池的数据区域*/
    size_t                max;           /* 最大每次可分配内存 */
    ngx_pool_t           *current;  /* 指向当前的内存池指针地址。ngx_pool_t链表上最后一个缓存池结构*/
    ngx_chain_t          *chain;    /* 缓冲区链表 */
    ngx_pool_large_t     *large;  /* 存储大数据的链表 malloc申请内存需要注意内存释放*/

    ngx_pool_cleanup_t   *cleanup; /* 可自定义回调函数, 结构体及数据
                                data都是在内存池上申请,无需注意内存的释放*/
    ngx_log_t            *log;             /* 日志 */
};
typedef struct {
    ngx_fd_t              fd; /*文件描述符*/
    u_char               *name;/*文件的存储路径*/
    ngx_log_t            *log; /*log日志记录文件*/
} ngx_pool_cleanup_file_t;

数据结构图
1. Nginx的内存池会放在ngx_pool_t的数据结构上(ngx_pool_data_t用于记录内存块block的可用地址空间和内存块尾部)。当初始化分配的内存块大小不能满足需求的时候,Nginx就会调用ngx_palloc_block函数来分配一个新的内存块ngx_pool_t,通过链表的形式连接起来。内存池只有全部销毁的函数ngx_destroy_pool,没有针对单个内存的释放函数。

  1. 当申请的内存大于pool->max的值的时候,Nginx就会单独分配一块large的内存块,会放置在pool->large的链表结构上。ngx_pool_large_t本身的内存空间是在内存池上申请的,无需注意释放。但是alloc数据块的内存直接malloc申请,关注内存释放。

  2. pool->cleanup的链表结构主要存放需要通过回调函数关闭文件描述符及删除文件。ngx_pool_cleanup_s本身结构体的空间是在内存池上申请的;结构体成员data也是在内存池上申请的,无需考虑释放。
    这里写图片描述

主要函数说明
1、内存池的申请、销毁及重设
疑问:1、内存池只有全部销毁及重设操作,如果频繁在内存池上申请内存,而不释放?
2、内存池是如何工作的?

/*主要完成内存池首个节点的初始化工作。*/
ngx_pool_t *ngx_create_pool(size_t size, ngx_log_t *log);
/*主要完成内存池中挂接所有数据的释放,及内存池链表的数据释放*/
void ngx_destroy_pool(ngx_pool_t *pool);
/*应该是内存池数据不再使用时刻重新设置*/
void ngx_reset_pool(ngx_pool_t *pool);

2、从内存池上申请内存,或者大块malloc内存的申请及释放

/*按照字节对其方式,在内存上申请size大小内容*/
void *ngx_palloc(ngx_pool_t *pool, size_t size);
/*按照非字节对其方式,在内存上申请size大小内容*/
void *ngx_pnalloc(ngx_pool_t *pool, size_t size);
/*按照字节对其方式,在内存上申请size大小内容并对申请内存进行初始化操作*/
void *ngx_pcalloc(ngx_pool_t *pool, size_t size);
/*申请大块内存地址,且挂在内存池*/
void *ngx_pmemalign(ngx_pool_t *pool, size_t size, size_t alignment);
/*释放指定的大块内存地址*/
ngx_int_t ngx_pfree(ngx_pool_t *pool, void *p);

参考文件:https://blog.csdn.net/initphp/article/details/50588790

猜你喜欢

转载自blog.csdn.net/jsh13417/article/details/80699561