浅谈nginx内存池(一)

来源:互联网 发布:淘宝评价不能发图片 编辑:程序博客网 时间:2024/06/12 22:18

一直听别人说nginx的内存池设计非常巧妙,所以就去学习了一下。感觉确实很不错。在这里我就说说我的理解吧。可能有的地方理解不到位,请多谅解!吐舌头

 

1.首先介绍一下内存池的结构:

//内存池的结构

struct ngx_pool_t {

//数据区的指针

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相当于内存池的一个头,保存了当前内存池的一些必要信息而已。

 

当内存池存取数据的时候,有两种情况:

(1)小块数据。他是直接从内存池中取得数据的。

(2)大块数据。他是直接malloc一块数据,也就是说是从内存池外部分配数据的,然后将这个指针保存到内存中。

 

问题:如何判断是小块数据还是大块数据?

答:如果需要分配的内存大于max(在前面的ngx_pool_t中),则认为是较大内存,否则是较小内存。

 

2.下面介绍一下数据区的指针ngx_pool_data_t

这个结构其实相对来说还是比较简单的,它包含了我们所需要操作这块内存池数据的一些指针。结构体如下:

typedef struct {

//表示已使用数据的结尾

u_char *last;


//表示当前内存池的结尾

u_char *end;


//指向下一块内存池

ngx_pool_t *next;


///失败标记

ngx_uint_t failed;

} ngx_pool_data_t;

 

由此可以知道:end - last表示内存池中还未使用的内存大小。

failed域主要是标记我们请求的时候由于内存池空间不够,我们需要分配一个子内存池的次数。

 

问题:在nginx中如果内存池满了该如何处理?

答:这个就是比较特殊的地方了。一般来说,当我们一个内存池请求一块内存时,如果此时内存池已经满了,那么就是扩大内存池。但是nginx中却不是这样做的。他是直接再分配一个内存池,然后链接到ngx_pool_data_t中的next指针上。也就是说,在nginx中,每一个内存池都会包含一些子内存池,我们请求内存的时候都需要遍历这些子内存池。

 

3.ngx_chain_t这个比较复杂,我们放到后面介绍,下来我们看看ngx_pool_large_s,他表示了大块的内存,这个结构也是很简单的,结构如下:

struct ngx_pool_large_s {

//指向下一块large

ngx_pool_large_t *next;


//指向数据

void *alloc;

};

 

4.ngx_pool_cleanup_s

这个结构是用来表示内存池中的数据的清理handler,结构如下:

struct ngx_pool_cleanup_s {

//清理函数

ngx_pool_cleanup_pt handler;


//传递给清理函数的数据

void *data;


//表示下一个清理handler

ngx_pool_cleanup_t *next;

};


具体结构如图所示:



下一节就要进入具体的函数啦!!!奋斗

原创粉丝点击