遇到一个项目情况比较特别,可能是一个嵌入式的系统吧,居然不支持动态分配,还只能用标准C,琢磨了好几天,最后还是自己写了套函数,模拟一下动态分配。
大致是这样想的,弄个全局的buffer,在buffer里做alloc和free操作,局限性当然是buffer的大小不宜太大,尤其是16bit的环境。
如果对buffer的大小有要求,可通过修改源代码中的预定义来实现。
MAX_ARRAY_SIZE 最多可分配的内存块数的量。
MAX_POOL_SIZE 最多可分配的字节数,也就是预留的buffer大小。
struct BM_ARRAY_NODE 描述未分配和已分配的区块。
源代码:bm_malloc.h (version 1.0)
源代码:bm_malloc.c (version 1.0)
大致是这样想的,弄个全局的buffer,在buffer里做alloc和free操作,局限性当然是buffer的大小不宜太大,尤其是16bit的环境。
如果对buffer的大小有要求,可通过修改源代码中的预定义来实现。
MAX_ARRAY_SIZE 最多可分配的内存块数的量。
MAX_POOL_SIZE 最多可分配的字节数,也就是预留的buffer大小。
struct BM_ARRAY_NODE 描述未分配和已分配的区块。
源代码:bm_malloc.h (version 1.0)
#pragma
once
void uimalloc_init( void );
void * ui_malloc(unsigned short size);
void ui_mfree( void * p);
void uimalloc_init( void );
void * ui_malloc(unsigned short size);
void ui_mfree( void * p);
源代码:bm_malloc.c (version 1.0)
#include
<
memory.h
>
#include < string .h >
#include < assert.h >
#include " bm_malloc.h "
#define MAX_ARRAY_SIZE 256
#define MAX_POOL_SIZE 0xFFFF
typedef struct BM_ARRAY_NODE
{
unsigned short index;
unsigned short len;
} BM_ARRAY_NODE;
static BM_ARRAY_NODE g_BM_FreeBlockList[MAX_ARRAY_SIZE + 1 ] = {0} ;
static BM_ARRAY_NODE g_BM_UsedBlockList[MAX_ARRAY_SIZE + 1 ] = {0} ;
static unsigned char g_BM_Buffer[MAX_POOL_SIZE];
/*
* insert a new node into ary_list, order by BM_ARRAY_NODE.index
*
* return value: the index of new node in array. return -1 if error.
*/
int bm_array_add(BM_ARRAY_NODE * ary_list, const BM_ARRAY_NODE node)
{
assert(ary_list);
unsigned short i; /*loop*/
unsigned short n = ary_list[MAX_ARRAY_SIZE].index; /*item count in the ary_list*/
unsigned short pos = n; /*insert position. assume insert at the end of array*/
unsigned mov_len; /*moved data length in byte*/
assert(n < MAX_ARRAY_SIZE);
/*search the fixed position in order*/
for (i=0; i<n; i++)
{
if (node.index < ary_list[i].index)
{
pos = i;
break;
}
}
mov_len = (n - pos) * sizeof(BM_ARRAY_NODE);
if (mov_len > 0)
{
memmove(&(ary_list[i+1]), &(ary_list[i]), mov_len);
ary_list[MAX_ARRAY_SIZE].index = n;
}
ary_list[i].index = node.index;
ary_list[i].len = node.len;
ary_list[MAX_ARRAY_SIZE].index++;
return i;
}
/*
* remove node from ary_list
*
* return value: void
*/
void bm_array_remove(BM_ARRAY_NODE * ary_list, unsigned index)
{
unsigned short n; /*item count in the ary_list*/
unsigned mov_len; /*moved data length in byte*/
n = ary_list[MAX_ARRAY_SIZE].index;
assert(ary_list);
assert(index < n);
mov_len = (n - index - 1) * sizeof(BM_ARRAY_NODE);
if (mov_len > 0)
{
memmove(&(ary_list[index]),&(ary_list[index+1]),mov_len);
}
n--;
ary_list[n].index = ary_list[n].len = 0;
ary_list[MAX_ARRAY_SIZE].index = n;
return;
}
/*
* combine the consecutive blocks in FreeBlockList
*
* return value: void
*/
void bm_pack_free_blocks( void )
{
unsigned short n; /*item count in the ary_list*/
unsigned short i = 0;
n = g_BM_FreeBlockList[MAX_ARRAY_SIZE].index;
while (i < n - 1)
{
if (g_BM_FreeBlockList[i].index + g_BM_FreeBlockList[i].len == g_BM_FreeBlockList[i+1].index)
{
unsigned mov_len; /*moved data length in byte*/
g_BM_FreeBlockList[i].len = g_BM_FreeBlockList[i].len + g_BM_FreeBlockList[i+1].len;
mov_len = (n - i - 2) * sizeof(BM_ARRAY_NODE);
if (mov_len > 0)
{
memmove(&(g_BM_FreeBlockList[i+1]), &(g_BM_FreeBlockList[i+2]), mov_len);
}
n--;
g_BM_FreeBlockList[n].index = g_BM_FreeBlockList[n].len = 0;
}
else
{
i++;
}
}
g_BM_FreeBlockList[MAX_ARRAY_SIZE].index = n;
return;
}
/*
* initialize
* add a new free block
*/
void uimalloc_init( void )
{
BM_ARRAY_NODE node;
memset(g_BM_FreeBlockList, 0, sizeof(g_BM_FreeBlockList));
memset(g_BM_UsedBlockList, 0, sizeof(g_BM_UsedBlockList));
node.index = 0;
node.len = MAX_POOL_SIZE;
bm_array_add(g_BM_FreeBlockList, node);
return;
}
/*
* alloc a block of memory. it's zero filled.
*
* return value: the pointer. if failed, return value is NULL.
*/
void * ui_malloc(unsigned short size)
{
unsigned short n; /*item count in the ary_list*/
unsigned short i = 0;
unsigned short fix_min_size = MAX_POOL_SIZE;
unsigned short fix_index = 0;
void * p_ret = NULL;
n = g_BM_FreeBlockList[MAX_ARRAY_SIZE].index;
assert(size > 0);
assert(n < MAX_ARRAY_SIZE);
for (i=0; i<n; i++)
{
if ( g_BM_FreeBlockList[i].len < fix_min_size && g_BM_FreeBlockList[i].len >= size )
{
fix_min_size = g_BM_FreeBlockList[i].len;
fix_index = i;
}
}
if (fix_min_size >= size && fix_index < MAX_ARRAY_SIZE && g_BM_FreeBlockList[fix_index].len >= size)
{
BM_ARRAY_NODE NewNode;
NewNode.index = g_BM_FreeBlockList[fix_index].index;
NewNode.len = size;
if (fix_min_size == size)
{
bm_array_remove(g_BM_FreeBlockList, fix_index);
}
else
{
g_BM_FreeBlockList[fix_index].index = g_BM_FreeBlockList[fix_index].index + size;
g_BM_FreeBlockList[fix_index].len = g_BM_FreeBlockList[fix_index].len - size;
}
bm_array_add(g_BM_UsedBlockList, NewNode);
p_ret = g_BM_Buffer + NewNode.index;
memset(p_ret, 0, size);
}
return p_ret;
}
/*
* void bios_free(void *p)
*/
void ui_mfree( void * p)
{
unsigned short n; /* item count in the g_BM_UsedBlockList */
unsigned short i;
assert(p);
n = g_BM_UsedBlockList[MAX_ARRAY_SIZE].index;
for (i=0; i<n; i++)
{
if ( g_BM_Buffer + g_BM_UsedBlockList[i].index == (unsigned char *) p )
{
BM_ARRAY_NODE node;
unsigned need_pack;
unsigned short n_free; /*item count in the g_BM_FreeBlockList*/
node.index = g_BM_UsedBlockList[i].index;
node.len = g_BM_UsedBlockList[i].len;
bm_array_remove(g_BM_UsedBlockList, i);
int index = bm_array_add(g_BM_FreeBlockList, node);
/* if bm_array_add return error. the free block will be out of use. */
if (index < 0)
{
break;
}
n_free = g_BM_FreeBlockList[MAX_ARRAY_SIZE].index;
need_pack = 0;
if (index > 0)
{
if (g_BM_FreeBlockList[index-1].index + g_BM_FreeBlockList[index-1].len == node.index)
{
need_pack = 1;
}
}
if (index < n_free - 1 && need_pack == 0)
{
if (node.index + node.len == g_BM_FreeBlockList[index+1].index)
{
need_pack = 1;
}
}
if (need_pack)
{
bm_pack_free_blocks();
}
break; /*for (i=0; i<n; i++)*/
}
}/*end for (i=0; i<n; i++)*/
return;
}
#include < string .h >
#include < assert.h >
#include " bm_malloc.h "
#define MAX_ARRAY_SIZE 256
#define MAX_POOL_SIZE 0xFFFF
typedef struct BM_ARRAY_NODE
{
unsigned short index;
unsigned short len;
} BM_ARRAY_NODE;
static BM_ARRAY_NODE g_BM_FreeBlockList[MAX_ARRAY_SIZE + 1 ] = {0} ;
static BM_ARRAY_NODE g_BM_UsedBlockList[MAX_ARRAY_SIZE + 1 ] = {0} ;
static unsigned char g_BM_Buffer[MAX_POOL_SIZE];
/*
* insert a new node into ary_list, order by BM_ARRAY_NODE.index
*
* return value: the index of new node in array. return -1 if error.
*/
int bm_array_add(BM_ARRAY_NODE * ary_list, const BM_ARRAY_NODE node)
{
assert(ary_list);
unsigned short i; /*loop*/
unsigned short n = ary_list[MAX_ARRAY_SIZE].index; /*item count in the ary_list*/
unsigned short pos = n; /*insert position. assume insert at the end of array*/
unsigned mov_len; /*moved data length in byte*/
assert(n < MAX_ARRAY_SIZE);
/*search the fixed position in order*/
for (i=0; i<n; i++)
{
if (node.index < ary_list[i].index)
{
pos = i;
break;
}
}
mov_len = (n - pos) * sizeof(BM_ARRAY_NODE);
if (mov_len > 0)
{
memmove(&(ary_list[i+1]), &(ary_list[i]), mov_len);
ary_list[MAX_ARRAY_SIZE].index = n;
}
ary_list[i].index = node.index;
ary_list[i].len = node.len;
ary_list[MAX_ARRAY_SIZE].index++;
return i;
}
/*
* remove node from ary_list
*
* return value: void
*/
void bm_array_remove(BM_ARRAY_NODE * ary_list, unsigned index)
{
unsigned short n; /*item count in the ary_list*/
unsigned mov_len; /*moved data length in byte*/
n = ary_list[MAX_ARRAY_SIZE].index;
assert(ary_list);
assert(index < n);
mov_len = (n - index - 1) * sizeof(BM_ARRAY_NODE);
if (mov_len > 0)
{
memmove(&(ary_list[index]),&(ary_list[index+1]),mov_len);
}
n--;
ary_list[n].index = ary_list[n].len = 0;
ary_list[MAX_ARRAY_SIZE].index = n;
return;
}
/*
* combine the consecutive blocks in FreeBlockList
*
* return value: void
*/
void bm_pack_free_blocks( void )
{
unsigned short n; /*item count in the ary_list*/
unsigned short i = 0;
n = g_BM_FreeBlockList[MAX_ARRAY_SIZE].index;
while (i < n - 1)
{
if (g_BM_FreeBlockList[i].index + g_BM_FreeBlockList[i].len == g_BM_FreeBlockList[i+1].index)
{
unsigned mov_len; /*moved data length in byte*/
g_BM_FreeBlockList[i].len = g_BM_FreeBlockList[i].len + g_BM_FreeBlockList[i+1].len;
mov_len = (n - i - 2) * sizeof(BM_ARRAY_NODE);
if (mov_len > 0)
{
memmove(&(g_BM_FreeBlockList[i+1]), &(g_BM_FreeBlockList[i+2]), mov_len);
}
n--;
g_BM_FreeBlockList[n].index = g_BM_FreeBlockList[n].len = 0;
}
else
{
i++;
}
}
g_BM_FreeBlockList[MAX_ARRAY_SIZE].index = n;
return;
}
/*
* initialize
* add a new free block
*/
void uimalloc_init( void )
{
BM_ARRAY_NODE node;
memset(g_BM_FreeBlockList, 0, sizeof(g_BM_FreeBlockList));
memset(g_BM_UsedBlockList, 0, sizeof(g_BM_UsedBlockList));
node.index = 0;
node.len = MAX_POOL_SIZE;
bm_array_add(g_BM_FreeBlockList, node);
return;
}
/*
* alloc a block of memory. it's zero filled.
*
* return value: the pointer. if failed, return value is NULL.
*/
void * ui_malloc(unsigned short size)
{
unsigned short n; /*item count in the ary_list*/
unsigned short i = 0;
unsigned short fix_min_size = MAX_POOL_SIZE;
unsigned short fix_index = 0;
void * p_ret = NULL;
n = g_BM_FreeBlockList[MAX_ARRAY_SIZE].index;
assert(size > 0);
assert(n < MAX_ARRAY_SIZE);
for (i=0; i<n; i++)
{
if ( g_BM_FreeBlockList[i].len < fix_min_size && g_BM_FreeBlockList[i].len >= size )
{
fix_min_size = g_BM_FreeBlockList[i].len;
fix_index = i;
}
}
if (fix_min_size >= size && fix_index < MAX_ARRAY_SIZE && g_BM_FreeBlockList[fix_index].len >= size)
{
BM_ARRAY_NODE NewNode;
NewNode.index = g_BM_FreeBlockList[fix_index].index;
NewNode.len = size;
if (fix_min_size == size)
{
bm_array_remove(g_BM_FreeBlockList, fix_index);
}
else
{
g_BM_FreeBlockList[fix_index].index = g_BM_FreeBlockList[fix_index].index + size;
g_BM_FreeBlockList[fix_index].len = g_BM_FreeBlockList[fix_index].len - size;
}
bm_array_add(g_BM_UsedBlockList, NewNode);
p_ret = g_BM_Buffer + NewNode.index;
memset(p_ret, 0, size);
}
return p_ret;
}
/*
* void bios_free(void *p)
*/
void ui_mfree( void * p)
{
unsigned short n; /* item count in the g_BM_UsedBlockList */
unsigned short i;
assert(p);
n = g_BM_UsedBlockList[MAX_ARRAY_SIZE].index;
for (i=0; i<n; i++)
{
if ( g_BM_Buffer + g_BM_UsedBlockList[i].index == (unsigned char *) p )
{
BM_ARRAY_NODE node;
unsigned need_pack;
unsigned short n_free; /*item count in the g_BM_FreeBlockList*/
node.index = g_BM_UsedBlockList[i].index;
node.len = g_BM_UsedBlockList[i].len;
bm_array_remove(g_BM_UsedBlockList, i);
int index = bm_array_add(g_BM_FreeBlockList, node);
/* if bm_array_add return error. the free block will be out of use. */
if (index < 0)
{
break;
}
n_free = g_BM_FreeBlockList[MAX_ARRAY_SIZE].index;
need_pack = 0;
if (index > 0)
{
if (g_BM_FreeBlockList[index-1].index + g_BM_FreeBlockList[index-1].len == node.index)
{
need_pack = 1;
}
}
if (index < n_free - 1 && need_pack == 0)
{
if (node.index + node.len == g_BM_FreeBlockList[index+1].index)
{
need_pack = 1;
}
}
if (need_pack)
{
bm_pack_free_blocks();
}
break; /*for (i=0; i<n; i++)*/
}
}/*end for (i=0; i<n; i++)*/
return;
}