源码mempool.h|c sf_sdlist_types.h
内存池涉及几个动作 :初始化、分配、释放、销毁、清空
底层使用两个链表实现内存的分配used_list与释放回收free_list
int mempool_init(MemPool *mempool, PoolCount num_objects, size_t obj_size);
int mempool_destroy(MemPool *mempool);
MemBucket *mempool_alloc(MemPool *mempool);
void mempool_free(MemPool *mempool, MemBucket *obj);
int mempool_clean(MemPool *mempool);
数据结构
typedef unsigned int PoolCount;
typedef struct _MemBucket
{
/* 链表元素节点*/
SDListItem *key;
int used;
/* 用于存储datapool中单个元素的指针*/
void *data;
} MemBucket;
typedef struct _MemPool
{
/* 分配的连续内存空间*/
void **datapool; /* memory buffer for MemBucket->data */
/* 桶数组 */
MemBucket *bucketpool; /* memory buffer */
/* 链表节点数组*/
SDListItem *listpool; /* list of things to use for memory bufs */
PoolCount total;
/* 这两个链表使用sf_sdlist_append 将listpool、bucketpool、datapool结合起来*/
/* 剩余多少*/
sfSDList free_list;
/* 使用多少 */
sfSDList used_list;
/* 元素大小*/
size_t obj_size;
} MemPool;
snort的链表是一个双向链表,有时间在后面的博客会继续分析。
/* Function: int mempool_init(MemPool *mempool,
* PoolCount num_objects, size_t obj_size)
*
* Purpose: initialize a mempool object and allocate memory for it
* Args: mempool - pointer to a MemPool struct
* num_objects - number of items in this pool
* obj_size - size of the items
*
* Returns: 0 on success, 1 on failure
*/
int mempool_init(MemPool *mempool, PoolCount num_objects, size_t obj_size)
{
PoolCount i;
if(mempool == NULL)
return 1;
if(num_objects < 1)
return 1;
if(obj_size < 1)
return 1;
/* 单个元素的大小*/
mempool->obj_size = obj_size;
/* this is the basis pool that represents all the *data pointers
in the list */
/* 分配一块连续的空间,供内存池进行分配操作*/
mempool->datapool = calloc(num_objects, obj_size);
if(mempool->datapool == NULL)
return 1;
/* 分配对应num_objects个链表节点, 为后面构建两个分配和回收链表使用*/
mempool->listpool = calloc(num_objects, sizeof(SDListItem));
if(mempool->listpool == NULL)
{
/* well, that sucked, lets clean up */
ErrorMessage("%s(%d) mempool_init(): listpool is null\n",
__FILE__, __LINE__);
mempool_free_pools(mempool);
return 1;
}
/* 每一个元素使用MemBucket进行封装管理, 一样分配num_objects个*/
mempool->bucketpool = calloc(num_objects, sizeof(MemBucket));
if(mempool->bucketpool == NULL)
{
ErrorMessage("%s(%d) mempool_init(): bucketpool is null\n",
__FILE__, __LINE__);
mempool_free_pools(mempool);
return 1;
}
/* 初始化这两个内存管理链表*/
/* sets up the 2 memory lists */
if(sf_sdlist_init(&mempool->used_list, NULL))
{
ErrorMessage("%s(%d) mempool_init(): Failed to initialize used list\n",
__FILE__, __LINE__);
mempool_free_pools(mempool);
return 1;
}
if(sf_sdlist_init(&mempool->free_list, NULL))
{
ErrorMessage("%s(%d) mempool_init(): Failed to initialize free list\n",
__FILE__, __LINE__);
mempool_free_pools(mempool);
return 1;
}
/* 循环处理, 将被分割的内存使用bucket封装, 最后将bucket 放到链表节点SDListItem的data中加入到free_list的链表尾部*/
for(i=0; i<num_objects; i++)
{
SDListItem *itemp;
MemBucket *bp;
bp = &mempool->bucketpool[i];
itemp = &mempool->listpool[i];
/* each bucket knows where it resides in the list */
bp->key = itemp;
#ifdef TEST_MEMPOOL
printf("listpool: %p itemp: %p diff: %u\n",
mempool->listpool, itemp,
(((char *) itemp) - ((char *) mempool->listpool)));
#endif
/* 对连续内存进行切割使用*/
bp->data = ((char *) mempool->datapool) + (i * mempool->obj_size);
#ifdef TEST_MEMPOOL
printf("datapool: %p bp.data: %p diff: %u\n",
mempool->datapool,
mempool->datapool + (i * mempool->obj_size),
(((char *) bp->data) - ((char *) mempool->datapool)));
#endif
/* 添加到free_list的尾部*/
if(sf_sdlist_append(&mempool->free_list,
&mempool->bucketpool[i],
&mempool->listpool[i]))
{
ErrorMessage("%s(%d) mempool_init(): Failed to add to free list\n",
__FILE__, __LINE__);
mempool_free_pools(mempool);
return 1;
}
mempool->total++;
}
return 0;
}
内存分配动作
/* Function: MemBucket *mempool_alloc(MemPool *mempool);
*
* Purpose: allocate a new object from the mempool
* Args: mempool - pointer to a MemPool struct
*
* Returns: a pointer to the mempool object on success, NULL on failure
*/
MemBucket *mempool_alloc(MemPool *mempool)
{
SDListItem *li = NULL;
MemBucket *b;
if(mempool == NULL)
{
return NULL;
}
/* get one item off the free_list,
put one item on the usedlist
*/
/* 从回收链表free_list中拿掉一个节点*/
li = mempool->free_list.head;
if((li == NULL) || sf_sdlist_remove(&mempool->free_list, li))
{
#ifdef TEST_MEMPOOL
printf("Failure on sf_sdlist_remove\n");
#endif
return NULL;
}
/* 将从free_list中拿掉的节点加入used_list中, 进行管理,表明这个节点已使用*/
if(sf_sdlist_append(&mempool->used_list, li->data, li))
{
#ifdef TEST_MEMPOOL
printf("Failure on sf_sdlist_append\n");
#endif
return NULL;
}
/* 返回bucket指针, 将初始化的时候那块连续的内存的某一个对象的内存clean*/
/* TBD -- make configurable */
b = li->data;
bzero(b->data, mempool->obj_size);
return b;
}
内存回收动作:
/*
* 将要释放的对象从used_list中删除,然后添加到free_list中
*/
void mempool_free(MemPool *mempool, MemBucket *obj)
{
if ((mempool == NULL) || (obj == NULL))
return;
if(sf_sdlist_remove(&mempool->used_list, obj->key))
{
#ifdef TEST_MEMPOOL
printf("failure on remove from used_list");
#endif
return;
}
/* put the address of the membucket back in the list */
if(sf_sdlist_append(&mempool->free_list, obj, obj->key))
{
#ifdef TEST_MEMPOOL
printf("failure on add to free_list");
#endif
return;
}
return;
}
内存的分配和释放,都是通过链表的插入删除,时间复杂度o(1)。由于snort使用的单进程单线程架构,不涉及到多线程操作,无需加锁。