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

来源:互联网 发布:旅行者1号 知乎 编辑:程序博客网 时间:2024/05/17 06:54

概述

静态内存为开辟若干个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));}

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

用途

应用场景为多任务使用同一资源,例如多个任务同时调用网络发送任务,此时可将多任务的发送数据存入静态内存,网络定时查询是否有数据要发送。

0 0
原创粉丝点击