nginx内存池(外部资源释放和内存池销毁)
举个例子
相当于我们开辟了一大块内存,
p指针指向一块堆内存的数据空间:
相当于是C++对象的成员变量占用外部的资源:
free只是把大块内存释放了,这个内存里的成员变量可能占用着外部资源,怎么释放???在释放大块内存之前,先执行一个函数,预置资源释放的函数,
在释放大块内存之前,把其他该释放的先释放。
因为这个内存池是C语言写的,需要预置回调函数。如果是C++,会有析构函数。
cleanup的作用
我们来看,cleanup_s相当于大块内存的内存头信息,把释放资源的回调都组织起来在一个结构体里面。第一个成员变量就是函数指针,保存预先设置的回调函数。第二个成员变量是预置回调函数在释放的资源的地址。
第三个成员变量是next,相当于链表串起来(可能有很多释放资源的操作)。
注意:这些头部信息都是直接分配在小块内存的内存池上的。
我们来看看函数实现:
外部资源释放
参数:内存池的入口,data存储的数据的大小
我们从头开始看下去:首先开辟 包含清理操作的头部信息(在小块内存上开辟的)
然后执行:
回调函数可以传参或者不传参,资源释放函数如果传参的话,size要给个大于0的数字,具体传多大,如果不需要参数,就size填0。然后执行
hanlder先置为空,因为还没有具体的handler
把清除函数的头部信息串在cleanup链表中
然后返回创建的头信息的起始地址c。假如说我们提供了这么一个函数:
调用函数顺序如下:
预置了回调,把回调函数需要的参数传进去,赋值
data记录的是外部资源的地址,为了传给release函数的。
内存池销毁操作
for循环,如果handler不为空,直接调用下面的方法:
不能释放小块内存池,因为一旦释放小块内存池,大块内存池的内存头和清除操作的内存头就没了。所以释放的顺序是:
先执行内存清理操作(预置的回调操作handler,内存外部的资源的清理)
然后遍历large链表:
这个是调试信息。然后遍历large链表,释放大块内存
然后执行第三步
遍历小块内存池,一个一个遍历,全部free掉。
整个内存池就全部清空了!!!