Размер стека потоков Keil RTX RTOS

В файле конфигурации Keil RTX RTOS пользователь может настроить размер стека пользовательских потоков по умолчанию. Как правило, стек содержит автоматические / локальные переменные. Раздел «ZI data» содержит неинициализированные глобальные переменные.

Поэтому, если я изменю размер стека пользовательских потоков в файле конфигурации RTX, размер стека увеличится, а размер раздела «ZI data» не увеличится.

Я тестирую его, результат теста показывает, что если я увеличу размер стека пользовательского потока. Размер раздела «ZI data» будет увеличиваться синхронно с тем же размером.

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

      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   

     36810       4052       1226        380       6484     518461   Grand Totals
     36810       4052       1226        132       6484     518461   ELF Image Totals (compressed)
     36810       4052       1226        132          0          0   ROM Totals

==============================================================================

    Total RO  Size (Code + RO Data)                38036 (  37.14kB)
    Total RW  Size (RW Data + ZI Data)              6864 (   6.70kB)
    Total ROM Size (Code + RO Data + RW Data)      38168 (  37.27kB)  

Но если бы я изменил размер стека каждого потока на 800 байт. Кейл показывает мне следующее:

==============================================================================


      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   

     36810       4052       1226        380       7684     518461   Grand Totals
     36810       4052       1226        132       7684     518461   ELF Image Totals (compressed)
     36810       4052       1226        132          0          0   ROM Totals

==============================================================================

    Total RO  Size (Code + RO Data)                38036 (  37.14kB)
    Total RW  Size (RW Data + ZI Data)              8064 (   7.88kB)
    Total ROM Size (Code + RO Data + RW Data)      38168 (  37.27kB)

==============================================================================

Размер раздела «ZI data» увеличен с 6484 до 7684 байт. 7684 - 6484 = 1200 = 6 * 200. И 800 - 600 = 200. Итак, я вижу, что стек потоков помещен в раздел «ZI Data».

Мой вопрос: означает ли это, что автоматические / локальные переменные в потоке будут помещены в раздел «Данные ZI», когда стек потока помещен в раздел «Данные ZI» в БАРАН ? Если это правда, это означает, что секции стека нет вообще. Есть вообще только "RO / RW / ZI Data" и разделы кучи.

Эта статья дает мне другой ответ. И сейчас я немного запутался в этом. https://developer.mbed.org/handbook/RTOS-Memory-Model


person lrouter    schedule 19.08.2016    source источник
comment
стек содержит автоматические / локальные переменные - с точки зрения запущенного потока, где, конечно, это стек. Однако я не вижу причин, по которым эти стеки не могут быть статически распределенными переменными с точки зрения ОС. Вы просто представили здесь наблюдение; какой конкретный вопрос?   -  person Notlikethat    schedule 19.08.2016


Ответы (2)


Компоновщик определяет, какие разделы памяти существуют. Компоновщик по умолчанию создает некоторые разделы памяти. В вашем случае три из этих разделов по умолчанию, очевидно, называются «Данные RO», «Данные RW» и «Данные ZI». Если вы явно не укажете, в каком разделе должна находиться переменная, то компоновщик назначит ее одному из этих разделов по умолчанию в зависимости от того, объявлена ​​ли переменная константной, инициализированной или неинициализированной.

Компоновщик автоматически не узнает, что вы используете RTOS. И у него нет специальных знаний о том, какие переменные вы собираетесь использовать в качестве стеков потоков. Таким образом, компоновщик не создает автоматически независимые разделы памяти для ваших стеков потоков. Скорее, компоновщик будет обрабатывать переменные стека как любую другую переменную и включать их в один из разделов памяти по умолчанию. В вашем случае стеки потоков, по-видимому, помещаются компоновщиком в раздел ZI Data.

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

person kkrambo    schedule 19.08.2016
comment
Спасибо. Обычно есть несколько разделов по умолчанию: данные RO, данные RW и данные ZI, стек, куча. Компоновщик определяет структуру флэш-памяти и оперативной памяти. Если стек потока помещен в ZI Data, означает ли это, что все автоматические переменные функций, вызываемых в потоке, будут в разделе ZI Data? Тогда что в разделе стека? - person lrouter; 20.08.2016
comment
Есть стек для основной программы. Это стек, который используется при вызове main () до запуска RTOS. Командный файл компоновщика может явно указывать раздел памяти для основного стека. У каждого потока есть собственный стек, отдельный от основного стека. Ваш компоновщик находит эти стеки потоков в разделе ZI Data. После запуска ОСРВ в стеке потоков будут созданы локальные переменные потока. Да, локальные переменные потока будут в ZI Data, потому что стек потока находится в ZI Data. В основном стеке локальные переменные располагаются до запуска ОСРВ. - person kkrambo; 20.08.2016
comment
После того, как ОСРВ запущена, основная функция больше никогда не будет вызываться. Таким образом, основной стек никогда не будет использоваться, если RTOS выйдет из строя. Для экономии памяти это означает, что пространство памяти основного стека и стека потоков будет перекрываться. - person lrouter; 21.08.2016
comment
Да, обычно ОСРВ не возвращается в основной, поэтому основной стек может не использоваться после запуска ОСРВ. Вы должны иметь возможность сделать размер основного стека относительно небольшим. Теоретически я предполагаю, что вы могли бы организовать, чтобы один из стеков потоков превышал основной стек, чтобы память основного стека повторно использовалась после запуска RTOS. Но на практике это кажется сложным маневром, чтобы сэкономить, может быть, пару сотен слов оперативной памяти. ЯГНИ. Я бы порекомендовал вам не усложнять задачу и хранить стеки отдельно. В конечном итоге это упростит отладку и обслуживание. - person kkrambo; 22.08.2016
comment
Да ты прав. И я забыл, что основной стек будет использоваться ядром RTOS. - person lrouter; 22.08.2016
comment
На многих портах ОСРВ Cortex-M стек, определенный компоновщиком (который упоминается как первый элемент в векторной таблице), в конечном итоге станет MSP (стек прерываний) после запуска планировщика. Есть некоторые RTOS (ChibiOS - единственное, что приходит на ум), когда вызов для запуска планировщика возвращается, и этот поток выполнения становится основной задачей с использованием исходного стека. - person rjp; 30.08.2016

Стеки задач должны откуда-то поступать - в RTX по умолчанию они размещаются статически и имеют фиксированный размер.

os_tsk_create_user() позволяет вызывающей стороне предоставить стек, который может быть выделен любым способом (статически или из кучи; выделение из стека вызывающего объекта возможно, но необычно, вероятно, бессмысленно и, безусловно, опасно), если оно имеет 8-байтовое выравнивание. Я считаю, что автоматическое выделение стека RTX почти бесполезно и редко уместно во всех приложениях, кроме самых тривиальных.

person Clifford    schedule 04.09.2016