Jump to content

    

Физический смысл configMINIMAL_STACK_SIZE configTOTAL_HEAP_SIZE

Здравствуйте.

Использую в своём проекте порт FreeRTOS для LPC1343.

 

Заявленные в топике дефайны

configMINIMAL_STACK_SIZE

configTOTAL_HEAP_SIZE

 

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

 

2. Что будет, если общий объем стеков задач в сумме с configTOTAL_HEAP_SIZE превысит объем памяти?

 

3. Что происходит, когда размеры локальных переменных в таске превышают объём configMINIMAL_STACK_SIZE.

 

4. Как можно объяснить такое наблюдение:

configMININAL_STACK_SIZE 300

configTOTAL_HEAP_SIZE 6*1024

 

В одной из 3х созданных задач есть структура объемом 216 байт и ещё кое-что по-мелочи. Но самое главное, код работает.

 

Меняем просто

configTOTAL_HEAP_SIZE 5*1024 - и всё умирает.

 

Впрочем, программа умирает также, когда из трех тасков в двух размер стека задается configMININAL_STACK_SIZE. а в третьей - самой прожорливой configMININAL_STACK_SIZE*2.

 

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

 

5. Наверное уже набившая оскомину тема с выделением и освобождением памяти внутри тасков: чем отличается использование malloc() и free() от специальных функций pvPortMalloc() и vPortFree().

 

Буду благодарен за ответы по существу и за ссылки на подробные объяснения в других местах.

Share this post


Link to post
Share on other sites

Складывается ощущение, что вы не совсем понимаете как оно крутится.

FreeRTOS использует кучу для создания своих структур (задач, списков, очередей, семафоров) и стеков задач.

В составе FreeRTOS есть три варианта кучи: heap_1.c, heap_2.c и heap_3.c

 

heap_1.c - простейший вариант. По сути - эмулятор динамического распределения без освобождения. Пригоден для случаев, когда объекты RTOS (задачи, очереди, семафоры и т.д.) создаются один раз и никогда не уничтожаются. Ситуация, как ни странно, довольно распространенная.

 

heap_2.c - чуть сложнее. Есть возможность освобождать память, но нет дефрагментации свободных блоков. Пригоден в некоторых редких случаях.

 

heap_3.c - обертка над стандартными malloc/free. Функциональность зависит от стандартной библиотеки используемого компилятора.

 

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

configMINIMAL_STACK_SIZE задает размер стека для IDLE TASK. Более самой FreeRTOS нигде не используется.

 

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

Каждой задаче выделяется только свой стек. Выделяется он из кучи FreeRTOS (то есть из configTOTAL_HEAP_SIZE). Глобальные и статические переменные выделяются линкером и FreeRTOS к ним сугубо перпендикулярна. Остатки что физической памяти, что кучи FreeRTOS - никуда не деваются и просто не используются.

 

2. Что будет, если общий объем стеков задач в сумме с configTOTAL_HEAP_SIZE превысит объем памяти?

объем стеков с configTOTAL_HEAP_SIZE не суммируется, а наоборот из него вычитается. Если при создании задачи в куче не хватает памяти для стека - то задача не будет создана.

 

3. Что происходит, когда размеры локальных переменных в таске превышают объём configMINIMAL_STACK_SIZE.

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

 

4. Как можно объяснить такое наблюдение:

configMININAL_STACK_SIZE 300

configTOTAL_HEAP_SIZE 6*1024

В одной из 3х созданных задач есть структура объемом 216 байт и ещё кое-что по-мелочи. Но самое главное, код работает.

Меняем просто

configTOTAL_HEAP_SIZE 5*1024 - и всё умирает.

"Имя сестра, имя!". Процессор какой? configTOTAL_HEAP_SIZE задается в байтах, а configMINIMAL_STACK_SIZE - в portBASE_TYPE, который на армах имеет тип int. Для случая арма ваши три задачи займут 3*300*4 = 3.6 кБ. Плюс Idle Task еще 1.2 кБ. Вот уже почти ваши 5*1024, а ведь еще есть Task Control Block, очереди-семафоры и т.д.

 

Впрочем, программа умирает также, когда из трех тасков в двух размер стека задается configMININAL_STACK_SIZE. а в третьей - самой прожорливой configMININAL_STACK_SIZE*2.

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

Ничего не проверяется. Скорее всего памяти в куче у вас не хватает.

 

5. Наверное уже набившая оскомину тема с выделением и освобождением памяти внутри тасков: чем отличается использование malloc() и free() от специальных функций pvPortMalloc() и vPortFree().

malloc() обычно не многозадачен. Зачастую - избыточен по функционалу. И время выполнения непредсказуемо. Потому и не любят его в мелких системах.

Edited by LightElf

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this