一、nginx 中内存池相关结构体定义
内存池管理结构的定义或者说内存池结构的定义:
typedef struct ngx_pool_large_s ngx_pool_large_t;
struct ngx_pool_s {
ngx_pool_data_t d;//第一块初始小内存,单链表
size_t max;//内存池中最大内存块的数目
ngx_pool_t *current;//指向当前的正在使用的内存池
ngx_chain_t *chain;//下一个ngx_chain_t结构
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;
大块内存的定义:
struct ngx_pool_large_s {
ngx_pool_large_t *next;
void *alloc;
};
那么nginx代码是如何管理的呢?下面一个图很说明问题
这里要注意的是,struct ngx_pool_s中的ngx_pool_data_t d这个成员,其中d是小内存的第一块内存,这段结构是内含在第一次分配内存的中的,作为小内存的sentinel。
当然,内存池创建的第一块内存中存储有效数据的要剪掉ngx_pool_t这个结构的大小,剩余部分便是存储数据的部分。
而大内存的结构只有两个成员,可以看到,大内存中,不存在已经使用和未使用的两部分,也就是说,如果某次需要分配大内存,直接使用就是了,不需要计算used或者unused部分,也不需要计算像小内存中的last的位置。
内存池的创建:
这块代码值得注意的是内存池结构体成员max的取值,宏NGX_MAX_ALLOC_FROM_POOL如果在64位系统上为4096
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);//指向刨除调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_palloc
我们看到,向内存池申请内存的时候会有大体三种状况:
1、小块内存,并且内存池中有足够的内存来供分配
2、小块内存,并且内存池中没有足够的内存来分配
3、申请大块内存
当然,也会有三种策略
对应情况1,就是在小块内存链表中查找到,直到这块内存足够
对应情况2,则重新申请一块内存
对应情况3,则直接申请大块内存
//last成员指向可用地址空间的首地址
void *
ngx_palloc(ngx_pool_t *pool, size_t size)
{
u_char *m;
ngx_pool_t *p;
//内存足够分配的情况下
if (size <= pool->max) {
p = pool->current;
do {
m = ngx_align_ptr(p->d.last, NGX_ALIGNMENT);//alignment in available memroy
if ((size_t) (p->d.end - m) >= size) {//测试当前可用空间是否大于申请数字
p->d.last = m + size;
return m;
}
p = p->d.next;
} while (p);
//重新申请一块新的内存
return ngx_palloc_block(pool, size);
}
//内存不足的情况下
return ngx_palloc_large(pool, size);
}
当然,其中有一部分挺重要的,就是ngx_align_ptr,这块我只是猜测是字节对齐的部分,但是不确定
#define ngx_align_ptr(p, a) \
(u_char *) (((uintptr_t) (p) + ((uintptr_t) a - 1)) & ~((uintptr_t) a - 1))