0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

嵌入式系统裸机编程的内存管理简介

FPGA之家 来源:嵌入式大杂烩 作者:嵌入式大杂烩 2020-12-28 09:44 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

嵌入式裸机编程中,作为一名初级的CODER。经常要与CPU、内存等打交道。CPU作为系统的动力源,其重要程度不言而喻。 但是,在裸机编程中,对内存的管理也不容忽视。如果稍微不注意,轻则,可能造成内存泄漏,重则造成内存访问异常。导致系统死机。 嵌入式产品,对稳定性要求及其严格。动不动就死机,那可就麻烦大了。以下,是我本人对嵌入式系统裸机编程的内存管理的一些简介。

1、尽量不使用库自带的malloc和free。

malloc和free在PC编程中是很好用的一种内存分配手段。但是,其在嵌入式中,就未必好用了。由于嵌入式裸机编程中,无MMU,即内存管理单元。无法实现对内存进行动态映射(不明白什么叫动态映射的同学,可以参考网上的资料)。也就是说,实际上,malloc和free并不能实现动态的内存的管理。这需要在启动阶段专门给其分配一段空闲的内存区域作为malloc的内存区。如STM32中的启动文件startup_stm32f10x_md.s中可见以下信息:
其中,Heap_Size即定义一个宏定义。数值为 0x00000800。Heap_Mem则为申请一块连续的内存,大小为 Heap_Size。简化为C语言版本如下:
#define Heap_Size 0x00000800unsigned char Heap_Mem[Heap_Size] = {0};
在这里申请的这块内存,在接下来的代码中,被注册进系统中给malloc和free函数所使用:
__user_initial_stackheapLDR     R0, =  Heap_Mem  ;  返回系统中堆内存起始地址LDR     R1, =(Stack_Mem + Stack_Size)LDR     R2, = (Heap_Mem +  Heap_Size); 返回系统中堆内存的结束地址LDR     R3, = Stack_MemBX      LR
就如上面分析的那样,其实,在裸机编程的时候,对堆内存的管理。并非是智能化的,并非你想申请多少就多少。而是使用一块固定的内存用作堆内存的分配。这在设计的时候,往往不是最佳的方案。这块内存,如果被多次按照不同的大小进行申请,就会造成内存碎片。最终导致无法申请到足够的内存。导致系统运行出错。这在原本内存就已经很少的嵌入式系统中,更是不能接受的。所以,建议是把那个Heap_Size设置成 0 吧。放弃其使用吧。 而更为致命的是,有些malloc,free函数,由于工程人员的偷懒。实现甚至可能如下:
unsigned char mem_buffer[512];unsigned char *mem_offset = & mem_buffer;void *malloc(int size){unsigned char *tmp = mem_offset;    mem_offset += size;return (void *)tmp;}void free(void *mem){ mem_offset = mem;}

2、不用malloc、free的原因

一般单片机的内存都比较小,而且没有MMU,malloc 与free的使用容易造成内存碎片。而且可能因为空间不足而分配失败,从而导致系统崩溃,因此应该慎用,或者自己实现内存管理。如:《一个简单而强大的单片机内存管理器》 在函数中使用malloc,如果是大的内存分配,而且malloc与free的次数也不是特别频繁,使用malloc与free是比较合适的,但是如果内存分配比较小,而且次数特别频繁,那么使用malloc与free就有些不太合适了。 因为过多的malloc与free容易造成内存碎片,致使可使用的堆内存变小。尤其是在对单片机等没有MMU的芯片编程时,慎用malloc与free。如果需要对内存的频繁操作,可以自己实现一个内存管理。 使用动态内存分配,应分不同的应用场合。 对于在操作系统上运行的程序,实际的物理内存分配与释放使用操作系统来实现的,即使程序调用了 malloc和free物理内存并不会马上变化。物理内存的变化,直到系统的内存管理操作时才发生。 对于裸机跑在MCU上的程序,分配与释放内存都会造成实际物理内存的变化。因为此时物理内存的分配是由自己实现的,而内存管理我们自己并没有去做。这样,盲目的使用malloc与free恰恰并不好,反而会造成内存的不恰当使用。甚至于内存溢出。 所以,动态内存的使用前提是有一套好的内存管理方法,这样动态内存的使用才会合理使用内存。如果没有合适的内存管理代码,还是用静态内存好一些。

