您的位置:首页 > 其它

静态内存分配-链表管理(2)实现

2016-07-30 17:57 405 查看

概述

静态内存为开辟若干个Buf,在每个buf增加控制头,该控制头即为链表的节点。如下图所示。



实现

底层数据结构为

struct hstack_mem_pool {
u32 used;
u8 buf[HSTACK_MEMORY_POOL_BUFFER_SIZE];
} mem_pool[HSTACK_MEMORY_POOL_ITEMS];


此处开辟了HSTACK_MEMORY_POOL_ITEMS个静态内存,每一块静态内存均是由buf和used组成。此处的buf包含了用户使用的buf和控制头(链表)两个部分。

底层Malloc实现:

void *HstackList_MallocIMP(u8 length)
{
u8 i;

if (length > HSTACK_MEMORY_POOL_BUFFER_SIZE) {
assert(0);
}

for (i = 0; i < HSTACK_MEMORY_POOL_ITEMS; i++) {
if (cb.mem_pool[i].used == 0) {
cb.mem_pool[i].used = 1;
return ((void *)(cb.mem_pool[i].buf));
}
}

return NULL;
}


此函数返回了静态buf的首地址,在list层调用该函数,即可申请内存。list层内存申请如下代码

struct hstack_datablock *HstackList_New(u8 length)
{
struct hstack_list_entity *entity;

assert(length);

HstackList_LockIMP();

entity = HstackList_MallocIMP(HSTACK_LIST_CTRL_SIZE + length);

HstackList_UnLockIMP();

if (entity) {
entity->mark = HSTACK_LIST_ENTRY_MARK;
HSTACK_LIST_DEBUG_PRINTF("malloc @%08X", (u32)entity);
//返回用户的buf使用区
return ((void *)(((u8 *)(entity)) + HSTACK_LIST_CTRL_SIZE));
}
HSTACK_LIST_DEBUG_PRINTF("malloc @NULL");
return NULL;
}


这个函数申请底层的Buf,同时加上了链表控制头,返回给用户的Buf地址注意要加上Buf控制头的长度。

用户填充完Buf后,可调用插入接口,将数据插入链表中,代码如下:

void HstackList_Insert(struct hstack_datablock *buf, u8 priority)
{
struct hstack_list_entity *entity;

assert(buf);
//寻找控制头,和malloc对应
entity = (struct hstack_list_entity *)
((u8 *)buf - HSTACK_LIST_CTRL_SIZE);

assert(entity->mark == HSTACK_LIST_ENTRY_MARK);

HSTACK_LIST_DEBUG_PRINTF("insert @%08X %s",
(u32)entity, (priority ? "PRI high" : "PRI low"));

HstackList_LockIMP();

if (SIMPLEQ_EMPTY(&list_cb.tx_head)) {
SIMPLEQ_INSERT_HEAD(&list_cb.tx_head, entity, field);
list_cb.priority = entity;

} else {
if (priority) {
SIMPLEQ_INSERT_AFTER(
&list_cb.tx_head, list_cb.priority,
entity, field);
list_cb.priority = entity;
} else {
SIMPLEQ_INSERT_TAIL(&list_cb.tx_head, entity, field);
}
}

HstackList_UnLockIMP();

return;
}


该函数为将items插入链表中结构,插入的链表是有优先级的,来高优先级的要插入之前高优先级的后面,否则就插入尾部。list_cb.priority为记录出入之前优先级最高的item。

用户可使用下面这个函数定时查询静态内存中是否有数据:

struct hstack_datablock *HstackList_PeekHead(void)
{
struct hstack_list_entity *entity;

HstackList_LockIMP();

entity = SIMPLEQ_FIRST(&list_cb.tx_head);

HstackList_UnLockIMP();

if (entity) {
HSTACK_LIST_DEBUG_PRINTF("peek head @%08X", (u32)entity);
return ((struct hstack_datablock *)
((u8 *)entity + HSTACK_LIST_CTRL_SIZE));
} else {
HSTACK_LIST_DEBUG_PRINTF("peek head @NULL");
return NULL;
}
}


该函数定时查询静态内存链表中是否有数据,如果有数据的话,返回数据Buf指针给上层使用。

用户使用完静态内存后,一定要释放,释放的代码如下:

struct hstack_datablock *HstackList_RemoveHead(void)
{
struct hstack_list_entity *entity;

HstackList_LockIMP();

entity = SIMPLEQ_FIRST(&list_cb.tx_head);

if (entity) {

HSTACK_LIST_DEBUG_PRINTF("remove @%08X", (u32)entity);

SIMPLEQ_REMOVE_HEAD(&list_cb.tx_head, field);
HstackList_FreeIMP(entity);
} else {
HSTACK_LIST_DEBUG_PRINTF("remove @NULL");
}

HstackList_UnLockIMP();

return ((struct hstack_datablock *)
((u8 *)entity + HSTACK_LIST_CTRL_SIZE));
}


调用该函数即可释放已经使用过的内存。

用途

应用场景为多任务使用同一资源,例如多个任务同时调用网络发送任务,此时可将多任务的发送数据存入静态内存,网络定时查询是否有数据要发送。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: