APR-内存池

来源:互联网 发布:lnmp yum安装教程 编辑:程序博客网 时间:2024/05/14 08:09

使用内存池第一点削除了内存泄漏的问题,第二点减低在非配内存时带来的损耗

从某种意义上讲,内存池强制你遵循一种面相会话(session-oriented)的方式进行编程,一个内存池是一个种会话上下文环境(session context),这样它使得一组对象拥有同一种生存周期。你可以控制在同意会话的一组对象。你可以在一个会话开始的时候创建一个内存池,然后使用这个内存创建你的对象。你不必关心他们的生存周期,在这个会话结束的时候,你通过销毁这个内存池销毁全部对象。


这里有3个基本的API:

APR_DECLARE(apr_status_t) apr_pool_create(apr_pool_t **newpool, apr_pool_t *parent);
APR_DECLARE(void *) apr_palloc(apr_pool_t *p, apr_size_t size);
APR_DECLARE(void) apr_pool_destroy(apr_pool_t *p);


我们可以通过使用apr_pool_create()创建一个内存池。这个内存池直到我们调用apr_pool_destroy()是才被销毁。apr_pool_create()的第一个参数是结果参数(result argument)是一个新创建的内存池对象(apr_pool_t)。我们通过调用apr_palloc(),可以获得一个指定内存大小的内存块


apr_pool_t *mp;

apr_pool_create(&mp, NULL);

char *buf1;
buf1 = apr_palloc(mp, MEM_ALLOC_SIZE);//apr_pcalloc()返回一个已被清零的内存块


你可以使用apr_palloc()获得一个无限制的内存块,不过这并不是一个获得一个大容量内存池的好方法。内存池原本为小内存快而设计的,事实上一个内存池的初始化大小只有8k,如果你需要一个很大的内存块,比如需要一个几M字节的内存,你就不应该考虑使用内存池了

备注:在默认的情况下,通过内存池分配的内存是不会自动的返还给操作系统的。如果一个程序运行了很长时间,这他会出现一些问题,我推荐你在使用内存池的时候指定他的上限,代码如下:

#define YOUR_POOL_MAX_FREE_SIZE 32      /* apr_pool max free list size */
apr_pool_t *mp;
apr_pool_create(&mp, NULL);
apr_allocator_t* pa = apr_pool_allocator_get(mp);
if (pa) {
    apr_allocator_max_free_set(pa, YOUR_POOL_MAX_FREE_SIZE);
}


一个是apr_pool_clear(),另一个是apr_pool_cleanup_register()。apr_pool_clear()和apr_pool_destroy()类似,但是使用它后这个内存是可以复用的

apr_pool_t *mp;
apr_pool_create(&mp, NULL);
for (i = 0; i < n; ++i) {
    do_operation(..., mp);
    apr_pool_clear(mp);
}

apr_pool_destroy(mp);

这个内存池在do_operation()中被使用,在这里一些内存块被分配出来,如果在do_operation()之外你不需要这些内存,你可以调用apr_pool_clear(),这样你就可以减少内存使用数量

最后一个议题是关于内存池子池的问题(sub pool),每一个内存池可以有一个父内存池。因此内存池可以构建成一个树形结构(tree),apr_pool_create()的第二个参数就是父内存池,当你使用NULL作为父内存池的时候,新创建的内存池将被编程根内存池,你可以在这个内存池下创建字内存池。当你在一个树形内存池中使用apr_pool_destroy()的时候,这个内存池的子内存池也会被销毁。当你调用apr_pool_clear()的时候,当前的内存池仍然可用,但是他的子内存池被销毁。只要子内存池被销毁上一级的清理函数将会被调用。


当你相传递一个NULL作为清理的回调函数时,你必须使用apr_pool_cleanup_null代替NULL,不然会引起bug

/* apr_pool_cleanup_register(mp, ANY_CONTEXT_OF_YOUR_CODE, ANY_CALLBACK_OF_YOUR_CODE, NULL); THIS IS A BUG */

apr_pool_cleanup_register(mp, ANY_CONTEXT_OF_YOUR_CODE, ANY_CALLBACK_OF_YOUR_CODE, apr_pool_cleanup_null);


原创粉丝点击