本文共 5876 字,大约阅读时间需要 19 分钟。
源码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; ibucketpool[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使用的单进程单线程架构,不涉及到多线程操作,无需加锁。
转载地址:http://mvtmd.baihongyu.com/