浅谈nginx内存池(一)

发布于:2021-07-31 10:07:03

一直听别人说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;


};




具体结构如图所示:






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

相关推荐

最新更新

猜你喜欢