简体   繁体   English

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

[英]Why shouldn't we have dynamic allocated memory with different size in embedded system

I have heard in embedded system, we should use some preallocated fixed-size memory chunks(like buddy memory system?).我听说在嵌入式系统中,我们应该使用一些预先分配的固定大小的内存块(比如伙伴内存系统?)。 Could somebody give me a detailed explanation why?谁能给我一个详细的解释为什么? Thanks,谢谢,

In embedded systems you have very limited memory.在嵌入式系统中,您的内存非常有限。 Therefore, if you occasionally lose only one byte of memory (because you allocate it , but you dont free it), this will eat up the system memory pretty quickly (1 GByte of RAM, with a leak rate of 1/hour will take its time. If you have 4kB RAM, not as long)因此,如果您偶尔只丢失一个字节的内存(因为您分配了它,但没有释放它),这将很快耗尽系统内存(1 GB 的 RAM,泄漏率为 1/小时)时间。如果您有 4kB RAM,则不会那么长)

Essentially the behaviour of avoiding dynamic memory is to avoid the effects of bugs in your program.本质上,避免动态内存的行为是为了避免程序中错误的影响。 As static memory allocation is fully deterministic (while dynamic memory alloc is not), by using only static memory allocation one can counteract such bugs.由于静态内存分配是完全确定性的(而动态内存分配不是),因此仅使用静态内存分配就可以抵消此类错误。 One important factor for that is that embedded systems are often used in security-critical application.一个重要因素是嵌入式系统通常用于安全关键应用程序。 A few hours of downtime could cost millions or an accident could happen.几个小时的停机时间可能会造成数百万美元的损失,或者可能发生事故。

Furthermore, depending on the dynamic memory allocator, the indeterminism also might take an indeterminate amount of time, which can lead to more bugs especially in systems relying on tight timing (thanks to Clifford for mentioning this).此外,取决于动态内存分配器,不确定性也可能需要不确定的时间,这可能会导致更多的错误,尤其是在依赖严格计时的系统中(感谢Clifford提到这一点)。 This type of bug is often hard to test and to reproduce because it relies on a very specific execution path.这种类型的错误通常很难测试和重现,因为它依赖于非常具体的执行路径。

Additionally, embedded systems don't usually have MMUs, so there is nothing like memory protection.此外,嵌入式系统通常没有 MMU,因此没有像内存保护这样的东西。 If you run out of memory and your code to handle that condition doesn't work, you could end up executing any memory as instruction (bad things could happen! However this case is only indirectly related to dynamic mem allocation).如果内存不足并且处理该条件的代码不起作用,则最终可能会将任何内存作为指令执行(可能会发生坏事!但是这种情况仅与动态内存分配间接相关)。

As Hao Shen mentioned, fragmentation is also a danger.正如沉浩所说,碎片化也是一种危险。 Whether it may occur depends on your exact usecase, but in embedded systems it is quite easy to loose 50% of your RAM due to fragmentation.它是否可能发生取决于您的具体用例,但在嵌入式系统中,由于碎片,很容易丢失 50% 的 RAM。 You can only avoid fragmentation if you allocate chunks that always have the exact same size.如果分配始终具有完全相同大小的块,则只能避免碎片。

Performance also plays a role (depends on the usecase - thanks Hao Shen ).性能也很重要(取决于用例 - 感谢Hao Shen )。 Statically allocated memory is allocated by the compiler whereas malloc() and similar need to run on the device and therefore consume CPU time (and power).静态分配的内存由编译器分配,而malloc()和类似的需要在设备上运行,因此消耗 CPU 时间(和功率)。

Many embedded OSs (eg ChibiOS) support some kind of dynamic memory allocator.许多嵌入式操作系统(例如 ChibiOS)支持某种动态内存分配器。 But using it only increases the possibility of unexpected issues to occur.但是使用它只会增加发生意外问题的可能性。

Note that these arguments are often circumvented by using smaller statically allocated memory pools.请注意,这些参数通常可以通过使用较小的静态分配内存池来规避。 This is not a real solution, as one can still run out of memory in those pools, but it will only affect a small part of the system.这不是一个真正的解决方案,因为这些池中的内存仍然可能耗尽,但这只会影响系统的一小部分。

As pointed out by Stephano Sanfilippo , some system don't even have enough resources to support dynamic memory allocation.正如Stephano Sanfilippo所指出的,有些系统甚至没有足够的资源来支持动态内存分配。

