【问题标题】:How to add memory to the heap at runtime?如何在运行时向堆中添加内存?
【发布时间】:2011-05-17 19:49:34
【问题描述】:

我正在使用 Keil 的 ARM-MDK 4.11。我有一个静态分配的内存块,仅在启动时使用。它在调度程序初始化之前使用,并且由于 RL-RTX 控制堆管理的方式,不能动态分配(否则调度程序启动后的后续分配会导致硬故障)。

我想在调度程序初始化后将此静态块作为空闲块添加到系统堆中。似乎__Heap_ProvideMemory() 可能会提供答案,这在初始化期间被调用以创建初始堆。但是,这需要了解堆描述符地址,而我找不到获得该地址的记录方法。

有什么想法吗?

我已为此向 ARM/Keil 提出支持请求,但他们更感兴趣的是质疑我为什么要这样做,并提供替代解决方案。我很清楚替代方案,但在这种情况下,如果可以做到这一点,那将是最干净的解决方案。

【问题讨论】:

    标签: embedded heap-memory keil


    【解决方案1】:

    我使用的一种方法是合并我自己的简单堆例程并从库中接管malloc()/calloc()/free() 函数。

    简单的自定义堆例程具有允许向堆中添加内存块的接口。

    这样做的缺点(至少在我的情况下)是自定义堆例程远不如内置库例程复杂,并且可能比内置例程更容易产生碎片。在那个特定的应用程序中,这不是一个严重的问题。如果您想要内置库例程的功能,您可以让您的 malloc() 延迟到内置堆例程,直到它返回失败,然后尝试从您的自定义堆中分配。

    另一个缺点是我发现确保自定义例程没有错误比我乍一看更痛苦,即使我并没有尝试做任何太花哨的事情(只是一个简单的列表可以在分配时拆分并在释放时合并的空闲块)。

    这种技术的一个好处是它非常可移植(只要您的自定义例程是可移植的)并且如果工具链更改其内部结构也不会中断。唯一需要移植的部分是接管malloc()/free() 接口并确保您足够早地初始化。

    【讨论】:

    • 一些好主意,由于我可能正在使用 C++ new/delete 的事实而有些复杂,而且我没有处理 RTX 提供的版本所做的线程安全。我现在在想,我可以对分配之前的块管理结构进行逆向工程,将其复制到静态块的开头,然后 free() 将其添加到空闲列表中。
    • C++ new/delete 可能会让事情变得更容易(至少在某些事情上)。 C++ 直接支持最终用户覆盖全局 new/delete - 你可以 100% 便携地做到这一点。如果您不关心某些堆分配可能会绕过自定义堆,您可以忘记劫持malloc/free,而只需覆盖new/delete
    【解决方案2】:

    我们使用 Rowley Crossworks 编译器,但遇到了类似的问题 - 堆是在编译器 CRT 启动代码中设置的。不幸的是,直到 main() 开始,SDRAM 才被初始化,因此堆没有正确设置。在初始化 SDRAM 之后,我通过在 main() 开始时重新初始化堆来解决这个问题。

    我查看了编译器在启动时用来计算结构的汇编代码——这并不难。随后我还从 Rowley 那里获得了 malloc/free 源代码——也许你可以向 Keil 索要他们的版本?

    【讨论】:

    • 逆向工程可能是解决方案,但它会使代码在升级工具链时容易被破坏。我正在考虑的另一种选择是使根任务更简单(因此需要最少的堆栈分配),并从中产生一个正常的任务来进行初始化,以便可以动态分配其堆栈并因此可重用。正如他们所说,没有另一个间接级别就无法解决任何问题(除了太多间接级别的问题)! Keil 的 RL-ARM 库的源代码许可是收费的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-27
    • 2018-04-11
    相关资源
    最近更新 更多