-
内存池的逻辑结构:
-
-
链表1:多个分配模块,通过ngx_pool_data_t结构中的next成员,构成链表,形成内存池。
-
链表2:ngx_pool_large_t结构中的next成员,形成大数据内存块分配的链表。挂接在第一个分配模块上。
-
链表3:ngx_pool_cleanup_t结构中的next成员,形成内存回收链表。同样挂接第一个分配模块上。
-
-
内存池的管理:
-
相关源码位于:src/core/ngx_palloc.c文件中。
-
创建内存池:
-
按优先级选用如下三个系统调用,用于分配模块内存:
-
posix_memalign(): 考虑数据对齐。
-
memalign(): 考虑数据对齐。
-
malloc(): 不考虑数据对齐。
-
-
ngx_pool_t结构中的max成员:
-
含义:表示该分配模块可用于分配的最大内存。
-
源码疑问1:
-
源码:p->max = (size < NGX_MAX_ALLOC_FROM_POOL) ? size : NGX_MAX_ALLOC_FROM_POOL;
-
疑问:p->max的值应该为分配模块的大小size减去ngx_pool_t结构的大小。???
-
-
-
示例:
-
源码:init_cycle.pool = ngx_pool_create(1024, log); // 假设内存起始地址从10开始。
-
-
-
-
销毁内存池:
-
处理过程:
-
遍历ngx_pool_cleanup_t链表,调用各个节点的回调函数,进行数据清除操作。
-
遍历ngx_pool_large_t链表,释放各个节点上挂接的内存。
-
遍历ngx_pool_t链表,释放各个分配模块。
-
-
从处理过程中可以看出,ngx_pool_cleanup_t链表和ngx_pool_large_t链表只在第一个ngx_pool_t结构中存在。???
-
-
重置内存池:
-
处理过程:
-
遍历ngx_pool_large_t链表,释放各个节点上挂接的内存。
-
遍历ngx_pool_t链表,将各个分配模块的last指针重置到刚分配时的位置。
-
-
-
-
内存的使用:
-
申请内存:
-
Nginx内存池中申请内存的函数有3个:ngx_palloc(), ngx_pnalloc()和ngx_calloc()。
-
ngx_palloc()源码分析:
-
如果申请的内存大小size小于等于pool->max,则ngx_palloc_small()分配内存:
-
在当前分配模块pool中,判断pool->d.last + size是否小于pool->d.end,如果小于则在该分配模块分配内存,否则通过pool->d.next,在下一个分配模块中申请内存。
-
如果ngx_pool_t链表中没有剩余内存可供分配,则使用ngx_palloc_block()在系统内存中申请新的分配模块:
-
在系统内存中申请新的分配模块ngx_pool_t,并进行初始化。
-
在分配模块上分配所需的内存大小。
-
将新的分配模块,添加到ngx_pool_t链表上:
-
注意:ngx_pool_t结构中的current指针成员是会移动的。
-
pool->current指向ngx_pool_t链表的某个节点,该节点是所有链表节点中ngx_pool_data_t结构中failed成员最后一个小于等于4的节点。
-
将新的分配模块添加到ngx_pool_t链表的末尾。
-
-
-
-
否则使用ngx_palloc_large()申请大数据块内存。
-
使用ngx_alloc(实际使用了系统调用malloc),申请大数据块内存。
-
遍历ngx_pool_large_t链表,将新申请的内存挂接在合适的节点上。
-
如果没有合适的节点,则创建新的ngx_pool_large_t结构来挂接大数据块内存,并将新创建的结构插入到ngx_pool_large_t链表开头。
-
-
-
ngx_pnalloc()源码分析:
-
与ngx_palloc()功能基本相同,只是在分配内存时,没有考虑数据对齐的问题。
-
-
ngx_pcalloc()源码分析:
-
与ngx_palloc()功能基本相同,只是在分配内存后,将内存中的数据清零。
-
-
ngx_calloc()源码分析:
-
位于:src/os/unix/ngx_alloc.c文件中。
-
功能:从系统内存(而非内存池中分配内存)中分配内存,并初始化。
-
-
-
释放内存:
-
源码:#define ngx_free free
-
说明:大数据块内存交由ngx_free()进行释放,其他内存交由内存池的销毁过程。
-
-
回收内存:
-
原因:某些数据类型在回收其所占用的内存空间时,在释放内存空间前,还需要进行指定的清理操作。
-
处理:清理函数和待清理的数据,分别存储在ngx_pool_cleanup_s结构的handle和data成员中。
-
-
-
总结:
-
在内存池链表上通过ngx_palloc()申请的内存,不能被单独释放。
-
内存池链表是随着内存申请而逐渐增加的。
-
内存池链表只能整体释放或重置。
-