Как добавить память в кучу во время выполнения?

Я использую Keil ARM-MDK 4.11. У меня есть статически выделенный блок памяти, который используется только при запуске. Он используется до инициализации планировщика и из-за того, что RL-RTX берет на себя управление кучей, не может быть выделен динамически (в противном случае последующие выделения после запуска планировщика вызовут серьезную ошибку).

Я хотел бы добавить этот статический блок в качестве свободного блока в системную кучу после инициализации планировщика. Казалось бы, __Heap_ProvideMemory() может дать ответ, это вызывается во время инициализации для создания начальной кучи. Однако для этого потребуется знание адреса дескриптора кучи, и я не могу найти документированного метода его получения.

Любые идеи?

Я отправил запрос в службу поддержки ARM/Keil по этому поводу, но они больше заинтересованы в том, чтобы спросить, почему я хотел бы это сделать, и предложить альтернативные решения. Я хорошо знаю альтернативы, но в этом случае, если бы это можно было сделать, это было бы самым чистым решением.


person Clifford    schedule 30.11.2010    source источник


Ответы (2)


Мы используем компилятор Rowley Crossworks, но у нас была аналогичная проблема — куча настраивалась в коде запуска компилятора CRT. К сожалению, SDRAM не была инициализирована до запуска функции main(), поэтому куча не была настроена должным образом. Я работал над этим, повторно инициализируя кучу в начале main() после инициализации SDRAM.

Я посмотрел ассемблерный код, который компилятор использует при запуске для проработки структуры — это было несложно. Впоследствии я также получил исходный код malloc/free от Роули — возможно, вы могли бы попросить у Кейла их версию?

person peter_mcc    schedule 30.11.2010
comment
Реверс-инжиниринг может быть решением, но он делает код уязвимым для взлома при обновлении цепочки инструментов. Альтернативой, которую я рассматриваю, является упрощение корневой задачи (что требует минимального выделения стека) и создание из нее обычной задачи для выполнения инициализации, чтобы ее стек можно было динамически выделять и, следовательно, повторно использовать. Как говорится, нет проблемы, которую нельзя было бы решить без еще одного уровня косвенности (за исключением проблемы слишком большого количества уровней косвенности)! Исходная лицензия Keil для библиотеки RL-ARM доступна за плату. - person Clifford; 01.12.2010

Один метод, который я использовал, заключается в том, чтобы включить мои собственные простые процедуры работы с кучей и взять на себя функции malloc()/calloc()/free() из библиотеки.

Простые настраиваемые процедуры работы с кучей имели интерфейс, который позволял добавлять в кучу блоки памяти.

Недостатком этого (по крайней мере, в моем случае) было то, что пользовательские подпрограммы кучи были гораздо менее сложными, чем встроенные библиотечные подпрограммы, и, вероятно, были более подвержены фрагментации, чем встроенные подпрограммы. Это не было серьезной проблемой в этом конкретном приложении. Если вам нужны возможности встроенных библиотечных подпрограмм, вы, вероятно, могли бы сделать так, чтобы ваш malloc() откладывал встроенные подпрограммы кучи до тех пор, пока он не вернет ошибку, а затем попробуйте выделить из своей пользовательской кучи.

Другим недостатком является то, что мне было гораздо труднее удостовериться, что пользовательские подпрограммы не содержат ошибок, чем я думал на первый взгляд, хотя я не пытался делать что-то слишком причудливое (только простой список свободных блоков). которые могут быть разделены при распределении и объединены при освобождении).

Единственным преимуществом этого метода является то, что он довольно переносим (пока переносимы ваши пользовательские подпрограммы) и не ломается, если цепочка инструментов меняет свои внутренние компоненты. Единственная часть, которая требует переноса, — это использование интерфейса malloc()/free() и обеспечение достаточно ранней инициализации.

person Michael Burr    schedule 02.12.2010
comment
Некоторые хорошие идеи, несколько усложненные тем фактом, что я использую С++ new/delete, возможно, и мне не нужно обрабатывать потокобезопасность, которую обеспечивают версии RTX. Теперь я думаю, что я мог бы перепроектировать структуру управления блоками, которая предшествует выделению, реплицировать ее в начале статического блока, а затем использовать функцию free(), чтобы добавить ее в список свободных. - person Clifford; 03.12.2010
comment
С++ new/delete может упростить задачу (по крайней мере, некоторые вещи). C++ напрямую поддерживает переопределение конечным пользователем глобальных new/delete - вы можете сделать это на 100% переносимым. Если вас не волнует, что некоторые выделения кучи могут обходить пользовательскую кучу, вы можете забыть о перехвате malloc/free и просто переопределить new/delete. - person Michael Burr; 03.12.2010