当内存池中的内存不再需要时,或者当需要重用内存池时,可以使用
ngx_reset_pool
函数来清理和重置内存池,以便后续再次使用。
ngx_reset_pool函数
主要作用是将内存池恢复到初始状态,释放已经分配但尚未使用的内存块,并重置内存池的内部状态信息。这样,当再次需要分配内存时,内存池可以从一个干净、一致的状态开始。
在Nginx的源码中,ngx_reset_pool 函数的实现通常涉及以下几个关键步骤:
-
清理已分配的内存块:遍历内存池中的小内存块列表并释放。
-
重置内部状态信息:将内存池的内部状态信息重置为初始状态。这包括重置内存池的指针、计数器、标志位等,确保内存池处于一个干净、一致的状态。这样,在下次使用内存池时,可以正确地进行内存分配和管理。
-
保持必要的配置信息:虽然ngx_reset_pool 函数用于重置内存池的状态,但它通常会保留一些必要的配置信息,如内存池的大小、分配策略等。这些信息在重置过程中不会被改变,以确保在后续的内存分配中能够按照预期进行。
需要注意的是,ngx_reset_pool 函数并不会释放整个内存池所占用的内存空间,只会释放大块内存的空间。它只是清理和重置内存池的内部状态,以便再次使用。如果需要彻底释放内存池所占用的内存空间,通常需要通过其他机制(如调用内存池销毁函数)来实现。
// 小块内存没有free函数,只能重置
void
ngx_reset_pool(ngx_pool_t *pool)
{
ngx_pool_t *p;
ngx_pool_large_t *l;
for (l = pool->large; l; l = l->next) { // 重置大块内存
if (l->alloc) {
// 释放内存但是没有指针置空,保留了存放在小内存块中的头信息节点
// 头信息节点将在下面小内存空间中被重置
ngx_free(l->alloc);
}
}
// 重置小块内存
// 头信息ngx_pool_s 只有第一块有 -- 块信息ngx_pool_data_t 是每个块都有
// 原本的原代码如下注释中
// 有缺陷,这样会使得除首块(含头信息)的每个块都浪费了ngx_pool_s-ngx_pool_data_t 大小的空间
/*for (p = pool; p; p = p->d.next) { // 遍历小块内存
p->d.last = (u_char *) p + sizeof(ngx_pool_t); // 每个块都指向除头信息和块信息之外的内存的首地址
p->d.failed = 0;
}*/
/// 修改
if(p){ // 第一块(有头信息)指向除头信息ngx_pool_s和块信息ngx_pool_data_t 之外的内存的首地址
p->d.last = (u_char *) p + sizeof(ngx_pool_t);
p->d.failed = 0;
// 第一块之后的每个块(无头信息)都指向除块信息ngx_pool_data_t 之外的内存的首地址
for(p = p->d.next; p; p = p->d.next){
p->d.last = (u_char *) p + sizeof(ngx_pool_data_t);
p->d.failed = 0;
}
}
/// 修改
pool->current = pool; // 重置头信息
pool->chain = NULL;
pool->large = NULL; // 完全舍弃已经释放的大内存
}