单片机上实现内存池的功能

来源:互联网 发布:ubuntu配置lnmp 编辑:程序博客网 时间:2024/05/06 12:54


#define MAX_ALLOC_NUM32  //最多可申请的内存块数。

#define MEM_PAGE_SZ32 //一页内存的字节数。(分配的最小单位为page)
#define MEM_BLK_NUM2   //可供分配的块数量。(一个块2048byte字节)



//内存池的块
typedef struct mem_block
{
unsigned char mem[64][MEM_PAGE_SZ];  //内存池:64个页
u64 mask;  //内存池页占用的掩码
}mem_block_t;





//内存池的管理块
typedef structmem_patch
{
u8 m_blk_id;   //使用的内存池的块的ID
u8 m_sta_idx; //当前内存片在内存池中的起始位置(及在mem数组中的下标)
u16 m_sz;    //所申请的内存大小(单位字节)
u8 used;     //标识:标识当前管理块是否已被使用

}mem_patch_t;




mem_block_t mem_pool[MEM_BLK_NUM]; //所申请的内存池块
mem_patch_t mem_pacth[MAX_ALLOC_NUM];   //管理内存的管理块




//获取一个空闲的内存管理项ID
static  char mem_get_free_patch()
{
u8 i=0;


for(i=0;i<MAX_ALLOC_NUM;i++)
{
if(mem_pacth[i].used == 0)
{
return i;
}
}
return -1;
}


//通过给定的地址,查找一个内存管理项ID
static  char mem_get_patch_idx(u8*ptr)
{
char i=0;


for(i=0;i<MAX_ALLOC_NUM;i++)
{
if(mem_pacth[i].used == 1)
{
u8 *pMem = mem_pool[mem_pacth[i].m_blk_id].mem[mem_pacth[i].m_sta_idx];
u16  size = mem_pacth[i].m_sz;
if(pMem == ptr || (pMem < ptr && ptr < (pMem+size)))
{
return i;
}
}
}
return -1;
}





//获取一个给定bit位数的掩码
static  u64 mem_get_mask(u16 nbit)
{
u64   tmp=0;
u16   i =0;


for(i=0;i<nbit;i++)
{
tmp = tmp<<1;
tmp |= 1;
}
return tmp;
}

//在64bit的数中,获取一个存在连续nbit个为1的位置
static  int mem_empty_sub(u64mem_mask, u16 nbit)
{
u16 i=0;
u16 nbit_flg = sizeof(mem_mask)*8;
u64 mask= 0;
u64 shift= 0;
int ret= -1;


if(nbit > 64)
return ret;

mask = mem_get_mask(nbit);
shift  = mask<<(nbit_flg-nbit);

for(i=0;i<(nbit_flg-nbit+1); i++)
{
if((mem_mask & shift) == shift)
{
ret = i;
break;
}
shift = shift>>1;
}
return ret;
}



//从一个块中,获取一个大小满足size的下标
static  int mem_get_free_idx(mem_block_t *mem, u32size)
{
u8 nbit_req=size/MEM_PAGE_SZ;
int sub_mem = 0;
u64 mask_clr = 0;
u16 mask_sz = sizeof(mem->mask)*8;
int iRet = -1;


if((size%MEM_PAGE_SZ) > 0)
nbit_req = nbit_req +1;

sub_mem = mem_empty_sub(mem->mask, nbit_req);
if(sub_mem >= 0)
{
mask_clr   = mem_get_mask(nbit_req);
mask_clr   = mask_clr<<(mask_sz - nbit_req- sub_mem);
mem->mask = mem->mask &(~mask_clr);
iRet = sub_mem;
}
return iRet;
}

//释放一个指定起始位和大小的内存
static  void mem_free(mem_block_t *mem, u8start_idx, u32 size)
{
u8 nbit_req=size/MEM_PAGE_SZ;
u64 mask_clr = 0;
u16 mask_sz = sizeof(mem->mask)*8;


if((size%MEM_PAGE_SZ) > 0)
nbit_req = nbit_req +1;


mask_clr = mem_get_mask(nbit_req);
mask_clr   = mask_clr<<(mask_sz - nbit_req- start_idx);
mem->mask |= mask_clr;
}


OS_EVENT      *MemLock = NULL;


void    init_mem()
{
u8 i=0;
    
    if(MemLock == NULL)
        MemLock = OSSemCreate(1);
for(i=0;i<MEM_BLK_NUM;i++)
{
mem_pool[i].mask = 0xFFFFFFFFFFFFFFFFull;
}
for(i=0;i<MAX_ALLOC_NUM;i++)
{
mem_pacth[i].used = 0;
}
}




void *kmalloc(u32size)
{
u8 i=0;
void *pRet = NULL;
char patch_free = 0;
int mem_idx = 0;
    u8      err;
    
    if(MemLock!= NULL)
        OSSemPend(MemLock, 0, &err);
    
patch_free = mem_get_free_patch();
if(patch_free <0)
{
syslog(DBG_NOTICE,"[mem] malloc failed,no mem struct can use.\n");
goto endl;
}


for(i=0;i<MEM_BLK_NUM;i++)
{
mem_idx = mem_get_free_idx(&mem_pool[i], size);
if(mem_idx >= 0)
{
mem_pacth[patch_free].used = 1;
mem_pacth[patch_free].m_sta_idx = mem_idx;
mem_pacth[patch_free].m_blk_id = i;
mem_pacth[patch_free].m_sz     = size;
pRet = (void*)mem_pool[i].mem[mem_idx];
goto endl;
}
}
syslog(DBG_NOTICE,"[mem] this no mem can be malloc.\n");
endl:
    if(MemLock!= NULL)
        OSSemPost(MemLock);
    
return pRet;
}




void kfree(void *mem)
{
u8 *pMem = (u8*)mem;
u8 blk_id = 0;
u16 mem_sz   = 0;
u8 sta_idx  = 0;
char pacth_id= 0;


if(pMem == NULL)
    {
syslog(DBG_NOTICE,"[mem] free mem failed, addr is null\n");
        return;
    }
pacth_id = mem_get_patch_idx(pMem);


if(pacth_id >=0)
{
blk_id = mem_pacth[pacth_id].m_blk_id;
sta_idx= mem_pacth[pacth_id].m_sta_idx;
mem_sz = mem_pacth[pacth_id].m_sz;
mem_free(&mem_pool[blk_id],sta_idx, mem_sz);
        mem_pacth[pacth_id].used = 0;
}
else
{
syslog(DBG_NOTICE,"[mem] free mem failed, can not find addr 0x%08\n",mem);
}
}


0 0
原创粉丝点击