在嵌入式实时操作系统中使用malloc()和free()的危险
Posted ORI2333
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在嵌入式实时操作系统中使用malloc()和free()的危险相关的知识,希望对你有一定的参考价值。
前言
本文会从以下几个方面阐述使用malloc()
和 free()
函数动态的分配/释放内存的危害。
存在的问题
在嵌入式中无法很难实现对内存的动态映射(虚拟内存机制),尤其是裸机中。即使在嵌入式操作系统中,因为是实时性的要求,很少会用动态映射。
嵌入式设备自身RAM较小
嵌入式设备中RAM往往就几百KB大小,在小型的嵌入式设备中会更加紧张,RAM的使用更是寸土寸金。
函数自身的实现较为复杂
malloc()
和free()
自身的实现就比较复杂,自身就占据了很大一块代码空间。
安全性
在申请内存,使用完毕后,必须需要手动释放,若不及时释放容易造成内存泄漏。
另外malloc
函数常会表现出极其不可预测的特性,在多核多系统上进行多线程开发往往会遇到问题。
在signal中使用会产生错误与陷阱。
参考文章:https://blog.csdn.net/qq_40334837/article/details/96423711
不确定性
每次调用内存分配与释放函数执行的时间可能都不一样。每次申请内存都需要根据存储数据的长度,在内存中寻找一个合适大小的空闲内存块,然后将数据存储在内存块中。而寻找这样一个空闲内存块所耗费的时间是不确定的,因此对于实时系统来说,是不可接受的。
实时操作系统必须保证内存块的分配在可预测的时间内完成,否则实时任务对外部事件的响应也将变得不可确定。
会造成内存碎片化
过多的malloc
与free
容易造成内存碎片,致使可使用的堆内存变小。尤其是在对单片机等没有MMU的芯片编程时,慎用malloc
与free
。
在分配和释放过程中,会使内存空间中存在一些小的内存块,它们的地址不连续,不能够作为连续的内存块分配,所以一定会在某个时间,系统已经无法分配到合适的内存,导致系统瘫痪。
使链接器配置更加复杂
可能覆盖其它地方内存
如果允许堆空间的生长方向覆盖其他变量占据的内存,它们会成为debug
的灾难。
解决方案
内存池
内存池(Memory Pool),又被称为固定大小区块规划(fixed-size-blocks allocation),允许程序员以类似 C语言 的 malloc 或是 C++ 的 new 操作数进行动态的存储器规划。对于其它动态存储器规划的实践来说,因为会变动存储器区块大小导致的碎片问题,导致在实时系统上受限于性能因此,根本无法使用。内存池提供了一个更有效率的解决方案:预先规划一定数量的存储器区块,使得整个程序可以在运行期规划 (allocate)、使用 (access)、归还 (free) 存储器区块。
有许多实时操作系统采用了内存池。
优点:
- 效率高,先后对来说简单,且时间复杂度低
- 每次申请的大小都是固定的,可以有效地防止内存碎片化。
- 简单,易实现。
- 内存的申请和释放都在可控范围之内。
RTOS内存管理模块
当前市面上的绝大部分RTOS
(例如ucos
、RT-Thread
、liteOS
等)都实现了内存管理模块,可以根据各RTOS的方法进行申请释放内存。
最后
笔者才疏学浅,对此理解还不是很深刻,对底层理解有限,写此文只是总结个人目前对此的理解,后续若还有深入,必会更新。同时希望大佬多多指点!
以上是关于在嵌入式实时操作系统中使用malloc()和free()的危险的主要内容,如果未能解决你的问题,请参考以下文章