嵌入式无操作系统下管理内存和队列(类UCOS II思想)
例子:存储日志,最多存128条,每条最大1MB。
内存方面 因为嵌入式不适合用动态内存,会产生碎片。这里我们用 u8 data[LOG_SIZE];开辟固定128MB的内存区,再对其分为128个1MB内存块进行管理。
管理方法为:使用一个内存控制块结构体MCB,再编写增删改函数操作MCB进行管理。
队列方面我们使用循环队列,比如队列最多10个元素,我们存第11个元素时就会覆盖第一个。
管理方法为:使用一个队列控制块结构体LoopQueue,再编写增删改函数操作LoopQueue进行管理。
内存块与队列的关联是靠指针:
比如(存了信息的内存块1)与(队列位置1)
①我们可以把内存块1的地址指针存入队列位置1;
②也可以再定义个新结构体,包含内存块1的地址指针、信息的序号、信息的时间。再将这个结构体的指针存入队列位置1。
一、管理128MB内存
#define LOG_SIZE 0x8000000 // (0x8000000 / 1024 / 1024= 128)
#define Blk_Num 128
//内存控制块结构体 Memory control block
typedef struct _MCB {
void* BeginAddr; //指向开辟的内存的首地址
uint32 TotalSize; //开辟内存的总大小
uint32 BlkSize; //每个内存块的大小
uint32 BlkNums; //开辟的总内存块数目
uint32 FreeBlks; //可用的内存块数目
uint32 BlkOut; //获取内存时释放的位置
uint32 BlkIn; //回收内存时存放的位置
uint32 MemAddr[Blk_Num];//该数组存储所有内存块的首地址
} MCB;
//对指定内存的实际操作就靠这两个全局变量
u8 data[LOG_SIZE];
MCB LogMCB;
//初始化,应该用函数执行,这里简单贴出来:
memset(data,0,sizeof(u8)*LOG_SIZE);
LogMCB.BeginAddr = data;
LogMCB.TotalSize = 0x8000000*sizeof(u8); //128MB
LogMCB.BlkSize = 0x100000*sizeof(u8); //1MB
LogMCB.BlkNums = LogMCB.TotalSize/LogMCB.BlkSize;
LogMCB.FreeBlks = LogMCB.BlkNums;
LogMCB.BlkIn = 0;
LogMCB.BlkOut = 0;
For(i=0;i<LogMCB.BlkNums;i++)
{
LogMCB.MemAddr[i] = LogMCB.BeginAddr+(i*LogMCB.BlkSize);
}
//获取一块内存时各变量对应的操作:
LogMCB.MemAddr[LogMemObj.BlkOut] = 0; 置零
LogMCB.BeginAddr; 不变
LogMCB.TotalSize; 不变
LogMCB.BlkSize; 不变
LogMCB.BlkNums; 不变
LogMCB.FreeBlks--; 减一
LogMCB.BlkOut++; 加一
LogMCB.BlkIn; 不变
//释放一块内存时各变量对应的操作:
LogMCB.MemAddr[LogMemObj.BlkIn] = addr; 赋值
LogMCB.BeginAddr; 不变
LogMCB.TotalSize; 不变
LogMCB.BlkSize; 不变
LogMCB.BlkNums; 不变
LogMCB.FreeBlks++; 加一
LogMCB.BlkOut; 不变
LogMCB.BlkIn++; 加一
代码为功能解析,实际使用应将初始化内存、获取内存、释放内存包装为函数。

