Ресурсы для управления памятью во встроенном приложении

Как мне управлять памятью в моем критически важном встроенном приложении?

Я нашел несколько статей в Google, но не смог найти действительно полезного практического руководства.

DO-178b запрещает динамическое распределение памяти, но как вы будете управлять памятью тогда? Предварительно распределить все заранее и отправить указатель на каждую функцию, которая требует выделения? Выделить это в стеке? Использовать глобальный статический распределитель (но тогда он очень похож на динамическое распределение)?

Ответы могут быть в форме обычного ответа, ссылки на ресурс или ссылки на хорошую встроенную систему с открытым исходным кодом, например.

пояснение: проблема здесь не в том, доступно ли управление памятью для встроенной системы. Но что хорошего дизайна для встроенной системы, чтобы максимизировать надежность.

Я не понимаю, почему статическое предварительное выделение пула буферов и его динамическое получение и удаление отличаются от динамического выделения памяти.

7 ответов

Решение

Как кто-то, кто имел дело со встроенными системами, хотя и не до такой строгости (хотя я читал DO-178B, однако):

  • Если вы посмотрите на загрузчик u-boot, многое делается с помощью глобальной структуры. В зависимости от вашего конкретного приложения, вы можете обойтись без глобальной структуры и стека. Конечно, есть повторный вход и связанные с этим проблемы, которые на самом деле не относятся к загрузчику, но могут быть для вас.
  • Предварительно распределить, предварительно выделить, предварительно выделить. Если вы можете во время разработки связать размер структуры массива / списка / и т.д., объявите ее как глобальную (или статическую глобальную - смотрите Ма, инкапсуляция).
  • Стек очень полезен, используйте его там, где это необходимо, но будьте осторожны, так как может быть легко продолжать выделять его, пока у вас не останется свободного места в стеке. Некоторый код, который я когда-то обнаружил при отладке, выделил бы 1 тыс. Буферов для управления строками в нескольких функциях... иногда использование буферов попадало бы в пространство стека другой программы, так как размер стека по умолчанию был 4 тыс.
  • Случай с буферным пулом может зависеть от того, как именно он реализован. Если вы знаете, что вам нужно обойти буферы фиксированного размера, размер которых известен во время компиляции, то, вероятно, легче продемонстрировать правильность работы с буферным пулом, чем полный динамический распределитель. Вам просто нужно убедиться, что буферы не могут быть потеряны, и проверить, не обработана ли ваша обработка. Кажется, здесь есть несколько хороших советов: http://www.cotsjournalonline.com/articles/view/101217

На самом деле, я думаю, что ваши ответы могут быть найдены в присоединении http://www.do178site.com/

Я работал в среде DO-178B (системы для самолетов). Что я понял, так это то, что основной причиной, по которой динамическое распределение не разрешается, является главным образом сертификация. Сертификация проводится с помощью тестов (унитарных, покрытия, интеграции,...). С помощью этих тестов вы должны доказать, что поведение вашей программы на 100% предсказуемо, почти до такой степени, что объем памяти вашего процесса остается одинаковым от одного выполнения к другому. Поскольку динамическое распределение выполняется в куче (и может произойти сбой), вы не можете легко доказать это (я полагаю, это будет возможно, если вы освоите все инструменты от аппаратного обеспечения до любого написанного фрагмента кода, но...). У вас нет этой проблемы со статическим размещением. Вот почему C++ не использовался в настоящее время в таких средах. (это было около 15 лет назад, что могло измениться...)

Практически, вы должны написать много структурных пулов и функций выделения, которые гарантируют, что у вас есть что-то детерминированное. Вы можете представить множество решений. Ключ в том, что вы должны доказать (с ТОНСАМИ тестов) высокий уровень детерминированного поведения. Проще доказать, что ваша ручная работа над разработкой работает детерминистически, чем доказать, что linux + gcc является детерминистическим в распределении памяти.

Просто мои 2 цента. Это было давно, все могло измениться, но в отношении сертификации, такой как DO-178B, важно доказать, что ваше приложение будет работать одинаково в любое время и в любом контексте.

Отказ от ответственности: я не работал специально с DO-178b, но я написал программное обеспечение для сертифицированных систем.

На сертифицированных системах, для которых я был разработчиком,...

  1. Динамическое выделение памяти было приемлемо ТОЛЬКО на этапе инициализации.
  2. Динамическое удаление памяти никогда не было приемлемым.

Это оставило нас со следующими вариантами...

  • Используйте статически размещенные структуры.
  • Создайте пул структур и затем получите / отпустите их из / обратно в пул.
  • Для гибкости мы могли бы динамически распределять размер пулов или количество структур на этапе инициализации. Однако, как только мы прошли эту начальную фазу, мы застряли на том, что имели.

Наша компания обнаружила, что пулы структур и затем получение / освобождение от / обратно в пул было наиболее полезным. Мы смогли придерживаться модели и сохранить детализацию с минимальными проблемами.

Надеюсь, это поможет.

Долгосрочные, критически важные системы реального времени не должны динамически выделять и освобождать память из кучи. Если вам нужно, и вы не можете спроектировать его, напишите свою собственную схему управления выделенным и фиксированным пулом. Да, распределяется фиксированным заранее, когда это возможно. Все остальное требует возможных проблем.

Вам также может показаться интересным этот вопрос, динамическое распределение часто запрещено в установках с усиленной космической защитой (на самом деле, память ядра все еще полезна там).

Обычно, когда malloc() недоступен, я просто использую стек. Как сказал Троник, причина неиспользования malloc() в том, что он может потерпеть неудачу. Если вы используете глобальный статический пул, вполне возможно, что ваша внутренняя реализация malloc() может стать отказоустойчивой.

Это действительно, действительно, действительно зависит от поставленной задачи и от того, чему будет подвергаться правление.

Там нет никакого способа быть на 100% уверенным.

Вы можете посмотреть примеры распределения памяти FreeRTOS. Те используют статический пул, если я не ошибаюсь.

Выделение всего из стека обычно выполняется во встроенных системах или где-либо еще, где вероятность сбоя выделения недопустима. Я не знаю, что такое DO-178b, но если проблема в том, что malloc недоступен на вашей платформе, вы также можете реализовать его самостоятельно (реализовать свою собственную кучу), но это все равно может привести к сбою выделения при запуске из космоса, конечно.

Другие вопросы по тегам