毕竟第一次,今天就来聊点比较简单的东西。
如果此时正在读这篇博客的你是个老手,勿喷,仅供参考。毕竟水平有限。好了接下来进入正题:
今天要聊的是nginx的资源池pool设计,这个结构体ngx_pool_t贯穿了
nginx的各个地方,如果你是严格按照nginx的框架来写插件的话,那
ngx_pool_t就是这些的入口。先来看看ngx_pool_t的定义(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;
};
- 首先是第一个结构体ngx_pool_data_t,这个结构体用来指示当前的内存哪块可用。其定义为:
struct ngx_pool_data_t{
u_char *last;//可用内存区的首地址
u_char *end;//可用内存区的末地址
ngx_pool_t *next;//指向下一个内存区pool
ngx_uint_t failed;//申请内存时出现失败的次数
};
这里有一个需要注意的是,next指向的虽是下一个ngx_pool_t结构体,但是在使用时由于内存池的元信息存储只需要存一次,所以在ngx_pool_t构成的链表中除了第一个需存储元信息外,后面的都可以不用存储,所以第一个ngx_pool_t的有效存储空间是在变量log之后,而后面的有效内存区则从d之后。这也就是为什么在源代码中我们看到申请空间返回的地址只是在首地址后加了sizeof(ngx_data_t)个字节。
2. 由于pool申请内存空间时分为大内存区,小内存区。小内存区就是存在由1中结构体标识的内存区,大内存区则由另外一个变量标识,这个等一下再讲。所以就需要一个变量来区分这个,max就是来做这个工作的。大于max的就是存在大内存区,反之存在小内存区。
3. current指向当前ngx_pool_t链表中可申请的节点,判断是否可申请依据的是ngx_pool_data_t中的failed大小,如果申请的失败次数超过4则认为已不可申请(具体为什么是4不清楚,我觉得应该是测试出来的,认为4较合理)
4. chain挂载chain链条,具体使用不知道,后续再补充
5. large指针指向大内存区块的链表
6. cleanup指向由函数指针和数据组成的结构体中,并构成链表
7. log即为日志
最后来张图片总结一下: