STL中nginx内存池

                         STL中nginx内存池


相关文章:

https://wenku.baidu.com/view/a13f31751ed9ad51f01df218.html
https://blog.csdn.net/bossxu_linuxer/article/details/55657284

******nginx物理结构
|last|end|next|fail|  max|current|chain|large|cleanup|log|已分配内存|未分配内存
1.整体正如同目录nginx图片,只有nginx_pool头部这个内存池节点存在除了ngx_pool_data_t以外的
各个其他成员,因此我们可以理解为nginx_pool的大小max,大块数据链表头部large,特殊释
放处理的链表头部cleanup,我们日志输出文件地址log  这些都只能从我们的头部节点查询获得
因此我们这些信息都在源码中有体现  pool(头部节点指针)->?。
2.
max使我们内存池能够分配的最大存储空间(减去头部长度剩余的),内存池create时候就不变的。
我们nginx的三个链表,承上我们的nginx_pool节点形成内存池链表由next作为连接。
last,end分别指向可以开始分配小内存(size<max)的地址和该内存池节点最后一个地址。
fail是我们分配节点失败的次数之后的ngx_palloc中的ngx_palloc_block会用到。(从概率角度说当
我们会用ngx_palloc_block增加节点就说明之前的节点地址不够用的可能性很大,统计超过某个次数的
节点不在用它分配)
crrent指向我们下一个可分配内存的节点首地址,在ngx_palloc_block中使用。
large 是结构体ngx_pool_large_t结构体 成员:next(下一个大块内存),data(大块内存地址)这个
节点的空间在我们内存池上开辟,而data是系统malloc的地址。
cleanup是我们ngx_pool_cleanup_t结构体 成员:handler next data  这个成员标注了需要特别要求的
释放空间,比如我们在内存池里面开辟了一个空间给用户,用户不用了要free的时候有指定的处理函数
那么这个函数指针就放在handler里data就是这个空间地址next就是下一个需要这种处理函数的地址。
log就是日志目录地址


*******nginx操作函数
*ngx_create_pool(size,log)
开辟一个内存池,size是内存池大小必须小于4k-1,log就是日志地址。
current这时候是这个节点自己,其他可以通过这些节点的意义推得。
*ngx_destroy_pool(addr)
这个是销毁内存池,他会把cleanup和large先释放在释放自己
ngx_reset_pool(addr)
这个是重置内存池函数,
释放large cleanup,并将last等初始化其他开辟了的内存池节点不归还。
*向ngx申请空间函数
ngx_palloc(根据NGX_ALIGNMENT对齐)
ngx_pnalloc(不考虑内存对齐)
ngx_pcalloc(调用palloc,0初始化操作)
ngx_pmemalign(将这个内存申请的size不管多大都内存对齐放在large下)
*ngx_palloc阐述(p内存池指针)
当我们申请空间大于p->max我们直接调用malloc解决,否则我们遍历内存池节点寻找能够开辟空间的
节点,如果失败该节点fail+1在走下一个节点,当没有节点可以开辟调用ngx_palloc_block函数,
这个函数就是先开辟一个新的节点然后把新节点插入内存池尾部,从头寻找fail<=4的第一个节点
将p->current指向第一个满足条件的节点。这意味着我们以后不再去访问我们失败次数大于4的
节点去索要内存,大概率下它分配不出内存空间了。
*ngx_pfree
这个函数对large上的真的释放,小块内存不做处理,最后的destroy同一处理。


*******
这些节点大小相同对齐不容易产生内存碎片。并且不用频繁陷入内核与操作系统交互。
nginx只提供给了用户申请内存的接口,却没有释放内存的接口,那么nginx是如何完成内存释放的呢?总不能一直申请,
用不释放啊。针对这个问题,nginx利用了web server应用的特殊场景来完成;
    一个web server总是不停的接受connection和request,所以nginx就将内存池分了不同的等级,有进程级的内存池、
connection级的内存池、request级的内存池。也就是说,创建好一个worker进程的时候,同时为这个worker进程创建一
个内存池,待有新的连接到来后,就在worker进程的内存池上为该连接创建起一个内存池;连接上到来一个request后,
又在连接的内存池上为request创建起一个内存池。
    这样,在request被处理完后,就会释放request的整个内存池,连接断开后,就会释放连接的内存池。因而,就保证
了内存有分配也有释放。
小结:通过内存的分配和释放可以看出,nginx只是将小块内存的申请聚集到一起申请,然后一起释放。避免了频繁申
请小内存,降低内存碎片的产生等问题。

猜你喜欢

转载自blog.csdn.net/qq_41784469/article/details/80752218