nginx内存池(外部资源释放和内存池销毁)

nginx内存持续增长_成员变量


nginx内存持续增长_nginx_02


nginx内存持续增长_nginx内存持续增长_03


nginx内存持续增长_成员变量_04


nginx内存持续增长_nginx内存持续增长_05

举个例子

nginx内存持续增长_nginx内存持续增长_06


相当于我们开辟了一大块内存,

nginx内存持续增长_成员变量_07


p指针指向一块堆内存的数据空间:

nginx内存持续增长_回调函数_08


相当于是C++对象的成员变量占用外部的资源:

nginx内存持续增长_成员变量_09


free只是把大块内存释放了,这个内存里的成员变量可能占用着外部资源,怎么释放???在释放大块内存之前,先执行一个函数,预置资源释放的函数

在释放大块内存之前,把其他该释放的先释放。

因为这个内存池是C语言写的,需要预置回调函数。如果是C++,会有析构函数。

nginx内存持续增长_nginx内存持续增长_10

cleanup的作用

nginx内存持续增长_成员变量_11


nginx内存持续增长_nginx内存持续增长_12


我们来看,cleanup_s相当于大块内存的内存头信息,把释放资源的回调都组织起来在一个结构体里面。第一个成员变量就是函数指针,保存预先设置的回调函数。第二个成员变量是预置回调函数在释放的资源的地址。
第三个成员变量是next,相当于链表串起来(可能有很多释放资源的操作)。

nginx内存持续增长_成员变量_13


nginx内存持续增长_回调函数_14


注意:这些头部信息都是直接分配在小块内存的内存池上的。

我们来看看函数实现:

外部资源释放

nginx内存持续增长_链表_15


参数:内存池的入口,data存储的数据的大小

我们从头开始看下去:首先开辟 包含清理操作的头部信息(在小块内存上开辟的)

nginx内存持续增长_链表_16


然后执行:

nginx内存持续增长_成员变量_17


回调函数可以传参或者不传参,资源释放函数如果传参的话,size要给个大于0的数字,具体传多大,如果不需要参数,就size填0。然后执行

hanlder先置为空,因为还没有具体的handler

nginx内存持续增长_成员变量_18


把清除函数的头部信息串在cleanup链表中

nginx内存持续增长_nginx_19


然后返回创建的头信息的起始地址c。假如说我们提供了这么一个函数:

nginx内存持续增长_成员变量_20


调用函数顺序如下:

nginx内存持续增长_回调函数_21


预置了回调,把回调函数需要的参数传进去,赋值

data记录的是外部资源的地址,为了传给release函数的。

nginx内存持续增长_nginx内存持续增长_22

内存池销毁操作

nginx内存持续增长_nginx内存持续增长_23


for循环,如果handler不为空,直接调用下面的方法:

nginx内存持续增长_成员变量_24


不能释放小块内存池,因为一旦释放小块内存池,大块内存池的内存头和清除操作的内存头就没了。所以释放的顺序是:

先执行内存清理操作(预置的回调操作handler,内存外部的资源的清理)

然后遍历large链表:

nginx内存持续增长_nginx_25


这个是调试信息。然后遍历large链表,释放大块内存

nginx内存持续增长_回调函数_26

然后执行第三步
遍历小块内存池,一个一个遍历,全部free掉。

nginx内存持续增长_nginx内存持续增长_27


整个内存池就全部清空了!!!