【nginx流程分析之内存分配】
写在前面
这个文章主要是为了分析nginx中是如何进行内存分配,是对上一篇文章nginx流程分析的继承,详见nginx流程分析.
所以这篇文章主要就是为了写ngx_create_pool,详见下图
ngx_create_pool
首先点进去看一下,看一下具体的实现:
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;
}
ngx_pool_t
首先看一下ngx_pool_t这个定义:
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;
ngx_pool_large_t *large;
ngx_pool_cleanup_t *cleanup;
ngx_log_t *log;
};
struct ngx_pool_large_s {
ngx_pool_large_t *next;
void *alloc;
};
struct ngx_pool_cleanup_s {
ngx_pool_cleanup_pt handler;
void *data;
ngx_pool_cleanup_t *next;
};
ngx_pool_data_t
last和end分别是下一个ngx_pool_t结构体开始的指针,然后end自然就是最后一个ngx_pool_t的指针。next指向下一个ngx_pool_t结构体的指针。failed 就是申请失败的次数。
max
就是当前最多可用的内存
current
就是当前的ngx_pool_t的指针,
ngx_chain_t
暂时没看到有什么作用,类型定义如下:
struct ngx_chain_s {
ngx_buf_t *buf;
ngx_chain_t *next;
};
large
就是申请的大内存,是一个void的指针,同时next指向下一个内存地址
typedef struct ngx_pool_large_s ngx_pool_large_t;
struct ngx_pool_large_s {
ngx_pool_large_t *next;
void *alloc;
};
cleanup
从名字可以看出来是清理内存的方法,然后看一下定义
struct ngx_pool_cleanup_s {
ngx_pool_cleanup_pt handler;
void *data;
ngx_pool_cleanup_t *next;
};
确实也是这样,handler是清理的具体实现
typedef void (*ngx_pool_cleanup_pt)(void *data);
log
log 就是用来进行日志,这个在前面已经初始化。
进行初始化
申请了一个 类型为ngx_pool_t,名称为p的变量。
然后就是申请内存,然后用的是ngx_memalign,根据NGX_POOL_ALIGNMENT也就是16位进行内存对齐的内存。因为在调用的时候传的是1024,也就是此时的size是1024,所以我们这边申请的是以 16byte对齐内存,大小为1026个字节的大小的一块内存。
然后出去ngx_pool_t占用的80字节的内存,还是944字节。
然后 p->d.last 指向开头,p->d.last 指向结尾。size就是剩余可以用的字节大小,p->max 其实和size一样,最多可用的字节大小,如果申请超过这么大的内存,那么就要申请大块内存。
文件描述可能有点枯燥,这边借用网上的一张图,可能会更加形象。
注意,这边这个大佬用的是32的电脑,所以sizeof(ngx_pool_t)是40,可用内存是 1024-40= 984,而我们的电脑是64位的,所以sizeof(ngx_pool_t)是80,可用内存是1024-80=944;
之所以是80,是因为ngx_pool_t有十个成员,然后有人疑惑max为什么也是8个字节,这个是因为c语言出于cpu利用率等原因的考虑,底层已经做了内存对齐,不足8个字节会自动补齐,因此也是8个字节。至于为什么是8个字节,是因为我们的电脑是64位,也就是8个字节。
ngx_create_pool 结束
将p返回,初始化结束。