嵌入式开发中内存管理的7个技巧

2022-07-20 11:06:08

        在实时系统中管理内存是一项挑战。有许多方面需要考虑,例如代码空间内存管理、RAM内存管理、内存优化以及它们如何影响性能等等。下面是七个通用的技巧,可以帮助嵌入式开发人员开始管理他们的内存。


        避免malloc

  在需要确定性计时的实时系统中,使用malloc动态分配内存是一个坏主意。首先,典型的malloc实现是不确定的,这意味着即使能够分配内存,也不能保证分配内存需要多长时间。使用malloc会产生许多实时问题,例如


  堆碎片

  分配内存失败

  不确定的行为

  不要试探命运,避开malloc就好。


        监控内存映射文件

  跟踪ROM和RAM去向的一个好方法是查看编译器生成的内存映射文件。这个文件将告诉开发人员函数的代码大小,以及为它们的变量分配了多少内存。不同工具的地图文件通常略有不同,因此需要开发人员打开文件并手动浏览它们,以确定它们的内存使用情况。开发人员可以编写一个Python脚本来读取文件,并提供机制来查看哪里的优化和代码返工是最有效的。


        使用内存块池进行动态内存分配

  有时候,嵌入式开发人员无法摆脱静态分配所有内存的问题。应用程序可能无法提前知道需要多少内存,或者预先分配所有内存可能需要比微控制器上可用内存更多的RAM。不想使用内存分配或字节池的话,开发人员应该怎么做呢?答案是使用块内存池。块内存池在固定的内存块中分配内存,不像字节内存池一次分配一个字节。块内存池的算法是确定性的和快速的!因此,如果你需要动态分配内存,请使用块内存池。(大多数实时操作系统都有)。


    仅将内存字节池用于任务堆栈分配

  RTOS通常包含许多供开发人员分配内存的机制。选项通常是字节和块内存池。字节内存池的行为与堆非常相似,并像malloc一样分配内存。有一些实现是确定性的,但是仍然存在堆碎片的潜在问题。出于这些原因,强烈建议开发人员在应用程序开始时只使用字节池来分配内存,例如缓冲区或任务堆栈。


        静态分配内存

  静态分配内存意味着所有的内存分配都是在编译时而不是运行时执行的。这是确保确定性的最安全的方法,并且不会有内存碎片问题。当开发人员不能在编译时分配内存时,一些动态分配任务控制块的RTOS就是这种情况,尝试在系统初始化期间执行所有的动态内存分配。在启动时分配内存看起来像是静态分配的。


        尽量减少RTOS对象的使用

  通过RTOS创建的每个对象,比如任务、信号量、消息队列等等,都有一个与之相关联的控制块。控制块本质上是一种结构,它保存了对象执行其功能所必需的各种参数。在资源受限的环境中工作的嵌入式开发人员会希望尽量减少他们在应用程序中使用的对象数量。如果开发人员不密切监控RTOS对象的代码,它们会很快开始使用大量的RAM。




        更改编译器的默认优化设置

  在运行时处理内存并不是开发人员会遇到的唯一内存管理问题。有时,开发人员需要尝试优化RAM和ROM,以便最大限度地降低他们使用的微控制器的BOM成本。在许多情况下,编译器(如GCC)默认不包含最佳优化设置,代码通常臃肿而缓慢。不要依赖默认的编译器设置。查看编译器手册,了解可用于调整RAM和ROM大小的优化和设置。


        结论

  实时嵌入式软件开发人员经常为管理他们的系统内存而苦恼。由于没有跟踪内存的去向,它们可能会很快耗尽代码空间,或者出现与堆碎片相关的运行时问题。我们在本文中研究的技巧看起来很简单,但是通过遵循它们,嵌入式开发人员不仅可以更好地管理他们的内存占用,还可以省去调试一个濒临内存灾难的系统的麻烦。