Note: Most coding standard, including the JPL coding standard and DO-178B (for critical avionics code - thanks Stephano Sanfilippo ) forbid the use of malloc.注意:大多数编码标准,包括JPL 编码标准DO-178B (用于关键航空电子代码 - 感谢Stephano Sanfilippo )禁止使用 malloc。

I also assume the MISRA C standard forbids malloc() because of this forum post -- however I don't have access to the standard itself.我还假设MISRA C 标准因为这个论坛帖子而禁止malloc() - 但是我无权访问标准本身。

The main reasons not to use dynamic heap memory allocation here are basically:这里不使用动态堆内存分配的主要原因基本上是:

a) Determinism and, correlated, b) Memory fragmentation. a) 确定性和相关性,b) 记忆碎片。

Memory leaks are usually not a problem in those small embedded applications, because they will be detected very early in development/testing.在那些小型嵌入式应用程序中,内存泄漏通常不是问题,因为它们会在开发/测试的早期被检测到。

Memory fragmentation can however become non-deterministic, causing (best case) out-of-memory errors at random times and points in the application in the field.然而,内存碎片可能变得不确定,导致(最佳情况)在现场应用程序中的随机时间和点出现内存不足错误。

It may also be non-trivial to predict the actual maximum memory usage of the application during development with dynamic allocation, whereas the amount of statically allocated memory is known at compile time and it is absolutely trivial to check if that memory can be provided by the hardware or not.在使用动态分配的开发过程中预测应用程序的实际最大内存使用量也可能非常重要,而静态分配的内存量在编译时是已知的,并且检查该内存是否可以由硬件与否。

Allocating memory from a pool of fixed size chunks has a couple advantages over dynamic memory allocation.从固定大小的块池中分配内存比动态内存分配有几个优点。 It prevents heap fragmentation and it is more deterministic.它可以防止堆碎片,并且更具确定性。

With dynamic memory allocation, dynamically sized memory chunks are allocated from a fixed size heap.通过动态内存分配,动态大小的内存块是从固定大小的堆中分配的。 The allocations aren't necessarily freed in the same order that they're allocated.分配不一定按照分配的顺序释放。 Over time this can lead to a situation where the free portions of the heap are divided up between allocated portions of the heap.随着时间的推移,这可能导致堆的空闲部分在堆的分配部分之间划分的情况。 As this fragmentation occurs, it can become more difficult to fulfill requests for larger allocations of memory.随着这种碎片的发生,满足更大内存分配的请求会变得更加困难。 If a request for a large memory allocation is made, and there is no contiguous free section in the heap that's large enough then the allocation will fail.如果请求大内存分配,并且堆中没有足够大的连续空闲部分,则分配将失败。 The heap may have enough total free memory but if it's all fragmented and there is not a contiguous section then the allocation will fail.堆可能有足够的总可用内存,但如果它全部碎片化并且没有连续的部分,则分配将失败。 The possibility of malloc() failing due to heap fragmentation is undesirable in embedded systems.由于堆碎片而导致 malloc() 失败的可能性在嵌入式系统中是不可取的。

One way to combat fragmentation is rejoin the smaller memory allocations into larger contiguous sections as they are freed.消除碎片的一种方法是在释放时将较小的内存分配重新加入较大的连续部分。 This can be done in various ways but they all take time and can make the system less deterministic.这可以通过多种方式完成,但它们都需要时间,并且会使系统的确定性降低。 For example, if the memory manager scans the heap when a memory allocation is freed then the amount of time it takes free() to complete can vary depending on what types of memory are adjacent to the allocation being freed.例如,如果内存管理器在释放内存分配时扫描堆,则 free() 完成所需的时间可能会根据与正在释放的分配相邻的内存类型而有所不同。 That is non-deterministic and undesirable in many embedded systems.这在许多嵌入式系统中是不确定的和不可取的。

Allocating from a pool of fixed sized chunks does not cause fragmentation.从固定大小的块池中分配不会导致碎片。 So long as there is some free chunks then an allocation won't fail because every chunk is the right size.只要有一些空闲块,分配就不会失败,因为每个块的大小都是正确的。 Plus allocating and freeing from a pool of fixed size chunks is simpler.此外,从固定大小的块池中分配和释放更简单。 So the allocate and free functions can be written to be deterministic.所以分配和释放函数可以写成确定性的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM