当前位置:首页 > 单片机 > 单片机
[导读]一、内存管理简介内存管理,是指软件运行时对计算机内存资源的分配和使用的技术。其最主要的目的是如何高效,快速的分配,并且在适当的时候释放和回收内存资源。内存管理的实现方法有很多种,他们其实最终都是要实现

一、内存管理简介

内存管理,是指软件运行时对计算机内存资源的分配和使用的技术。其最主要的目的是如何高效,快速的分配,并且在适当的时候释放和回收内存资源。内存管理的实现方法有很多种,他们其实最终都是要实现 2 个函数:malloc 和 free;malloc 函数用于内存申请,free 函数用于内存释放。本章,我们介绍一种比较简单的办法来实现:分块式内存管下面我们介绍一下该方法的实现原理,如图 42.1.1 所示:

内存管理表的项值代表的意义为:当该项值为 0 的时候,代表对应的内存块未被占用,当该项值非零的时候,代表该项对应的内存块已经被占用,其数值则代表被连续占用的内存块数。比如某项值为 10,那么说明包括本项对应的内存块在内,总共分配了 10 个内存块给外部的某
个指针。内寸分配方向如图所示,是从顶到底的分配方向。即首先从最末端开始找空内存。当内存管理刚初始化的时候,内存表全部清零,表示没有任何内存块被占用。


二、分配原理
当指针 p 调用 malloc 申请内存的时候,先判断 p 要分配的内存块数(m),然后从第 n 项开始,向下查找,直到找到 m 块连续的空内存块(即对应内存管理表项为 0),然后将这 m 个内存管理表项的值都设置为 m(标记被占用),最后,把最后的这个空内存块的地址返回指针 p,完成一次分配。注意,如果当内存不够的时候(找到最后也没找到连续的 m 块空闲内存),则返回 NULL 给 p,表示分配失败。


三、释放原理
当 p 申请的内存用完,需要释放的时候,调用 free 函数实现。free 函数先判断 p 指向的内存地址所对应的内存块,然后找到对应的内存管理表项目,得到 p 所占用的内存块数目 m(内存管理表项目的值就是所分配内存块的数目),将这 m 个内存管理表项目的值都清零,标记释放,完成一次内存释放。

四、部分驱动函数

//内存池(32字节对齐)
__align(32) u8 mem1base[MEM1_MAX_SIZE]; //内部SRAM内存池
__align(32) u8 mem2base[MEM2_MAX_SIZE] __attribute__((at(0X68000000)));//外部SRAM内存池
//内存管理表
u16 mem1mapbase[MEM1_ALLOC_TABLE_SIZE]; //内部SRAM内存池MAP
u16 mem2mapbase[MEM2_ALLOC_TABLE_SIZE] __attribute__((at(0X68000000+MEM2_MAX_SIZE)));//外部SRAM内存池MAP
//内存管理参数
const u32 memtblsize[SRAMBANK]={MEM1_ALLOC_TABLE_SIZE,MEM2_ALLOC_TABLE_SIZE};//内存表大小
const u32 memblksize[SRAMBANK]={MEM1_BLOCK_SIZE,MEM2_BLOCK_SIZE};//内存分块大小
const u32 memsize[SRAMBANK]={MEM1_MAX_SIZE,MEM2_MAX_SIZE};//内存总大小




//内存管理控制器
struct _m_mallco_dev mallco_dev=
{
my_mem_init, //内存初始化
my_mem_perused,//内存使用率
mem1base,mem2base,//内存池
mem1mapbase,mem2mapbase,//内存管理状态表
0,0, //内存管理未就绪
};


