1.sofia-sip库的内存管理
home-based 内存管理机制,在需要分配许多内存块的情况下非常有用。分配器是通过分配中心保存各个分配内存块的引用来实现的。当分配中心释放,所有它保持引用的内存块都会被释放。
为一个给定任务分配大量的内存块时基于home的内存管理将非常高效。分配将通过home内存来执行,home内存保留着每个分配内存块的地址。当home内存被释放时,它也将释放那些它跟踪的内存块。这大大简化了应用代码逻辑,不再需要维护每块分配的内存空间,不需要保留他们的地址也不再需要一个个单独释放。
核心代码剖析
核心数据结构
/** Memory home structure */
struct su_home_s {
int suh_size;
su_block_t *suh_blocks;
su_alock_t *suh_lock;
};
struct su_block_s {
su_home_t *sub_parent; /**< Parent home */
char *sub_preload; /**< Preload area */
su_home_stat_t *sub_stats; /**< Statistics.. */
void (*sub_destructor)(void *); /**< Destructor function */
size_t sub_ref; /**< Reference count */
#define REF_MAX SIZE_MAX
size_t sub_used; /**< Number of blocks allocated */
size_t sub_n; /**< Size of hash table */
unsigned sub_prsize:16; /**< Preload size */
unsigned sub_prused:16; /**< Used from preload */
unsigned sub_hauto:1; /**< "Home" is not from malloc */
unsigned sub_auto:1; /**< struct su_block_s is not from malloc */
unsigned sub_preauto:1; /**< Preload is not from malloc */
unsigned sub_auto_all:1; /**< Everything is from stack! */
unsigned :0;
su_alloc_t sub_nodes[SUB_N]; /**< Pointers to data/lower blocks */
};
typedef struct {
unsigned sua_size:SIZEBITS; /**< Size of the block */
unsigned sua_home:1; /**< Is this another home? */
unsigned :0;
void *sua_data; /**< Data pointer */
} su_alloc_t;
从结构体类型来看,整个Home based memory management包括三个层级。最上层是su_home_s,中间一层是su_block_s,最下那层是su_alloc_t。su_home_s结构体保留一个指向su_block_s结构体的指针,su_block_s包含一个su_alloc_t类型的数组。
使用方法
1、先申明一个包含有su_home_s结构体对象的结构体,类似于这样
struct context { su_home_t ctx_home[1]; other_t *ctx_stuff; ...}
context结构体内第一个就是su_home_s结构体对象。然后context结构体内包含了其他的对象。要求就是必须确保context结构体内第一个对象一定时su_home_s对象。
2、然后就是调用创建函数创建、初始化context结构体对象。
struct context *ctx = su_home_new(sizeof (struct context));
3、接着使用su_zalloc函数处理内存分配事宜。
zeroblock = su_zalloc(ctx->ctx_home, sizeof (*zeroblock));
4、调用su_home_deinit(ctx->ctx_home)释放内存。
2.APR内存池
Apache中的内存分配的基本结构都是资源池,包括线程池,套接字池等等。内存池通常是一块很大的内存空间,一次性被分配成功,然后需要的时候直接去池中取,而不需要重新分配,这样避免的频繁的malloc操作,而且另一方面,即时内存的使用者忘记释放内存或者根本就不想分配,那么这些内存也不会丢失,它们仍然保存在内存池中,当内存池被销毁的时候这些内存将自动的被销毁。
使用方法
1、创建一个内存池。
switch_core_new_memory_pool(&usepool);
2、从内存池中分配。
session = switch_core_alloc(usepool, sizeof(*session));
3、销毁内存池,回收内存。
switch_core_destroy_memory_pool(usepool);
内存回收剖析
在Freeswitch使用apr内存池中,在调用
switch_core_perform_destroy_memory_pool后,并没有马上回收内存,而是放到了memory_manager.pool_queue的队列里面,再由单独的一个线程,从这个队列里面取出指针进行销毁。