Memory management 为什么不应该';在嵌入式系统中,我们有不同大小的动态分配内存

Memory management 为什么不应该';在嵌入式系统中,我们有不同大小的动态分配内存,memory-management,embedded,dynamic-memory-allocation,static-memory-allocation,Memory Management,Embedded,Dynamic Memory Allocation,Static Memory Allocation,我听说在嵌入式系统中,我们应该使用一些预先分配的固定大小的内存块(比如buddy memory system?)。有人能给我详细解释一下原因吗? 谢谢,在嵌入式系统中,内存非常有限。因此,如果您偶尔只丢失一个字节的内存(因为您分配了它,但没有释放它),这将很快消耗掉系统内存(1 GB的RAM,泄漏率为1/小时需要时间。如果您有4kB的RAM,则不需要那么长) 从本质上讲,避免动态内存的行为是为了避免程序中错误的影响。由于静态内存分配是完全确定的(而动态内存分配则不是),因此仅使用静态内存分配就可

我听说在嵌入式系统中,我们应该使用一些预先分配的固定大小的内存块(比如buddy memory system?)。有人能给我详细解释一下原因吗?
谢谢,

在嵌入式系统中,内存非常有限。因此,如果您偶尔只丢失一个字节的内存(因为您分配了它,但没有释放它),这将很快消耗掉系统内存(1 GB的RAM,泄漏率为1/小时需要时间。如果您有4kB的RAM,则不需要那么长)

从本质上讲,避免动态内存的行为是为了避免程序中错误的影响。由于静态内存分配是完全确定的(而动态内存分配则不是),因此仅使用静态内存分配就可以抵消此类错误。其中一个重要因素是嵌入式系统通常用于安全关键应用。几小时的停机可能会造成数百万美元的损失,否则可能会发生事故

此外,根据动态内存分配器的不同,不确定性也可能需要不确定的时间,这可能会导致更多的错误,特别是在依赖紧时间的系统中(感谢您提到这一点)。这种类型的错误通常很难测试和复制,因为它依赖于非常特定的执行路径

此外,嵌入式系统通常没有MMU,因此没有什么比内存保护更好的了。如果内存不足,并且处理该情况的代码不起作用,那么最终可能会以指令的形式执行任何内存(可能会发生不好的事情!然而,这种情况只与动态内存分配间接相关)

如前所述,碎片化也是一种危险。它是否可能发生取决于您的具体用例,但在嵌入式系统中,由于碎片,很容易丢失50%的RAM。只有分配始终具有完全相同大小的块,才能避免碎片

性能也起作用(取决于用例-谢谢)。静态分配的内存由编译器分配,而
malloc()
等需要在设备上运行,因此会消耗CPU时间(和电源)

许多嵌入式操作系统(如ChibiOS)支持某种动态内存分配器。但使用它只会增加意外问题发生的可能性

请注意,这些参数通常通过使用较小的静态分配内存池来避免。这不是一个真正的解决方案,因为这些池中的内存可能仍然不足,但这只会影响系统的一小部分

正如所指出的,一些系统甚至没有足够的资源来支持动态内存分配

注:大多数编码标准,包括和DO-178B(适用于关键航空电子设备代码-谢谢)禁止使用malloc


我还假设禁止
malloc()
,因为--但是我没有访问标准本身的权限。

这里不使用动态堆内存分配的主要原因基本上是:

a) 决定论和, b) 内存碎片

在那些小型嵌入式应用程序中,内存泄漏通常不是问题,因为它们在开发/测试的早期就会被检测到

然而,内存碎片可能会变得不确定,导致(最佳情况下)在现场应用程序中随机出现内存不足错误


在动态分配的开发过程中,预测应用程序的实际最大内存使用量也是非常重要的,然而,静态分配的内存量在编译时是已知的,检查该内存是否可以由硬件提供是非常简单的。

从固定大小的块池分配内存比动态内存分配有两个优点。它可以防止堆碎片,而且更具确定性

通过动态内存分配,可以从固定大小的堆中分配动态大小的内存块。分配的释放顺序不一定与分配的顺序相同。随着时间的推移,这可能会导致堆的空闲部分被分配到堆的已分配部分之间的情况。当出现这种碎片时,完成更大内存分配的请求可能会变得更加困难。如果请求大内存分配,并且堆中没有足够大的连续空闲部分,则分配将失败。堆可能有足够的总可用内存,但是如果它都是碎片,并且没有连续的部分,那么分配将失败。在嵌入式系统中,由于堆碎片而导致malloc()失败的可能性是不可取的

对抗碎片的一种方法是在释放较小的内存分配时将其重新连接到较大的连续部分。这可以通过各种方式完成,但它们都需要时间,并且会降低系统的确定性。例如,如果内存管理器在释放内存分配时扫描堆,那么完成free()所需的时间可能会因与被释放的分配相邻的内存类型而异。这在许多嵌入式系统中是不确定的和不可取的


从固定大小的块池中分配不会导致碎片。只要有一些空闲块,分配就不会失败,因为每个块的大小都是正确的。另外,从固定大小的块池中分配和释放更简单。因此,分配和释放函数可以编写为确定性函数。

仅举一个实际例子,DO-178B美国军用标准禁止在安全关键嵌入式航空电子代码中使用
malloc
。您好,感谢您提供的信息。我相信碎片也会浪费嵌入式系统中宝贵的内存。但是你认为速度也是一个问题吗?也许使用更小的静态分配内存是一种选择