单片机上实现内存池的功能
来源:互联网 发布: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);
}
}
- 单片机上实现内存池的功能
- 单片机定时功能的实现
- 一种在单片机上实现多个软件定时功能的框架
- 51单片机定时/计数器的功能实现
- 2KB内存单片机上实现彩屏GUI控件库
- 2KB内存单片机上实现彩屏GUI控件库
- 单片机实现秒表功能
- RTOS在MSP430单片机上的实现
- 在μPD78F0485单片机实验盒上编写程序实现在LCD上显示日历功能
- 单片机时钟实现闹钟功能
- 51单片机实现智能小车的寻轨避障功能
- 单片机上的寄存器
- 嵌入式RTOS在MSP430单片机上的实现
- TCP/IP协议栈在MSP430单片机上的实现
- 单片机上内存管理(重定义malloc & free)de实现
- 在8位单片机上实现JSON数据的简单解析(单片机解析JSON)
- XMOVE3.0手持终端——软件介绍(二):在2KB内存的单片机上实现的彩屏GUI控件库
- windows平台上的一个内存池的实现
- dcos 1.7 安装
- UISegmentedControl自定义背景颜色和字体颜色
- 创建第一个Android Studio项目(界面介绍、打包签名等)
- Dynamics AX 2012 R2 安装额外的AOS
- 稀疏表示背景及基本概念
- 单片机上实现内存池的功能
- XMPP IM 长连接 连接状态维护 和断线重连和单点登录 讲解(4)
- UBUNTU16.04安装mysql,php,apache
- 发送按键
- Android开发非常有用的方法、类或接口
- jquery异步请求
- 1.2.11、如何在开发板上选择不同启动方式
- 名字修饰约定extern "C"与extern "C++"浅析
- 相对布局与图片缩放类型