基于stm32f103zet6的内存管理的学习

发布者:NexusDream最新更新时间:2015-05-06 来源: 51hei关键字:stm32f103zet6  内存管理 手机看文章 扫描二维码
随时随地手机看文章
主要是依照原子哥哥的代码来初步了解或者说学习一下内存管理,特别对于我们这个想往嵌入式方向发展的人来说,内存管理应该是一种艺术的。

今天在对原子的代码稍作修改是可以进行内存分配和回收的,所以开始深入分析一下这个代码的实现过程。一、所谓的内存管理内存管理,是指软件运行时对计算机内存资源的分配和使用的技术。其最主要的目的是如何高效,快速的分配,并且在适当的时候释放和回收内存资源。

二、代码分析

1、首先了解一下一个数据结构,这是一个声明

 

/*************************** 内存管理控制 **********************************************/ typedef struct {void (*init)(u8);//初始化u8 (*perused)(u8); //内存使用率u8 *membase[2];//内存池 管理2个区域的内存u16 *memmap[2]; //内存管理状态表u8 memrdy[2]; //内存管理是否就绪}_m_mallco_dev;

 

成员包括两个函数指针(该指针指向函数),两个指针数组和一个u8类型的数组,具体分析下这几个成员的含义,那么首先要找到这个

 

_m_mallco_dev mallco_dev={mem_init,//内存初始化mem_perused,//内存使用率mem1base,mem2base,//内存池 mem1mapbase,mem2mapbase,//内存管理状态表0,0, //内存管理未就绪};这才是真正定义的地方,现在就可以了解这个几个成员的具体功能了。

 

a、初始化中 mem_init,mem_perused,这是两个函数,为什么可以这样用呢(直接用函数名)?

 可以这样理解么,函数名就像数组名一样,只不过函数名是代码段的指针,而数组名是数据段的指针 ,所以这里函数名就是给函数指针赋值了。当然函数指针并不能说是等于指针的,就像数组一样,数组名不等于指针的。总书记和主席还是不一样的。所以暂时可以这样理解,函数名虽然代表了一个地址,但是这个值是确定了的,但是指针是可以指向别的地址的。就这样!这样写只不过是为了方便我们访问罢了。可以按自己的需要修改!
那么这两个函数的作用?这才是我们最关心的,看这个
void 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 } b、注释很明确,那么接下来就是分析这个三句话的作用,没办法,我无法做到,一眼能看出究竟。
mymemset(mallco_dev.memmap[memx], 0,memtblsize[memx]*2);等价于mymemset(mem1base, 0,0x500*2)
它里面的内容很简单就是
void mymemset(void *s,u8 c,u32 count) { u8 *xs = s; while(count--)*xs++=c; }以mem1base为首地址的大小为0xa00的内容清0,那么mem1base又是什么呢?接下来看看
__align(4) u8 mem1base[MEM1_MAX_SIZE];这明显是4字节对齐的内部SRAM的地址,也就是我们的flash里面的地址。所以这就实现了对我们内部flash0xa00的内容清零,好的继续看下面的
 
c、 mymemset(mallco_dev.membase[memx], 0,memsize[memx]); //内存池所有数据清零  
 
自然地这个也是一个意思,清零,唯一不同的就是代表的意思不一样,到底是内存池数据清零,还是状态表的清零,我们看不出来,那么只有继续分析了。清零完成就给相应的数组元素填充1表示完成标志。至此我们第一个初始化成员就分析完毕!!
2、下面开始分析第二个成员perused函数
先看函数如何定义的/*************************************************************************************** 
名 称: mem_perused
* 功 能: 获取内存使用率
* 参 数: *memx:所属内存块
* 返 回 值: 使用率(0~100)**************************************************************************************
/u8 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]); 
} 这里可以看到出现一个这样的表达式,需要仔细分析!mallco_dev.memmap[memx][i]
分解一下,还是一样,这个是指针数组,也就是数组里面存放的是指针,那么这里给它赋值为一个数组名 mem1mapbase,但是访问的时候还是可以用下表来访问的。那么可以替换为:if(mem1mapbase[i]) used++;看到没,这还是我们之前访问过了的那个数组,只不过这里是当非零的时候执行used++,也就是我们占用了才会进行++。那么作用就是:used表示的是占用了的大小。(used*100)/(memtblsize[memx])表示的就是占用值,memtblsize[memx]使我们分配的总的大小,到这里那么第二个成员也分析完毕。
3、后面这几个成员变量,之前就已经分析过了。mem1base,mem2base,//内存池mem1mapbase,mem2mapbase,//内存管理状态表0,0, 这里就不详述了。这个数据结果分析至此,那么接下来看我们分配内存的过程究竟如何实现?
三、分配内存
首先看一个核心代码如下

[page]

/*************************************************************************************** 
名 称: mem_malloc
* 功 能: 内存分配(内部调用)
* 参 数: *memx:所属内存块*size:要分配的内存大小(字节)
* 返 回 值: 0XFFFFFFFF,代表错误;其他,内存偏移地址
**************************************************************************************
u32 mem_malloc(u8 memx,u32 size)

      signed long offset=0; 
     u16 nmemb;//需要的内存块数
     u16 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;//未找到符合分配条件的内存块
}

1、首先进行的是一个初始化,初始化的作用上面已经提及,再次不赘述,这里我们假设一块内存为40个block(一个block为32字节,因为内存太小)那么接下来可以看到是通过我们传入的参数计算出了总的内存块数,并且如果不整除的话,还会多分配一个内存块。nmemb = 64。内存管理表内容用于检测该块是否被占用。注意这里的内存块一定是连续的,

内存管理表的项值代表的意义为:当该项值为0的时候,代表对应的内存块未被占用,当该项值非零的时候,代表该项对应的内存块已经被占用,其数值则代表被连续占用的内存块数。比如某项值为10,那么说明包括本项对应的内存块在内,总共分配了10个内存块给外部的某个指针。
 

之后就是标志代码了,注释很详细,接下来看看这个返回偏移地址的代码:offset*memblksize[memx],这个偏移值就是memblksize【0】 = 0x20*offset

2、好的,接下来就是将偏移值转化为所谓的外部指针了。

 

else return (void*)((u32)mallco_dev.membase[memx]+offset); 
这行代码,返回一个void 类型的首地址就是mallco_dev.membase[0],这样我们就得到了一个地址了。

 

3、然后就是

 

p=mymalloc(sramx,2048); //申请2K字节if(p!=NULL)sprintf((char*)p,"This is xiaobing's Memory Malloc Test!!");//向p写入一些内容 printf("%s",p); //显示P的内容

 

这就是把这个地址传给指针p,那么我们接着就可以给指针p赋值内容了,这回爽到了吧?

打印指针内容。

4、很重要的一步

myfree(sramx,p);//释放内存,否则资源难以回收
 

记得要释放内存呀,看代码函数

 

/*************************************************************************************** 名 称: mem_free* 功 能: 释放内存(内部调用)* 参 数: *memx:所属内存块* offset:内存地址偏移* 返 回 值: 0,释放成功;1,释放失败; **************************************************************************************/u8 mem_free(u8 memx,u32 offset) { int i; if(!mallco_dev.memrdy[memx])//未初始化,先执行初始化{mallco_dev.init(memx); return 1;//未初始化 } if(offset

 

 

mallco_dev.memmap[memx][offset+i]=nmemb;标注非空了,那么也就是说,我们占用了的那些内存块就会标记为nmenb,否则就是0。

 

当我们释放完内存后,记得加上这个  P = NULL.

只是为了防止产生野指针,谁能保证,每次运行程序的时候,给变量分配地址的时候,不会使用到这个地址呢??所以这是个好习惯!

关键字:stm32f103zet6  内存管理 引用地址:基于stm32f103zet6的内存管理的学习

上一篇:S3C2440中断代码的深层次分析
下一篇:基于STM32原子战舰板内存管理源码

推荐阅读最新更新时间:2024-03-16 14:00

基于stm32f103zet6之NRF905无线模块的学习
stm32f103zet6简介 STM32F系列属于中低端的32位ARM微控制器,该系列芯片是意法半导体(ST)公司出品,其内核是Cortex-M3。 该系列芯片按片内Flash的大小可分为三大类:小容量(16K和32K)、中容量(64K和128K)、大容量(256K、384K和512K)。 芯片集成定时器,CAN,ADC,SPI,I2C,USB,UART,等多种功能。 NRF905简介 nRF905是挪威Nordic公司推出的一款单片射频发射器芯片,采用32引脚5mm 5mm QFN封装,工作于433、868、915MHz 3个ISM(工业、科学和医学)频道,其中国内433频段可以免费使用。nRF905由频率合成器、接
[单片机]
基于<font color='red'>stm32f103zet6</font>之NRF905无线模块的学习
stm32内存管理总结
一、内存管理简介 内存管理,是指软件运行时对计算机内存资源的分配和使用的技术。其最主要的目的是如何高效,快速的分配,并且在适当的时候释放和回收内存资源。内存管理的实现方法有很多种,他们其实最终都是要实现 2 个函数:malloc 和 free;malloc 函数用于内存申请,free 函数用于内存释放。本章,我们介绍一种比较简单的办法来实现:分块式内存管下面我们介绍一下该方法的实现原理,如图 42.1.1 所示: 内存管理表的项值代表的意义为:当该项值为 0 的时候,代表对应的内存块未被占用,当该项值非零的时候,代表该项对应的内存块已经被占用,其数值则代表被连续占用的内存块数。比如某项值为
[单片机]
stm32<font color='red'>内存管理</font>总结
ARM内存管理MMU详解
嵌入式系统中,存储系统差别很大,可包含多种类型的存储器件,如 FLASH , SRAM , SDRAM , ROM 等,这些不同类型的存储器件速度和宽度等各不相同;在访问存储单元时,可能采取平板式的地址映射机制对其操作,或需要使用虚拟地址对其进行读写;系统中,需引入存储保护机制,增强系统的安全性。为适应如此复杂的存储体系要求, ARM 处理器中引入了存储管理单元来管理存储系统。 一 内存管理单元( MMU )概述 在 ARM 存储系统中,使用 MMU 实现虚拟地址到实际物理地址的映射。为何要实现这种映射?首先就要从一个嵌入式系统的基本构成和运行方式着手。系统上电时,处理器的程序指针从 0x0 (或者是由 0Xffff_0000
[单片机]
Linux内存管理学习3 —— head.S中的段页表的建立
平台 TQ2440 Qemu+vexpress-ca9 Linux-4.10.17 正文 继续分析head.S: 1 ldr r13, =__mmap_switched @ address to jump to after 2 @ mmu has been enabled 3 badr lr, 1f @ return (PIC) address 4 mov r8, r4 @ set TTBR1 to swapper_pg_dir 5 ldr r12, 6 add r12, r12, r10 7 ret r12 8 1:
[单片机]
一个动态内存管理模块的实现
    摘要: 介绍一个动态内存管理模块,可以有效地检测C程序中内存泄漏和写内存越界等错误,适用于具有标准C语言开发环境的各种平台。     关键词: C语言 动态内存 内存泄漏 写越界 引言 当前,绝大多数嵌入式平台上的软件都采用C语言编写。除了代码简洁、运行高效之外,灵活操作内存的能力更是C语言的重要特色。然而,不恰当的内存操作通常也是错误的根源之一。如“内存泄漏” ——不能正确地释放已分配的动态内存,就是一种非常难于检测的存错误。持续的内存泄漏会使程序性能下降到最终完全不能运行,进而影响到所有其它有动态内存需求的程序,在某些相对简单的嵌入式平台上甚至会妨碍操作系统的运转。再如“写内存越界”,一
[缓冲存储]
ARM 系列 -- FS2410 开发板上启用 MMU 实现虚拟内存管理
一、背景 FS2410 开发板上的 ARM 核心为 ARM920T, ARM920T 代表着什么呢? 其实ARM920T = ARM9 core + MMU + Cache,也就是说 ARM920T 为实现虚拟内存管理提供了硬件条件,这个硬件条件就是 MMU -- 内存管理单元。前面的实验我们程序里的地址都是直接对应物理地址,也就是说虚拟地址等同于物理地址,而今借助 MMU 我们可以实现虚拟内存管理,程序里面的地址不再被直接送到地址总线,而是先通过 MMU,由 MMU 来实现虚地址到物理地址的映射。这有什么意义?想象有这么两个程序,它们有相同的虚拟地址,但由于运行时其虚地址分别被映射到不同的物理地址,所以它们各行其道、和平共处,
[单片机]
ARM 系列 -- FS2410 开发板上启用 MMU 实现虚拟<font color='red'>内存管理</font>
STM32学习笔记一一内存管理
1.简介 内存管理:指软件运行时对计算机内存资源的分配和使用的技术。其最主要的目的是如何高效,快速的分配,并且在适当的时候释放和回收内存资源。 内存管理的实现方法有很多种,最终都是要实现两个函数: malloc 和 free。 malloc :函数用于内存申请; free: 函数用于内存释放。 1.1 分块式内存管理原理 由上图可知,分块式内存管理由内存池和内存管理表两部分组成。内存池被等分为 n块,对应的内存管理表,大小也为 n,内存管理表的每一个项对应内存池的一块内存。 内存管理表的项值代表的意义:当该项值为 0 的时候,代表对应的内存块未被占用;当该项值非零的时候,代表该项对应的内存块已经被占用,其数
[单片机]
STM32学习笔记一一<font color='red'>内存管理</font>
s3c2440 内存管理单元MMU学习笔记
学习了S3C2440内存管理单元MMU,主要参考了《嵌入式Linux应用开发完全手册》 (下载见 http://www.linuxidc.com/Linux/2011-01/31114.htm )。有两篇文章也说得很详细,分别是 http://www.linuxidc.com/Linux/2011-09/43526.htm 与 http://www.linuxidc.com/Linux/2011-09/43525.htm 感兴趣的可以参考一下,我就不重复内容了。但是它们在MMU地址变换过程这一块说得不太好理解。在此,我就按照我的理解将《嵌入式Linux应用开发完全手册》的相关内容解释一下,图片加点注释。如有错误,请大家不吝赐教,我
[单片机]
s3c2440 <font color='red'>内存管理</font>单元MMU学习笔记
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved