Nginx内存池:内存池的创建

本文深入剖析了内存池ngx_create_pool的创建过程,包括ngx_pool_t结构体的初始化,内存对齐的处理,以及内存池的数据结构和关键成员的设置。通过ngx_memalign函数,根据平台特性进行内存对齐的申请,确保内存高效使用。最后,文章展示了内存池ngx_pool_data_t的初始化状态和内存分配策略。
摘要由CSDN通过智能技术生成

内存池的创建

函数声明:该创建函数返回一个结构体,该结构体主要保存的内存池的主要头部信息,在上篇文章中提到过

ngx_pool_t *ngx_create_pool(size_t size, ngx_log_t *log);
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;
};

typedef struct {
    u_char               *last;
    u_char               *end;
    ngx_pool_t           *next;
    ngx_uint_t            failed;
} ngx_pool_data_t;

内存池图示:

在这里插入图片描述

源码实现

接下来会对每一步骤进行解析

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

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

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

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

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

    return p;				// 6
}
  1. 转到 ngx_memalign 的定义,如下,可以看出,如果定义了这两个宏,就进行字节对齐的申请,如果没有定义,就直接使用malloc()申请。
#if (NGX_HAVE_POSIX_MEMALIGN || NGX_HAVE_MEMALIGN)

void *ngx_memalign(size_t alignment, size_t size, ngx_log_t *log);

#else

#define ngx_memalign(alignment, size, log)  ngx_alloc(size, log)

#endif

如下,如果不进行内存对齐,就调用这个函数,它直接使用malloc()。

void *ngx_alloc(size_t size, ngx_log_t *log)
{
    void  *p;

    p = malloc(size);
    if (p == NULL) {
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
                      "malloc(%uz) failed", size);
    }

    ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, log, 0, "malloc: %p:%uz", p, size);

    return p;
}

如果进行内存对齐,就调用其他API:

#if (NGX_HAVE_POSIX_MEMALIGN)

void *
ngx_memalign(size_t alignment, size_t size, ngx_log_t *log)
{
    void  *p;
    int    err;

    err = posix_memalign(&p, alignment, size);

    if (err) {
        ngx_log_error(NGX_LOG_EMERG, log, err,
                      "posix_memalign(%uz, %uz) failed", alignment, size);
        p = NULL;
    }

    ngx_log_debug3(NGX_LOG_DEBUG_ALLOC, log, 0,
                   "posix_memalign: %p:%uz @%uz", p, size, alignment);

    return p;
}

#elif (NGX_HAVE_MEMALIGN)

void *
ngx_memalign(size_t alignment, size_t size, ngx_log_t *log)
{
    void  *p;

    p = memalign(alignment, size);
    if (p == NULL) {
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
                      "memalign(%uz, %uz) failed", alignment, size);
    }

    ngx_log_debug3(NGX_LOG_DEBUG_ALLOC, log, 0,
                   "memalign: %p:%uz @%uz", p, size, alignment);

    return p;
}

#endif

  1. 对 内存池的ngx_pool_data_t进行初始化,如图:last指向除头部信息的开始(即可分配内存的起始位置),end指向可分配内存的最末尾;由于此时没有next域,所以置为NULL;failed表示从该内存池申请内存失败的次数,初始化为0。

在这里插入图片描述

  1. size是指当前内存池可供使用的字节总数,所以需要减去头部信息。
  2. 然后拿size对max赋值,如果size < 4095,就将max置为size的大小,否则将max置为一个页的大小(4095)。
  3. current指向当前内存池的起始位置,所以初始化时current指向p。其他信息初始化为NULL。日志模块初始化为参数log。
  4. 返回当前内存池首地址。

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

_索伦

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

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

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

打赏作者

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

抵扣说明:

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

余额充值