静态内存分配-链表管理(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)); }
调用该函数即可释放已经使用过的内存。
用途
应用场景为多任务使用同一资源,例如多个任务同时调用网络发送任务,此时可将多任务的发送数据存入静态内存,网络定时查询是否有数据要发送。相关文章推荐
- java面向对象
- 静态链表
- 从源码出发了解RxJava的使用(中)
- I/O多路转接之select、poll、epoll
- Linux 基础知识
- Ajax使用学习
- Spring Bean初始化过程
- TensorFlow学习笔记(一):快速安装与使用TensorFlow
- HDU-1228 - A + B (很久没做水题了!都快忘了......)
- java生成PDF文件
- 开源学习网站学习
- 工厂模式
- 文章标题
- Java NIO学习——Buffer学习
- 5-31 切分表达式——写个tokenizer吧 (20分)
- OSAL的原理
- Windows系统防火墙用法
- 测试并发应用(七)配置Eclipse来调试并发代码
- BST二叉查找树
- LNMP-源码 nginx ,keepalived