3、 更好的替代方案:内存池。

可能有些同学,觉得:内存池,这是什么东西? 内存池,简洁地来说,就是预先分配一块固定大小的内存。以后,要申请固定大小的内存的时候,即可从该内存池中申请。用完了,自然要放回去。注意,内存池,每次申请都只能申请固定大小的内存。这样子做,有很多好处: (1)每次动态内存申请的大小都是固定的,可以有效防止内存碎片化。(至于为什么,可以想想,每次申请的都是固定的大小,回收也是固定的大小) (2)效率高,不需要复杂的内存分配算法来实现。申请,释放的时间复杂度,可以做到O(1)。 (3)实现简单,易用。 (4)内存的申请,释放都在可控的范围之内。不会出现以后运行着,运行着,就再也申请不到内存的情况。 内存池,并非什么很厉害的技术。实现起来,其实可以做到很简单。只需要一个链表即可。在初始化的时候,把全局变量申请来的内存,一个个放入该链表中。在申请的时候,只需要取出头部并返回即可。在释放的时候,只需要把该内存插入链表。以下是一种简单的例子(使用移植来的linux内核链表,对该链表的移植,以后有时间再去分析):
#define MEM_BUFFER_LEN  5    //内存块的数量#define MEM_BUFFER_SIZE 256 //每块内存的大小
//内存池的描述,使用联合体,体现穷人的智慧。就如,我一同学说的:一个字节,恨不得掰成8个字节来用。typedef union mem {struct list_head list;unsigned char buffer[MEM_BUFFER_SIZE];}mem_t;
static union mem gmem[MEM_BUFFER_LEN];
LIST_HEAD(mem_pool);
//分配内存void *mem_pop(){    union mem *ret = NULL;    psr_t psr;
    psr = ENTER_CRITICAL();    if(!list_empty(&mem_pool)) { //有可用的内存池         ret = list_first_entry(&mem_pool, union mem, list);        //printf("mem_pool = 0x%p  ret = 0x%p
", &mem_pool, &ret->list);        list_del(&ret->list); } EXIT_CRITICAL(psr); return ret;//->buffer;}

//回收内存void mem_push(void *mem){    union mem *tmp = NULL;     psr_t psr;
    tmp = (void *)mem;//container_of(mem, struct mem, buffer);    psr = ENTER_CRITICAL();    list_add(&tmp->list, &mem_pool);    //printf("free = 0x%p
", &tmp->list);
    EXIT_CRITICAL(psr);}
//初始化内存池void mem_pool_init(){    int i;    psr_t psr;    psr = ENTER_CRITICAL();    for(i=0; i        list_add(&(gmem[i].list), &mem_pool);        //printf("add mem 0x%p
", &(gmem[i].list)); } EXIT_CRITICAL(psr);}
责任编辑:xj
原文标题:嵌入式裸机编程中使用malloc、free会怎样?

文章出处:【微信公众号:FPGA之家】欢迎添加关注!文章转载请注明出处。


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 嵌入式
    +关注

    关注

    5186

    文章

    20151

    浏览量

    328894
  • 编程
    +关注

    关注

    90

    文章

    3708

    浏览量

    96765
  • Free
    +关注

    关注

    0

    文章

    16

    浏览量

    11339
  • 内存管理
    +关注

    关注

    0

    文章

    169

    浏览量

    14811

原文标题:嵌入式裸机编程中使用malloc、free会怎样?

