内存池
2015-06-18 17:46
253 查看
二,实现
1,内存池的相关信息结构体
点击(此处)折叠或打开
struct pool_head {
void **free_list;
struct list_head list; /* list of all known pools */
int32_t used; /* how many chunks are currently in use */
int32_t allocated; /* how many chunks have been
allocated */
int32_t limit; /* hard limit on the
number of chunks */
int32_t minavail; /* how many chunks are expected to be
used */
int32_t size; /* chunk size */
int32_t flags; /* MEM_F_* */
int32_t users; /* number of pools sharing
this zone */
int8_t name[12]; /* name
of the pool */
};
2,具体实现
a,头文件(pools.h)
点击(此处)折叠或打开
#ifndef __POOLS_H__
#define __POOLS_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Define to prevent recursive inclusion
-------------------------------------*/
#include "types.h"
#include "list.h"
#define MEM_F_SHARED 0x1 /* 标示对应的池允许共用 */
/* 每个池的相关信息 */
struct pool_head {
void **free_list;
struct list_head list; /* list of all known pools */
int32_t used; /* how many chunks are currently in use */
int32_t allocated; /* how many chunks have been
allocated */
int32_t limit; /* hard limit on the
number of chunks */
int32_t minavail; /* how many chunks are expected to be
used */
int32_t size; /* chunk size */
int32_t flags; /* MEM_F_* */
int32_t users; /* number of pools sharing
this zone */
int8_t name[12]; /* name
of the pool */
};
/* 池创建 */
/* Try to find an existing shared pool with the same characteristics and
* returns it, otherwise creates this one. NULL is returned if no
memory
* is available for a new creation.
*/
extern struct pool_head * pool_create(char *name, uint32_t
size, uint32_t flags);
/* 池销毁 */
/*
* This function destroys a pool by freeing it completely, unless it's
still
* in use. This should be called only under extreme circumstances. It
always
* returns NULL if the resulting pool is empty, easing
the clearing of the old
* pointer, otherwise it returns the pool.
* .
*/
extern void* pool_destroy(struct pool_head *pool);
/* 把池中的空闲的元素都给释放掉 */
/*
* This function frees whatever can be freed in pool <pool>.
*/
extern void pool_clear(struct pool_head *pool);
/* 把池中非必要的元素给释放掉 */
/*
* This function frees whatever can be freed in all pools, but
respecting
* the minimum thresholds imposed by owners. It takes care of avoiding
* recursion because it may be called from a signal handler.
*/
extern void pool_flush_nonessential(void);
/* 动态分配一个 pool 元素大小的内存空间 */
/* Allocate a new entry for pool <pool>, and return
it for immediate use.
* NULL is returned if no
memory is available for a new creation.
*/
extern void * pool_refill_alloc(struct pool_head *pool);
/*
* Returns a pointer to type <type> taken
from the
* pool <pool_type> or dynamically
allocated. In the
* first case, <pool_type> is updated to point to the
* next element in the
list.
*/
#define pool_alloc(pool) \
({ \
void *__p; \
if ((__p = (pool)->free_list) == NULL) \
__p = pool_refill_alloc(pool); \
else { \
(pool)->free_list = *(void **)(pool)->free_list;\
(pool)->used++; \
} \
__p; \
})
/*
* Puts a memory area back to the corresponding pool.
* Items are chained directly through a pointer that
* is written in the beginning of the memory area, so
* there's no need for any carrier cell. This
implies
* that each memory area is at least as big as one
* pointer. Just like with the libc's free(), nothing
* is done if <ptr> is NULL.
*/
#define pool_free(pool, ptr) \
({ \
if ((ptr) != NULL) { \
*(void **)(ptr) = (void *)(pool)->free_list; \
(pool)->free_list = (void *)(ptr); \
(pool)->used--; \
} \
})
#ifdef __cplusplus
}
#endif
#endif
b,c文件(pools.c)
点击(此处)折叠或打开
#include "pools.h"
#include "standard.h"
/* 管理所有池的链表头 */
static struct list_head pools = LIST_HEAD_INIT(pools);
/* 池创建 */
/* Try to find an existing shared pool with the same characteristics and
* returns it, otherwise creates this one. NULL is returned if no
memory
* is available for a new creation.
*/
struct pool_head * pool_create(char *name, uint32_t
size, uint32_t flags)
{
struct pool_head *pool;
struct pool_head *entry;
struct list_head *start;
uint32_t align;
/* We need to store at least a (void *) in the
chunks. Since we know
* that the malloc() function will
never return such a small size,
* let's round the
size up to something slightly bigger, in order to
* ease merging of entries. Note that the rounding is a power of two.
*/
align = 16;
size = (size + align - 1) & -align;
start = &pools;
pool = NULL;
list_for_each_entry(entry, &pools, list) {
if (entry->size == size) {
/* either we can share this place and we take it, or
* we look for a sharable one or for the next position
* before which we will insert a new one.
*/
if (flags & entry->flags & MEM_F_SHARED) {
/* we can share this one */
pool = entry;
break;
}
}
else if (entry->size > size) {
/* insert before this one */
start = &entry->list;
break;
}
}
if (!pool) {
pool = calloc(1, sizeof(*pool));
if (!pool)
return NULL;
if (name)
strlcpy(pool->name, (int8_t*)name, sizeof(pool->name));
pool->size = size;
pool->flags = flags;
list_add_tail(&pool->list,start);
}
pool->users++;
return pool;
}
/* 池销毁 */
void* pool_destroy(struct pool_head *pool)
{
if (pool)
{
pool_clear(pool); // 请看池中的空闲的元素
if (pool->used)
return pool;
pool->users--;
if (!pool->users)
{
list_del(&pool->list); // 从
pools 链表中删除
free(pool); // 把
pool 结构体占用的内存给释放了
}
}
return NULL;
}
/* 把池中的空闲的元素都给释放掉 */
/*
* This function frees whatever can be freed in pool <pool>.
*/
void pool_clear(struct pool_head *pool)
{
void *temp, *next;
if (!pool)
return;
next = pool->free_list;
while (next) {
temp = next;
next = *(void **)temp;
pool->allocated--;
free(temp);
}
pool->free_list = next;
/* here, we should have pool->allocate == pool->used */
}
/* 把池中非必要的元素给释放掉 */
/*
* This function frees whatever can be freed in all pools, but
respecting
* the minimum thresholds imposed by owners. It takes care of avoiding
* recursion because it may be called from a signal handler.
*/
void pool_flush_nonessential(void)
{
static int recurse;
struct pool_head *entry;
if (recurse++)
goto out;
list_for_each_entry(entry, &pools, list) {
void *temp, *next;
//qfprintf(stderr, "Flushing
pool %s\n", entry->name);
next = entry->free_list;
while (next &&
entry->allocated > entry->minavail &&
entry->allocated > entry->used) {
temp = next;
next = *(void **)temp;
entry->allocated--;
free(temp);
}
entry->free_list = next;
}
out:
recurse--;
}
/* 动态分配一个 pool 元素大小的内存空间 */
/* Allocate a new entry for pool <pool>, and return
it for immediate use.
* NULL is returned if no
memory is available for a new creation. A call
* to the garbage collector is performed before returning NULL.
*/
void *pool_refill_alloc(struct pool_head *pool)
{
void *ret;
if (pool->limit && (pool->allocated >= pool->limit))
return NULL;
ret = calloc(1, pool->size);
if (!ret) {
pool_flush_nonessential();
ret = calloc(1, pool->size);
if (!ret)
return NULL;
}
pool->allocated++;
pool->used++;
return ret;
}
/* 销毁所有的池 */
int32_t dump_pools(void)
{
int32_t ret = OPER_OK;
return ret;
}
c,辅助文件(standard.c)
点击(此处)折叠或打开
/*
* copies at most <size-1> chars
from <src> to <dst>. Last
char is always
* set to 0, unless <size> is 0. The
number of chars copied is returned
* (excluding the terminating zero).
* This code has been optimized for size and speed : on x86, it's
45 bytes
* long, uses only registers, and consumes
only 4 cycles per char.
*/
int32_t strlcpy(int8_t*dst, const int8_t*src, int32_t
size)
{
int8_t *orig = dst;
if (size)
{
while (--size && (*dst = *src))
{
src++; dst++;
}
*dst = 0;
}
return dst - orig;
}
d,辅助文件(types.h)
点击(此处)折叠或打开
#ifndef __TYPES_H__
#define __TYPES_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Define to prevent recursive inclusion
-------------------------------------*/
#include <stdio.h> // 标准输入输出定义
#include <stdlib.h> // 标准函数库定义
#include <string.h>
// memset
#include <unistd.h> // Unix标准函数定义,read,write...
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> // 文件控制定义
#include <termios.h> // POSIX中断控制定义
#include <errno.h> // 错误号定义
#include <pthread.h> // pthread_t,pthread_create...
#include "error.h"
#include "debug.h"
/* 类型定义 */
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef signed short int16_t;
typedef unsigned short uint16_t;
typedef signed int int32_t;
typedef unsigned int uint32_t;
typedef signed long long int64_t;
typedef unsigned long long uint64_t;
#define BUFFER_SIZE 256
/* 1,COM,串口相关*/
#define COM_TYPE_UPPER_DEVICE 1
#define COM_TYPE_LOWER_DEVICE 2
#define COM_BUFFER_SIZE (BUFFER_SIZE)
/* 2,pools,池相关 */
/* 3,命令相关*/
#define CMD_DATA_LEN_MAX (BUFFER_SIZE)
#ifdef __cplusplus
}
#endif
#endif
三,实例
1,头文件(command.h)
点击(此处)折叠或打开
#ifndef __COMMAND_H__
#define __COMMAND_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Define to prevent recursive inclusion
-------------------------------------*/
#include "types.h"
/* 接收到的命令的来源等 */
typedef struct _cmd
{
int32_t fd;
pthread_t id;
void* data;
}cmd_t;
// 创建内存池
extern int32_t cmd_pool_create(void);
// 释放内存池
extern int32_t cmd_pool_destroy(void);
// 申请命令内存块,用以保存命令数据
extern int32_t cmd_alloc(cmd_t **param);
// 释放命令内存块
extern int32_t cmd_free(cmd_t *param);
#ifdef DEBUG_POOL
extern void cmd_pool_info(void);
#endif
#ifdef __cplusplus
}
#endif
#endif
2,c文件(command.c)
点击(此处)折叠或打开
#include "command.h"
#include "pools.h"
static struct pool_head *cmd_head_pool = NULL;
static struct pool_head *cmd_data_pool = NULL;
// 创建内存池
int32_t cmd_pool_create(void)
{
int32_t ret = OPER_OK;
if (cmd_head_pool == NULL)
{
if((cmd_head_pool = pool_create("cmd_head", sizeof(cmd_t), MEM_F_SHARED)) == NULL)
{
ret = -POOL_CREATE_ERROR;
}
else
{
if (cmd_data_pool == NULL)
if((cmd_data_pool = pool_create("cmd_data", CMD_DATA_LEN_MAX, MEM_F_SHARED)) == NULL)
{
cmd_pool_destroy();
ret = -POOL_CREATE_ERROR;
}
}
}
#ifdef DEBUG_POOL
cmd_pool_info();
#endif
return ret;
}
#ifdef DEBUG_POOL
void cmd_pool_info(void)
{
struct pool_head *entry = cmd_head_pool;
printf("pool %s (%d bytes) : %d allocated (%u bytes), %d used\n",entry->name, entry->size, entry->allocated,entry->size * entry->allocated, entry->used);
entry = cmd_data_pool;
printf("pool %s (%d bytes) : %d allocated (%u bytes), %d used\n",entry->name, entry->size, entry->allocated,entry->size * entry->allocated, entry->used);
}
#endif
// 释放内存池
int32_t cmd_pool_destroy(void)
{
int32_t ret = OPER_OK;
#ifdef DEBUG_POOL
cmd_pool_info();
#endif
if(cmd_head_pool != NULL)
{
if(NULL != pool_destroy(cmd_head_pool))
{
ret = -POOL_DESTROY_ERROR;
}
else
{
if(cmd_data_pool != NULL)
if(NULL != pool_destroy(cmd_data_pool))
ret = -POOL_DESTROY_ERROR;
}
}
return ret;
}
// 申请命令内存块,用以保存命令数据
int32_t cmd_alloc(cmd_t **param)
{
int32_t ret = OPER_OK;
if((*param = (cmd_t*)pool_alloc(cmd_head_pool)) == NULL)
{
ret = -CMD_POOL_ALLOC_ERROR;
}
else
{
memset(*param,0,sizeof(cmd_t));
if(((*param)->data = pool_alloc(cmd_data_pool)) == NULL)
{
cmd_free(*param);
ret = -CMD_POOL_ALLOC_ERROR;
}
}
#ifdef DEBUG_POOL
cmd_pool_info();
#endif
return ret;
}
// 释放命令内存块
int32_t cmd_free(cmd_t *param)
{
if(param->data != NULL)
{
pool_free(cmd_data_pool,param->data);
param->data = NULL;
}
if(param != NULL)
{
pool_free(cmd_head_pool,param);
param = NULL;
}
#ifdef DEBUG_POOL
cmd_pool_info();
#endif
return OPER_OK;
}
c,辅助文件(test.c)
点击(此处)折叠或打开
/*
* cmd pool begin
*/
static void cmd_pool_oper(void)
{
int32_t ret = OPER_OK;
printf("command pool test!\n");
if((ret = cmd_pool_create()) != OPER_OK)
{
printf("Create command pool fail!\n");
}
else
{
cmd_t* cmd_buf[5];
int32_t i = 0;
int32_t count = 0;
printf("Create command pool success!!!\n");
memset(cmd_buf,0,sizeof(cmd_buf));
for(i = 0; i < 5; i++)
{
printf(" alloc \n");
if(cmd_alloc(&cmd_buf[i]) != OPER_OK)
{
printf("Alloc buffer fail : %d\n",i);
count = i;
break;
}
cmd_buf[i]->fd = i+1;
strcpy((char*)cmd_buf[i]->data,"hello");
}
printf("Alloc complete success!\n");
// if(i >= 5) count = i;
for(i = 0 ; i < 5; i++)
{
printf("command %d fd : %d,data : %s\n",(i+1),cmd_buf[i]->fd,(char*)cmd_buf[i]->data);
cmd_free(cmd_buf[i]);
}
if((ret = cmd_pool_destroy()) != OPER_OK)
printf("command pool destroy fail, still in use\n");
else
printf("command pool destroy success!\n");
}
}
void test_cmd_pool()
{
cmd_pool_oper();
}
/*
* cmd pool end
*/
d,测试结果
相关文章推荐
- 二进制搜索方法C++通用执行
- SYNONYM和权限用法
- [Leetcode]Implement Stack using Queues
- SAT阅读填空题常考单词整理(1)
- Mongodb从库数据重新初始化步骤
- CSS选择器
- 【转】Android软件开发需要学什么
- 高精度(还有其它的以后再补充)
- 7z压缩文件时排除指定的文件
- Android中Application类用法
- 备战2015GRE之核心词组under the banner of
- grep
- Oracle 对象信息收集
- Hadoop2.6.0集群搭建
- mysql group by中没有的字段 select中可以有
- Android实用方法—Activity的封装以及美化
- Linux Input子系统以及A/B(SLOT)协议
- Python 安装使用模块
- 使用POI操作Excel,读取、写入Excel
- Qt 中一些常用类的中文说明