提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
apr大部分接口函数内部申请内存和释放内存,都会用到内存池。
一、内存池接口简介
1、初始化
/**
* Setup all of the internal structures required to use pools
* @remark Programs do NOT need to call this directly. APR will call this
* automatically from apr_initialize.
* @internal
*/
APR_DECLARE(apr_status_t) apr_pool_initialize(void);
apr_pool_initialize是内存池总的初始化接口,但在apr_initialize中会调用apr_pool_initialize,所以无需显示的再调用。
2、创建内存池
/**
* Create a new pool.
* @param newpool The pool we have just created.
* @param parent The parent pool. If this is NULL, the new pool is a root
* pool. If it is non-NULL, the new pool will inherit all
* of its parent pool's attributes, except the apr_pool_t will
* be a sub-pool.
* @remark This function is thread-safe, in the sense that multiple threads
* can safely create subpools of the same parent pool concurrently.
* Similarly, a subpool can be created by one thread at the same
* time that another thread accesses the parent pool.
*/
APR_DECLARE(apr_status_t) apr_pool_create(apr_pool_t **newpool,
apr_pool_t *parent);
创建内存池可以指定父内存池。
3、使用内存池分配内存
/**
* Allocate a block of memory from a pool and set all of the memory to 0
* @param p The pool to allocate from
* @param size The amount of memory to allocate
* @return The allocated memory
*/
#if defined(DOXYGEN)
APR_DECLARE(void *) apr_pcalloc(apr_pool_t *p, apr_size_t size);
#elif !APR_POOL_DEBUG
#define apr_pcalloc(p, size) memset(apr_palloc(p, size), 0, size)
#endif
apr_pcalloc和c标准库的calloc类似,它内部分自动给分配的内存块赋值为0。
4、释放内存和销毁内存池
从内存池分配的内存不需要释放,在释放内存池的时候会自动释放。
/**
* Destroy the pool. This takes similar action as apr_pool_clear() and then
* frees all the memory.
* @param p The pool to destroy
* @remark This will actually free the memory
*/
APR_DECLARE(void) apr_pool_destroy(apr_pool_t *p) __attribute__((nonnull(1)));
二、调用示例
#include "apr_pools.h"
void pool_alloc_test()
{
apr_pool_t* pool = NULL;
apr_pool_create(&pool, NULL);
char* p = (char*)apr_palloc(pool, 20);
strcpy(p, "hello apr");
printf("%s\n", p);
apr_pool_destroy(pool);
}
int main()
{
apr_status_t rv = apr_initialize();
if (rv != APR_SUCCESS) {
aprerr("apr_initialize()", rv);
}
atexit(apr_terminate);
pool_alloc_test();
getchar();
return 0;
}
输出:
hello apr
三、注意
- apr pool分配有会话的概念,在一个会话内创建内存池,并申请内存,会话结束释放内存;
- apr_pool_destroy并不会真的释放内存(通常说的释放内存应该是把内存归还给操作系统),而是将内存归还给apr pool的内存分配单元,因此调用apr_pool_destroy后程序的内存并没有减少;当调用apr_pool_destroy之后,再次用apr_palloc分配内存是从之前释放的内存中申请,此时内存大小也不会重新增加。
apr_pool_initialize();
apr_pool_t* pool = NULL, *child = NULL;
apr_pool_create(&pool, NULL);
{
//apr pool分配有会话的概念,在一个会话内创建内存池,并申请内存,会话结束释放内存
apr_pool_create(&child, pool);
apr_palloc(child, 1024 * 1024 * 100); //申请内存100MB
apr_pool_destroy(child); //将child内存池释放归还给分配单元 (内存并未归还给系统,程序占用还是100MB)
}
apr_palloc(pool, 1024 * 1024 * 100); //申请内存100MB (总内存还是100MB)
apr_palloc(pool, 1024 * 1024 * 100); //申请内存100MB (总内存200MB)
apr_pool_destroy(pool); //释放内存,归还给分配单元
apr_pool_terminate(); //释放内存,归还内存给系统
总结
以上就是对libapr的内存池的简单介绍,主要包括内存池的初始化、创建、分配内存和销毁,主要是捡主要的介绍了一些,对其他用法,如apr_pool_core_create、apr_pool_clear等没作细致研究。