//要理解内存控制结构体 每个成员的意义及用法
typedef struct _MCB {
void* BeginAddr; //指向开辟的内存的首地址
uint32 TotalSize; //开辟内存的总大小
uint32 BlkSize; //每个内存块的大小
uint32 BlkNums; //开辟的总内存块数目
uint32 FreeBlks; //可用的内存块数目
uint32 BlkOut; //获取内存时释放的位置
uint32 BlkIn; //回收内存时存放的位置
uint32 MemAddr[Blk_Num];//该数组存储所有内存块的首地址
} MCB;
//对指定内存的实际操作就靠这两个全局变量
u8 data[LOG_SIZE];
MCB LogMCB;
二、用循环队列管理日志
假如我们对日志是一直进行收发操作的,那么实际队列可能只用50条,就能满足128条日志的收发了。所以队列数不一定要内存块数这么大。
#define MAX 128
typedef struct _LoopQueue
{
uint32 QueueMax; //队列最大数目
uint32 QueueUsed; //使用了的数目
uint32 QueueIn; //进队位置
uint32 QueueOut; //出队位置
void *Member[MAX]; //存储每条日志的结构体指针
} LoopQueue;
LoopQueue LogQueue;
//initial
LogQueue.QueueMax = MAX;
LogQueue.QueueUsed = 0;
LogQueue.QueueIn = 0;
LogQueue.QueueOut = 0;
for(int i=0;i<MAX;i++)
{
LogQueue.Member[i] = NULL;
}
//存储一条日志到内存块后,将内存块地址存入队列。我们发送日志时 直接操作队列、间接操作内存块:
void *nowlog = LogMCB.MemAddr[LogMemObj.BlkOut] ;
LogMCB.MemAddr[LogMCB.FreeRingOut] = 0;
LogMCB.FreeBlks--;
LogMCB.BlkOut++;
LogQueue.Member[LogQueue.QueueIn] = (void *)nowlog ;
LogQueue.QueueUsed ++;
LogQueue.QueueIn ++;
//删除一条日志时:
LOG * nlog = (LOG *)LogQueue.Member[LogQueue.QueueOut] ;
LogQueue.Member[LogQueue.QueueOut] = NULL;
LogQueue.QueueOut ++;
LogQueue.QueueUsed --;
LogMCB.MemAddr[LogMCB.BlkIn] = (void *)nlog;
LogMCB.FreeBlks++;
LogMCB.BlkIn++;
//队列实现循环:
LogQueue.QueueIn = LogQueue.QueueIn % LogQueue.QueueMax ; //比如存第129条,会存储到物理第一条的位置
LogQueue.QueueOut = LogQueue.QueueOut % LogQueue.QueueMax ;

