C语言实现用程序数据段空间模拟内存的动态分配

在一个不支持动态分配的嵌入式系统中,通过C语言编写了一套函数,使用全局buffer模拟内存动态分配。该实现包括alloc和free操作,通过预定义的MAX_ARRAY_SIZE和MAX_POOL_SIZE限制内存分配的大小,并使用结构体BM_ARRAY_NODE管理和跟踪内存块。
摘要由CSDN通过智能技术生成
遇到一个项目情况比较特别,可能是一个嵌入式的系统吧,居然不支持动态分配,还只能用标准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)
#pragma  once

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, 
0sizeof(g_BM_FreeBlockList));
    memset(g_BM_UsedBlockList, 
0sizeof(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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值