剖析Nginx内存池(重要类型定义和创建内存池函数)

剖析Nginx内存池(重要类型定义和创建内存池函数)

重要宏

内存池的设计,一般都会有大小内存的分界线
在这里插入图片描述
SGI STL内存池的应用场景主要是容器内存的分配释放,而Nginx是一个http服务器,包含了很多重要的模块,它的内存池是提供给所有模块使用的,它的大小内存的分界线是一个页面的大小,也就是4K,比SGI STL的128字节大的多。

  • NGX_DEFAULT_POOL_SIZE:内存池的默认大小,为16K
  • NGX_POOL_ALIGNMENT:内存对齐单位,为16
  • NGX_MIN_POOL_SIZE:内存池最小的大小,其定义用到了另一个宏,该宏定义为:
#define ngx_align(d, a)     (((d) + (a - 1)) & ~(a - 1))

这个宏的作用和SGI STL中的_S_round_up函数作用一样,用来提升到最邻近对齐字节倍数。其中的ngx_pool_t类型和ngx_pool_large_t类型后面再介绍,在这只需理解这个宏的作用即可。

重要函数

//创建内存池
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);

//分配内存,考虑内存对齐
void *ngx_palloc(ngx_pool_t *pool, size_t size);
//分配内存,不考虑内存对齐
void *ngx_pnalloc(ngx_pool_t *pool, size_t size);
//分配内存并初始化为0
void *ngx_pcalloc(ngx_pool_t *pool, size_t size);
//释放内存
ngx_int_t ngx_pfree(ngx_pool_t *pool, void *p);

重要struct

//小块内存链表普通节点
typedef struct {
    u_char               *last;
    u_char               *end;
    ngx_pool_t           *next;
    ngx_uint_t            failed;
} ngx_pool_data_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 ngx_pool_s ngx_pool_t;
struct ngx_pool_s {
    ngx_pool_data_t       d;
    size_t                max;
    ngx_pool_t           *current;
    ngx_chain_t          *chain;
    ngx_pool_large_t     *large;
    ngx_pool_cleanup_t   *cleanup;
    ngx_log_t            *log;
};

内存池创建函数

先来看创建内存池ngx_pool_t *ngx_create_pool(size_t size, ngx_log_t *log);的函数定义:

ngx_pool_t *
ngx_create_pool(size_t size, ngx_log_t *log)
{
    ngx_pool_t  *p;

    p = ngx_memalign(NGX_POOL_ALIGNMENT, size, log);
    if (p == NULL) {
        return NULL;
    }

    p->d.last = (u_char *) p + sizeof(ngx_pool_t);
    p->d.end = (u_char *) p + size;
    p->d.next = NULL;
    p->d.failed = 0;

    size = size - sizeof(ngx_pool_t);
    p->max = (size < NGX_MAX_ALLOC_FROM_POOL) ? size : NGX_MAX_ALLOC_FROM_POOL;

    p->current = p;
    p->chain = NULL;
    p->large = NULL;
    p->cleanup = NULL;
    p->log = log;

    return p;
}

在这里插入图片描述
首先从堆申请内存,Nginx用两个宏来确定是否字节对齐,如果申请失败则输出错误日志,然后返回空指针。

申请成功则用一个ngx_pool_t 类型的指针指向申请内存的起始地址,ngx_pool_t类型是用来记录一个内存池的状态的头信息,一个ngx_pool_t对应一个内存池。
然后把ngx_pool_t的d.last和d.end成员分别指向申请内存块的起始地址和末尾地址;d.next 表示下块小块内存池,初始化为 NULL,d.failed 表示小块内存申请失败的次数,初始化为 0;max记录小块内存池的最大大小,不超过4095也就是一个页面的大小。current表示分配小块内存的当前块,初始化为内存池头。其初始化结构如下图:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_200_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值