比较重要的就是内存初始化,内存使用,内存回收,队列初始化,队列使用,队列回收。对日志实际赋值以外很多地方都是用的指针进行交互。
主要要理解存储、删除日志时:内存的管理、队列的管理方式:
//存储一条日志时:
//1、使用一个内存块
void* nowlog = LogMCB.MemAddr[LogMCB.BlkOut] ;
LogMCB.MemAddr[LogMCB.FreeRingOut] = 0;
LogMCB.FreeBlks--;
LogMCB.BlkOut++;
//2、在地址处写日志(不一定用这种方法)
memcpy(nowlog ,pdata, 0x100000*sizeof(u8));
//3、将日志指针存入队列
LogQueue.Member[LogQueue.QueueIn] = (void )nowlog ;
LogQueue.QueueUsed ++;
LogQueue.QueueIn ++;
//删除一条日志时:
//1、取出队列中的日志指针
void nowlog = (LOG *)LogQueue.Member[LogQueue.QueueOut] ;
LogQueue.Member[LogQueue.QueueOut] = NULL;
LogQueue.QueueOut ++;
LogQueue.QueueUsed --;
//2、该日志指针也是内存块首地址指针,回收该内存块
LogMCB.MemAddr[LogMCB.BlkIn] = (void *)nlog;
LogMCB.FreeBlks++;
LogMCB.BlkIn++;
//队列实现循环:
LogQueue.QueueIn = LogQueue.QueueIn % LogQueue.QueueMax ;
//比如存第129条,会存储到物理第一条的位置
LogQueue.QueueOut = LogQueue.QueueOut % LogQueue.QueueMax ;
嵌入式无操作系统下管理内存和队列(类UCOS II思想)的更多相关文章
- 轻量级操作系统FreeRTOS的内存管理机制(一)
本文由嵌入式企鹅圈原创团队成员朱衡德(Hunter_Zhu)供稿. 近几年来,FreeRTOS在嵌入式操作系统排行榜中一直位居前列,作为开源的嵌入式操作系统之一,它支持许多不同架构的处理器以及多种编译 ...
- glibc下的内存管理
在解码过程中我们也遇到了类似的问题,第一次解码的音频比较大60s,耗了3G的内存,reset之后内存并没有退还给操作系统,第二次即使解一个10s的音频 几周前我曾提到,我被项目组分配去做了一些探究li ...
- 通俗易懂,C#如何安全、高效地玩转任何种类的内存之Span的脾气秉性(二)。 异步委托 微信小程序支付证书及SSL证书使用 SqlServer无备份下误删数据恢复 把list集合的内容写入到Xml中,通过XmlDocument方式写入Xml文件中 通过XDocument方式把List写入Xml文件
通俗易懂,C#如何安全.高效地玩转任何种类的内存之Span的脾气秉性(二). 前言 读完上篇<通俗易懂,C#如何安全.高效地玩转任何种类的内存之Span的本质(一).>,相信大家对sp ...
- iOS: ARC & MRC下string内存管理策略探究
ARC & MRC下string内存管理策略探究 前两天跟同事争论一个关于NSString执行copy操作以后是否会发生变化,两个人整了半天,最后写代码验证了一下,发现原来NSString操作 ...
- ARC下的内存管理
1.ARC下单对象内存管理 局部变量释放对象随之被释放 int main(int argc, const char * argv[]) { @autoreleasepool { Person *p = ...
- 嵌入式实时操作系统μCOS原理与实践任务控制与时间的解析
/*************************************************************************************************** ...
- linux 操作系统下c语言编程入门
2)Linux程序设计入门--进程介绍 3)Linux程序设计入门--文件操作 4)Linux程序设计入门--时间概念 5)Linux程序设计入门--信号处理 6)Linux程序设计入门--消息管理 ...
- Java是如何管理内存的?
本文转自CSDN用户Kevin涂腾飞的文章java内存管理机制:http://blog.csdn.net/tutngfei1129287460/article/details/7383480 JAVA ...
- 嵌入式LINUX环境下视频采集知识
V4L2是Linux环境下开发视频采集设备驱动程序的一套规范(API),它为驱动程序的编写提供统一的接口,并将所有的视频采集设备的驱动程序都纳入其的管理之中.V4L2不仅给驱动程序编写者带来极大的方便 ...
随机推荐
- Solution -「十二省联考2019」春节十二响
题目 题意简述 link. 给一棵 \(n\) 个结点的有根树,点带权.把点分为若干组,并要求同组内不存在任何祖先-后代关系.最小化每组内的最大点权之和. 数据规模 \(n\le2\tim ...
- 「微前端实践」使用Vue+qiankun微前端方案重构老项目的本地验证
10月份换了新的工作,参与完一个月的需求迭代后,接到了项目重构的任务.简单来说,需要在短时间内提出方案设想,同时进行本地验证,最终需要拿出一套技术替换方案来.于是,埋头苦干了一个月,总算干了点成绩出来 ...
- 利用shell脚本使用kubeadm部署kubenetes 1.18.6集群环境
# README # 此脚本需要在master节点上使用 # 注意root密码,请提前修改 # 个人实验环境,注意机器最低配置:master(2G内存,1cpu2核心,否则集群会创建失败),node( ...
- 技术管理进阶——谁能成为Leader,大Leader该做什么
原创不易,求分享.求一键三连 两个故事 谁能成为Leader 之前接手了一块产品业务线,于是与原Leader说了下分工,大概意思是: 我是过来学习的,也能给团队带来更多的资源,团队内的工作你继续管理, ...
- 查看树莓派系统相关信息的shell代码
一.系统信息 1.显示系统名.系统版本和cpu架构等 在命令行中输入下面的指令 uname -a 2.系统位数 在命令行中输入下面的指令 getconf LONG_BIT 如图,显示多少就是多少位 3 ...
- 零售BI解决方案_新零售时代转型升级思路全都在这里
新零售是什么意思?新零售即企业以互联网为依托,通过运用大数据.人工智能等先进技术手段,对商品的生产.流通与销售过程进行升级改造,进而重塑业态结构与生态圈,并对线上服务.线下体验以及现代物流进行深度融合 ...
- 使用教程:宝塔服务器管理助手Linux面版
网页提示:宝塔Linux面板初始化成功,点击登陆页面:直接使用初始化配置时填写的帐号及密码登陆面板功能:网站管理.FTP管理.数据库管理.系统安全.文件管理.计划任务.环境设置. 方法/步骤1: 使用 ...
- 【windows 访问控制】三、访问控制列表 ACL=DACL+SACL
访问控制列表(ACL:Access Control List) ACL列表的结构 ACL 中的每个 ACE 标识一个受信者,并指定该受信者访问规则.安全对象的安全描述符 可以包含两种类型的 ACL:D ...
- SQL:查询时给表起别名
Q 有两个表student.score,查询前一个表的id.name列,后一个表的total列,查询结果通过两个表的id连接起来 要求 使用别名st和sc替换表名进行查询 A SELECT st.id ...
- 安装xpath helper方便进行爬虫
安装xpath helper方便进行爬虫 因为我使用的是edge浏览器,扩展商店搜索不到xpath-helper,但是我不甘心,取下载源扩展直接放在edge中试试 下载XPath helper的源码 ...