9

我应该如何管理任务关键型嵌入式应用程序中的内存?

我在谷歌上找到了一些文章,但找不到真正有用的实用指南。

禁止DO-178b动态内存分配,但你将如何管理内存呢?提前预分配所有内容并发送一个指向每个需要分配的函数的指针?在堆栈上分配它?使用全局静态分配器(但它与动态分配非常相似)?

答案的形式可以是常规答案、对资源的引用或对好的开源嵌入式系统的引用。

澄清:这里的问题不是内存管理是否可用于嵌入式系统。但是对于嵌入式系统来说,什么是好的设计,可以最大限度地提高可靠性。

我不明白为什么静态预分配缓冲池并动态获取和删除它与动态分配内存不同。

4

7 回答 7

4

我曾在 DO-178B 环境(飞机系统)中工作。我的理解是,不允许动态分配的主要原因主要是认证。认证是通过测试(单一、覆盖、集成……)完成的。通过这些测试,您必须证明您的程序的行为是 100% 可预测的,几乎到您的进程的内存占用量从一次执行到下一次执行都是相同的。由于动态分配是在堆上完成的(并且可能会失败),因此您无法轻易证明这一点(我想如果您掌握从硬件到编写的任何代码的所有工具,应该是可能的,但是......)。静态分配没有这个问题。这也是为什么 C++ 目前没有在这样的环境中使用的原因。(大约 15 年前,可能已经改变了......)

实际上,您必须编写大量结构池和分配函数来保证您具有确定性。你可以想象很多解决方案。关键是您必须(通过大量测试)证明高水平的确定性行为。证明您手工制作的开发工作具有确定性比证明 linux + gcc 在分配内存方面具有确定性更容易。

只是我的2美分。那是很久以前的事了,事情可能已经发生了变化,但是对于像 DO-178B 这样的认证,关键是要证明您的应用程序在任何情况下都可以随时运行。

于 2010-03-18T18:51:45.167 回答
4

作为一个处理过嵌入式系统的人,虽然到目前为止还没有那么严格(虽然我读过 DO-178B):

  • 如果您查看 u-boot 引导加载程序,您会发现很多事情都是通过全局放置的结构完成的。根据您的具体应用程序,您可能能够摆脱全局结构和堆栈。当然,那里有重入和相关问题,这些问题并不真正适用于引导加载程序,但可能适合您。
  • 预分配,预分配,预分配。如果您可以在设计时绑定数组/列表结构/等的大小,请将其声明为全局(或静态全局--看马,封装)。
  • 堆栈非常有用,在需要的地方使用它——但要小心,因为很容易继续分配它,直到你没有剩余的堆栈空间。我曾经发现自己调试的一些代码会为多个函数中的字符串管理分配 1k 缓冲区……有时,缓冲区的使用会影响另一个程序的堆栈空间,因为默认堆栈大小为 4k。
  • 缓冲池的情况可能取决于它是如何实现的。如果您知道需要传递在编译时已知大小的固定大小缓冲区,则处理缓冲池可能比完整的动态分配器更容易证明正确性。您只需要验证缓冲区不会丢失,并验证您的处理不会失败。这里似乎有一些很好的提示:http: //www.cotsjournalonline.com/articles/view/101217

不过,真的,我认为您的答案可能会在加入http://www.do178site.com/时找到

于 2010-03-18T16:32:05.480 回答
3

免责声明:我没有专门使用 DO-178b,但我为认证系统编写了软件。

在我作为开发人员的认证系统上,...

  1. 只有在初始化阶段才可以接受动态内存分配。
  2. 动态内存解除分配是绝对不能接受的。

这给我们留下了以下选择......

  • 使用静态分配的结构。
  • 创建一个结构池,然后从池中获取/释放它们。
  • 为了灵活性,我们可以在初始化阶段动态分配池的大小或结构的数量。然而,一旦过了那个初始化阶段,我们就被我们所拥有的东西困住了。

我们公司发现结构池然后从池中获取/释放/返回池中是最有用的。我们能够保持模型,并以最少的问题保持确定性。

希望有帮助。

于 2010-03-18T13:26:36.520 回答
2

实时、长时间运行的关键任务系统不应从堆中动态分配和释放内存。如果您需要并且无法围绕它进行设计,则可以编写自己的分配和固定池管理方案。是的,尽可能提前固定分配。其他任何事情都是在自找麻烦。

于 2010-03-18T13:09:05.840 回答
0

从堆栈分配所有内容通常在嵌入式系统或分配失败可能性不可接受的其他地方完成。我不知道 DO-178b 是什么,但是如果问题是 malloc 在您的平台上不可用,您也可以自己实现(实现自己的堆),但这仍然可能导致运行时分配失败当然,空间不足。

于 2010-03-18T13:02:21.003 回答
0

没有办法百分百确定。

您可以查看 FreeRTOS 的内存分配器示例。如果我没记错的话,那些使用静态池。

于 2010-03-18T13:11:13.110 回答
0

您可能会发现这个问题也很有趣,在空间强化设置中通常禁止动态分配(实际上,核心内存在那里仍然有用)。

通常,当 malloc() 不可用时,我只使用堆栈。正如Tronic所说,不使用 malloc() 的全部原因是它可能会失败。如果您使用的是全局静态池,可以想象您的内部 malloc() 实现可以防故障。

这真的,真的,真的取决于手头的任务以及董事会将要接触的内容。

于 2010-03-18T13:12:22.733 回答