//复制内存
//*des:目的地址
//*src:源地址
//n:需要复制的内存长度(字节为单位)
void mymemcpy(void *des,void *src,u32 n)
{
u8 *xdes=des;
u8 *xsrc=src;
while(n--)*xdes++=*xsrc++;
}
//设置内存
//*s:内存首地址
//c :要设置的值
//count:需要设置的内存大小(字节为单位)
void mymemset(void *s,u8 c,u32 count)
{
u8 *xs = s;
while(count--)*xs++=c;
}
//内存管理初始化
//memx:所属内存块
void my_mem_init(u8 memx)
{
mymemset(mallco_dev.memmap[memx], 0,memtblsize[memx]*2);//内存状态表数据清零
mymemset(mallco_dev.membase[memx], 0,memsize[memx]);//内存池所有数据清零
mallco_dev.memrdy[memx]=1;//内存管理初始化OK
}
//获取内存使用率
//memx:所属内存块
//返回值:使用率(0~100)
u8 my_mem_perused(u8 memx)
{
u32 used=0;
u32 i;
for(i=0;i {
if(mallco_dev.memmap[memx][i])used++;
}
return (used*100)/(memtblsize[memx]);
}
//内存分配(内部调用)
//memx:所属内存块
//size:要分配的内存大小(字节)
//返回值:0XFFFFFFFF,代表错误;其他,内存偏移地址
u32 my_mem_malloc(u8 memx,u32 size)
{
signed long offset=0;
u32 nmemb; //需要的内存块数
u32 cmemb=0;//连续空内存块数
u32 i;
if(!mallco_dev.memrdy[memx])mallco_dev.init(memx);//未初始化,先执行初始化
if(size==0)return 0XFFFFFFFF;//不需要分配
nmemb=size/memblksize[memx]; //获取需要分配的连续内存块数
if(size%memblksize[memx])nmemb++;
for(offset=memtblsize[memx]-1;offset>=0;offset--)//搜索整个内存控制区
{
if(!mallco_dev.memmap[memx][offset])cmemb++;//连续空内存块数增加
else cmemb=0; //连续内存块清零
if(cmemb==nmemb)//找到了连续nmemb个空内存块
{
for(i=0;i {
mallco_dev.memmap[memx][offset+i]=nmemb;
}
return (offset*memblksize[memx]);//返回偏移地址
}
}
return 0XFFFFFFFF;//未找到符合分配条件的内存块
}
//释放内存(内部调用)
//memx:所属内存块
//offset:内存地址偏移
//返回值:0,释放成功;1,释放失败;
u8 my_mem_free(u8 memx,u32 offset)
{
int i;
if(!mallco_dev.memrdy[memx])//未初始化,先执行初始化
{
mallco_dev.init(memx);
return 1;//未初始化
}
if(offset {
int index=offset/memblksize[memx]; //偏移所在内存块号码
int nmemb=mallco_dev.memmap[memx][index]; //内存块数量
for(i=0;i {
mallco_dev.memmap[memx][index+i]=0;
}
return 0;
}else return 2;//偏移超区了.
}
//释放内存(外部调用)
//memx:所属内存块
//ptr:内存首地址
void myfree(u8 memx,void *ptr)
{
u32 offset;
if(ptr==NULL)return;//地址为0.
offset=(u32)ptr-(u32)mallco_dev.membase[memx];
my_mem_free(memx,offset); //释放内存
}
//分配内存(外部调用)
//memx:所属内存块
//size:内存大小(字节)
//返回值:分配到的内存首地址.
void *mymalloc(u8 memx,u32 size)
{
u32 offset;
offset=my_mem_malloc(memx,size);
if(offset==0XFFFFFFFF)return NULL;
else return (void*)((u32)mallco_dev.membase[memx]+offset);
}


本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

在嵌入式开发中,STM32的时钟系统因其灵活性和复杂性成为开发者关注的焦点。然而,看似简单的时钟配置背后,隐藏着诸多易被忽视的陷阱,轻则导致系统不稳定,重则引发硬件损坏。本文从时钟源选择、PLL配置、总线时钟分配等关键环...

关键字: STM32 时钟系统

在嵌入式系统开发中,STM32系列微控制器的内部温度传感器因其低成本、高集成度特性,广泛应用于设备自检、环境监测等场景。然而,受芯片工艺差异和电源噪声影响,其原始数据存在±1.5℃的固有误差。本文从硬件配置、校准算法、软...

关键字: STM32 温度传感器

在能源效率与智能化需求双重驱动下,AC-DC转换器的数字控制技术正经历从传统模拟方案向全数字架构的深刻变革。基于STM32微控制器的PFM(脉冲频率调制)+PWM(脉冲宽度调制)混合调制策略,结合动态电压调整(Dynam...

关键字: AC-DC STM32

在Linux系统性能优化中,内存管理与网络连接处理是两大核心领域。vm.swappiness与net.core.somaxconn作为关键内核参数,直接影响系统在高负载场景下的稳定性与响应速度。本文通过实战案例解析这两个...

关键字: Linux 内存管理

当前智能家居产品需求不断增长 ,在这一背景下 ,对现有浇花装置缺陷进行了改进 ,设计出基于STM32单片机的全 自动家用浇花机器人。该设计主要由机械结构和控制系统构成 ,机械结构通过麦克纳姆轮底盘与喷洒装置的结合实现机器...

关键字: STM32 麦克纳姆轮 安全可靠 通过性强

用c++编程似乎是让你的Arduino项目起步的障碍吗?您想要一种更直观的微控制器编程方式吗?那你需要了解一下Visuino!这个图形化编程平台将复杂电子项目的创建变成了拖动和连接块的简单任务。在本文中,我们将带您完成使...

关键字: Visuino Arduino ESP32 STM32

基于STM32与LoRa技术的无线传感网络凭借其低功耗、广覆盖、抗干扰等特性,成为环境监测、工业自动化等场景的核心解决方案。然而,如何在复杂电磁环境中实现高效休眠调度与动态信道优化,成为提升网络能效与可靠性的关键挑战。本...

关键字: STM32 LoRa

在实时控制系统、高速通信协议处理及高精度数据采集等对时间敏感的应用场景中,中断响应延迟的优化直接决定了系统的可靠性与性能上限。STM32系列微控制器凭借其灵活的嵌套向量中断控制器(NVIC)、多通道直接内存访问(DMA)...

关键字: STM32 DMA

数字电源技术向高功率密度、高效率与高动态响应方向加速演进,STM32微控制器凭借其基于DSP库的算法加速能力与对LLC谐振变换器的精准控制架构,成为优化电源动态性能的核心平台。相较于传统模拟控制或通用型数字控制器,STM...

关键字: STM32 数字电源

STM32微控制器凭借其针对电机控制场景的深度优化,成为高精度、高可靠性驱动系统的核心选择。相较于通用型MCU,STM32在电机控制领域的核心优势集中体现在FOC(磁场定向控制)算法的硬件加速引擎与PWM死区时间的动态补...

关键字: STM32 电机控制
关闭