文章出处:【微信号:zhuyandz,微信公众号:FPGA之家】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    嵌入式应掌握的几种能力

    1. 编程语言 基本掌握嵌入式必备的编程语言。C语言为主,C++为辅。在资源有限的情况下,大多数嵌入式产品还是使用C语言为主的,特别是底层驱动开发。上层应用开发大多用C,在一些资源比
    发表于 12-08 06:05

    CW32嵌入式软件开发的必备知识

    合适的数据结构和算法。 3 、计算机体系结构 了解处理器架构,如ARM、x86等,以及指令集和内存管理。 熟悉嵌入式系统的硬件组成,如微控制器、FPGA、DSP等。 可以很熟练地根据C
    发表于 11-28 07:48

    嵌入式开发的关键点介绍

    嵌入式开发在现代科技中扮演着非常重要的角色。随着物联网的发展,嵌入式系统的需求也越来越大。嵌入式开发不仅需要开发人员具备深入的硬件知识和编程
    发表于 11-13 08:12

    嵌入式实时操作系统的特点

    操作系统具备高效的中断处理机制,能够快速响应和处理系统的中断事件。 资源管理:实时嵌入式操作系统提供有效的资源
    发表于 11-13 06:30

    嵌入式需要掌握哪些核心技能?

    : 1)C语言与底层编程 核心地位:C语言是嵌入式开发的基石,需精通指针操作、内存管理、位运算,直接操控硬件资源。 延伸技能:C++用于复杂项目架构设计,汇编语言优化底层性能(如启动代
    发表于 10-21 16:25

    入行嵌入式应该怎么准备?

    知识: 一、C/C++编程C/C++是嵌入式系统开发中最常用的编程语言。熟练掌握C/C++语言将使你能够理解和编写底层驱动程序、操作系统
    发表于 08-06 10:34

    嵌入式和单片机,是同一个东西吗?

    (RTOS)或没有任何操作系统裸机编程。软件方面,嵌入式系统可能使用专门的编程语言,如C、C+
    发表于 07-09 10:20

    Linux嵌入式和单片机嵌入式的区别?

    : 单片机嵌入式 :开发环境相对简单,通常使用C语言或汇编语言进行编程,开发工具包括Keil、IAR等。 Linux嵌入式 :开发环境较为复杂,除了需要掌握C语言,还需要了解Linux操作
    发表于 06-20 09:46

    嵌入式开发入门指南:从零开始学习嵌入式

    基础 3. 学习路径推荐第一阶段:熟悉开发环境(如Keil、IAR、STM32)第二阶段:掌握裸机编程与驱动开发第三阶段:学习RTOS(实时操作系统)如FreeRTOS第四阶段:深入理解Linux
    发表于 05-15 09:29

    嵌入式编程设计模式

    嵌入式编程设计模式,介绍如何使用设计模式为嵌入式系统创建高效且优化的C语言设计。 纯分享贴,有需要可以直接下载附件获取完整资料! (如果内容有帮助可以关注、点赞、评论支持一下哦~
    发表于 04-15 14:47

    CPLD 在嵌入式系统中的应用

    在现代电子设计领域,复杂可编程逻辑器件(CPLD)因其灵活性、成本效益和快速开发周期而在嵌入式系统中扮演着重要角色。 1. CPLD简介 CPLD是一种集成电路,其内部包含可
    的头像 发表于 01-23 09:50 1760次阅读

    如何提高嵌入式代码质量?

    。 3. 嵌入式操作系统的使用:选择和配置合适的嵌入式操作系统(如FreeRTOS、uC/OS等),能够提供任务调度、内存
    发表于 01-15 10:48

    嵌入式主板的概述与发展

    未来发展趋势进行深入探讨。嵌入式主板的基本概念嵌入式主板是指为嵌入式系统设计的电路板,它通常集成了微处理器、内存、输入输出接口等关键组件。与
    的头像 发表于 01-13 16:30 1185次阅读
    <b class='flag-5'>嵌入式</b>主板的概述与发展

    新手怎么学嵌入式?

    嵌入式系统的发展,嵌入式操作系统也变得越来越重要。学习嵌入式操作系统可以帮助你更好地
    发表于 12-12 10:51

    嵌入式系统开发与硬件的关系 嵌入式系统开发常见问题解决

    系统开发与硬件关系的几个关键点: 硬件依赖性 :嵌入式系统的软件必须能够在特定的硬件上运行,这包括处理器、内存、输入/输出接口等。软件必须能够充分利用硬件的特性,同时绕过其限制。 资源
    的头像 发表于 12-09 09:38 1469次阅读