Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: malloc и free в прерывании
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
Atlantis-
Здравствуйте!
Подскажите пожалуйста, можно ли использовать функции динамического выделения памяти malloc и free в обработчике какого либо прерывания? Если да, то как примерно оценить время выполнения этой функции?
AlexandrY
Цитата(Atlantis- @ Dec 1 2016, 17:06) *
Здравствуйте!
Подскажите пожалуйста, можно ли использовать функции динамического выделения памяти malloc и free в обработчике какого либо прерывания? Если да, то как примерно оценить время выполнения этой функции?


Где-то можно, а где-то нельзя.
Время оценивают по таймеру и статистике. Для этого есть инструменты профайлинга.
Atlantis-
Цитата(AlexandrY @ Dec 1 2016, 18:17) *
Где-то можно, а где-то нельзя.

А с чем связана разница? Где можно и где нельзя? Мне надо использовать malloc и free в обработчике прерывания USB. То есть приходит команда по USB и в обработчике я выделяю или освобождаю память.


zltigo
QUOTE (Atlantis- @ Dec 1 2016, 17:41) *
А с чем связана разница? Где можно и где нельзя?

Изучаете исходные тексты КОНКРЕТНОЙ используемой Вами в каждом конкретном случае функции и решаете в каждом КОНКРЕТНОМ случае можете такой вариант функции использовать или нет. Если нет, то можно-ли сие исправить, например, оберткой, или надо менять более серьезно.
novikovfb
Цитата(Atlantis- @ Dec 1 2016, 18:41) *
А с чем связана разница? Где можно и где нельзя? Мне надо использовать malloc и free в обработчике прерывания USB. То есть приходит команда по USB и в обработчике я выделяю или освобождаю память.

Почитайте про понятие реентерабельности функций и посмотрите, как работают функции malloc и free в Вашей системной библиотеке. Может получиться, что прерывание возникнет в момент выполнения функции malloc или free, в прерывании будет вызвана функция malloc или free, может получиться либо выделение одного и того же буфера двум разным указателям или полное разрушение структуры кучи.
Atlantis-
Цитата(novikovfb @ Dec 2 2016, 08:47) *
Почитайте про понятие реентерабельности функций и посмотрите, как работают функции malloc и free в Вашей системной библиотеке. Может получиться, что прерывание возникнет в момент выполнения функции malloc или free, в прерывании будет вызвана функция malloc или free, может получиться либо выделение одного и того же буфера двум разным указателям или полное разрушение структуры кучи.

У меня предполагается только один malloc и один free, в прерывании USB, в разных командах.
Посмотреть код malloc...он где то в библиотеках запрятан. Не подскажете где его найти для Keil ARM?
novikovfb
Цитата(Atlantis- @ Dec 2 2016, 09:20) *
У меня предполагается только один malloc и один free, в прерывании USB, в разных командах.
Посмотреть код malloc...он где то в библиотеках запрятан. Не подскажете где его найти для Keil ARM?

тогда может и будет работать, если по времени успеет. Насчет исходников Keil - не знаю, у IAR были исходники в версии 2009 года, там просмотр связанного списка, поиск первой свободной области достаточного размера, сделана блокировка от повторного входа, но она поможет только в многозадачной среде, т.к. попытка остановить обработчик прерывания до окончания выполнения фоновой задачи добром не кончится.
По длительности обработки malloc и free - там, скорее всего, просмотр списка занятых/свободных областей памяти в куче, чем сильнее фрагментирована куча - тем медленнее будет работать.
Atlantis-
Понятно, а если эта куча выделена во внешней SDRAM памяти, как у меня, наверно, еще медленнее будет.
k155la3
Цитата(Atlantis- @ Dec 2 2016, 09:20) *
. . . в прерывании USB, в разных командах.
Посмотреть код malloc...он где то в библиотеках запрятан. . . . .

В прерываниях крайне нежелательно использовать "долгоиграющие" вызовы.
Тем более, что USB сейчас довольно "оборотистый", даже 2.0.
Как вариант - сделайте свой "malloc", работающий на заранее выделенной области памяти, c быстрым "выделением" и "освобождением"
через указател(и) и размер. Его и пользуйте в ISR.
esaulenka
Цитата(k155la3 @ Dec 2 2016, 10:07) *
В прерываниях крайне нежелательно использовать "долгоиграющие" вызовы.

Крайне нежелательно мыслить исключительно догмами. Правильный ответ - во втором уже сообщении, "где-то можно, где-то нет".
Если понимать, что происходит и представлять себе последствия, можно делать всё, что нужно.
Прерывания в современных контроллерах (читай "cortex-M") - вполне себе недо-операционка. С многими уровнями вложенности задач, если надо.


Цитата(k155la3 @ Dec 2 2016, 10:07) *
Тем более, что USB сейчас довольно "оборотистый", даже 2.0.

USB, даже 2.0, даже в 2016 году ещё поискать надо. В большинстве контроллеров бесплатно (без дополнительного PHY) до сих пор full-speed. И его до сих пор хватает для очень многих изделий.

Цитата(k155la3 @ Dec 2 2016, 10:07) *
Как вариант - сделайте свой "malloc", работающий на заранее выделенной области памяти, c быстрым "выделением" и "освобождением"
через указател(и) и размер. Его и пользуйте в ISR.

А вот совет "из г-на и палок быстренько сделайте свой велосипед" может выйти боком, когда через полгода у этого велосипеда окажется 13 колёс.
megajohn
Цитата(esaulenka @ Dec 2 2016, 10:48) *
А вот совет "из г-на и палок быстренько сделайте свой велосипед" может выйти боком, когда через полгода у этого велосипеда окажется 13 колёс.


давно ли пулы памяти это велосипед ?
Atlantis-
Померял осциллографом время выполнения malloc, выполняется в основном за 1 мкс иногда за 3 мкс, потыкал, чтобы забить побольше памяти, стало выполняться иногда за 1,2 или 3,2 мкс.
Функции вызова задачи FreeRTOS 4,5-6,9 мкс (для создания сообщения там тоже динамически выделяется память, но не с помощью malloc). Мда...
zltigo
QUOTE (esaulenka @ Dec 2 2016, 09:48) *
А вот совет "из г-на и палок быстренько сделайте свой велосипед"....

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


QUOTE (Atlantis- @ Dec 2 2016, 11:33) *
Функции вызова задачи FreeRTOS 4,5-6,9 мкс (для создания сообщения там тоже динамически выделяется память, но не с помощью malloc). Мда...

Что Вы назвали "вызовом задачи" неведомо никому sad.gif. Это раз. Задачи как таковые никакие сообщения не создают, а при собственно передаче сообщения никакого динамического выделения памяти уже не происходит. Ну и третье, если есть уже один менеджер памяти, как в FreeRTOS, причем в исходниках, то вторым пользоваться незачем. Ну и пятое - измеряли время Вы НЕПРАВИЛЬНО, поскольку время отрабатывания парочки malloc/free при отсутствии других вызовов менеджера, не может меняться при хоть сколь-нибудь реальной реализации этих функций.
novikovfb
Цитата(zltigo @ Dec 2 2016, 12:56) *
время отрабатывания парочки malloc/free при отсутствии других вызовов менеджера, не может меняться при хоть сколь-нибудь реальной реализации этих функций.

с каких пор просмотр связанного списка (а очень часто именно на нем делают управление кучей) перестал зависеть от длины этого списка?
Atlantis-
Цитата(zltigo @ Dec 2 2016, 12:56) *
Что Вы назвали "вызовом задачи" неведомо никому sad.gif. Это раз.

Я имел ввиду создание сообщения (Message) и отправку его в очередь (osMessagePut).
Данное сообщение потом разблокирует задачу и в ней выполняется malloc

Цитата(zltigo @ Dec 2 2016, 12:56) *
Задачи как таковые никакие сообщения не создают, а при собственно передаче сообщения никакого динамического выделения памяти уже не происходит.

Не создают, я сам создаю, в прерывании и память динамически выделяю, средствами RTOS

Цитата(zltigo @ Dec 2 2016, 12:56) *
Ну и третье, если есть уже один менеджер памяти, как в FreeRTOS, причем в исходниках, то вторым пользоваться незачем.

Менеджер памяти в FreeRTOS копается в внутренней RAM процессора (причем в статически выделенном ему кусочке этой RAM). А malloc выделяет память из внешней SDRAM.

Цитата(zltigo @ Dec 2 2016, 12:56) *
Ну и пятое - измеряли время Вы НЕПРАВИЛЬНО, поскольку время отрабатывания парочки malloc/free при отсутствии других вызовов менеджера, не может меняться при хоть сколь-нибудь реальной реализации этих функций.

Не знаю, дернул ножкой вверх до выполнения malloc и дернул вниз после выполнения. Хотя возможно в процессе вклинилось другое прерывание...ну не суть, главное, что дольше 3 мкс malloc у меня не выполнялся, а это мизерная задержка.
AlexandrY
Цитата(Atlantis- @ Dec 2 2016, 13:17) *
Не знаю, дернул ножкой вверх до выполнения malloc и дернул вниз после выполнения. Хотя возможно в процессе вклинилось другое прерывание...ну не суть, главное, что дольше 3 мкс malloc у меня не выполнялся, а это мизерная задержка.


Режим Persistence на осциллографе был включен?

И что, израсходуете malloc только для этого единственного прерывания?
Потом будете жалеть, когда подзабудете весь код, а понадобится его реюзинг.
zltigo
QUOTE (novikovfb @ Dec 2 2016, 12:15) *
с каких пор просмотр связанного списка (а очень часто именно на нем делают управление кучей) перестал зависеть от длины этого списка?

C тех пор, как по условиям теста этот список НЕ МЕНЯЕТСЯ. Разброс времен у Автора был вызван незакрытыми прерываниями при вызове менеджера и ничем более.
Atlantis-
Цитата(AlexandrY @ Dec 2 2016, 14:52) *
Режим Persistence на осциллографе был включен?

Не уверен, что точно понял, что Вы имеете ввиду. На осциллографе у меня есть режим Auto и Normal, был включен второй - когда засеченный импульс не уплывает, а остается на экране.

Цитата(AlexandrY @ Dec 2 2016, 14:52) *
И что, израсходуете malloc только для этого единственного прерывания?
Потом будете жалеть, когда подзабудете весь код, а понадобится его реюзинг.

Зато избавлюсь от лишней задачи
k155la3
Цитата(esaulenka @ Dec 2 2016, 11:48) *
(1) Крайне нежелательно мыслить исключительно догмами.
(2) Если понимать, что происходит и представлять себе последствия, можно делать всё, что нужно.
. . . .
(3) А вот совет "из г-на и палок быстренько сделайте свой велосипед" может выйти боком, когда через полгода у этого велосипеда окажется 13 колёс.

(1) - Я не настолько религиозен sm.gif
(2) Согласен. В рамках здравого смысла и уголовного кодекса.
(3) Согласен. Если не следовать (1,2)

haker_fox
QUOTE (Atlantis- @ Dec 1 2016, 23:06) *
Подскажите пожалуйста, можно ли использовать функции динамического выделения памяти malloc и free в обработчике какого либо прерывания?

Да, но я бы не стал (имхо). Нельзя ли просто выделить память статически, или динамически, но создавать её при подключении usb и удалять при отключении?

QUOTE (Atlantis- @ Dec 2 2016, 19:17) *
Менеджер памяти в FreeRTOS копается в внутренней RAM процессора (причем в статически выделенном ему кусочке этой RAM). А malloc выделяет память из внешней SDRAM.

А зачем так сложно? Сделайте один менеджер в SDRAM, переопределите операты new и delete, если используете Си++.
jorikdima
Если ксть СДРАМ, которой обычно много, вы уверены, что вообще нужна дин. память? Тем более только в одном месте, как сказали.
jcxz
Цитата(esaulenka @ Dec 2 2016, 10:48) *
Если понимать, что происходит и представлять себе последствия, можно делать всё, что нужно.

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

Цитата(esaulenka @ Dec 2 2016, 10:48) *
Прерывания в современных контроллерах (читай "cortex-M") - вполне себе недо-операционка. С многими уровнями вложенности задач, если надо.

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

Цитата(esaulenka @ Dec 2 2016, 10:48) *
А вот совет "из г-на и палок быстренько сделайте свой велосипед" может выйти боком, когда через полгода у этого велосипеда окажется 13 колёс.

Так и будет wink.gif И в случае начинающего велосипедостроителя (что мы имеем), первого компонента будет много больше чем 2-го wink.gif

Цитата(haker_fox @ Dec 2 2016, 18:54) *
Да, но я бы не стал (имхо). Нельзя ли просто выделить память статически, или динамически, но создавать её при подключении usb и удалять при отключении?

Для связных применений, особенно если в ПО имеется несколько каналов связи с несколькими драйверами, лучше создать "кучу" в виде распределённого статически массива блоков фиксированного размера. Размер блока (оптимально) == размеру максимального кадра протокола связи (протоколов, если обмен идёт по нескольким протоколам одновременно).
Выделение свободного блока из такой "кучи" можно организовать разными способами. Самый универсальный: изначально поместить дескрипторы всех блоков нашей "кучи" в FIFO-очередь свободных блоков, откуда их будет при необходимости брать каждый драйвер канала связи, заполнять и помещать в другую очередь (или какой другой механизм) на вход целевого процесса (процессов, если протоколов несколько) обработки входящих связных кадров. После обработки и освобождения блока, его дескриптор должен возвращаться в исходную очередь свободных дескрипторов.
Дескриптор блока здесь - это просто индекс соответствующего элемента в массиве-"куче".
Пул свободных дескрипторов и очереди дескрипторов между драйверами связи и обработчиками можно организовать и проще, если дескрипторов мало, то просто можно битмапом в переменной u32 например. Здесь по обстоятельствам.
Такие дескрипторы можно передавать через механизм очередей даже не только между задачами ОС или ISR, но и между процессорами в многоядерной среде, таким образом используя общий пул связных блоков для нескольких ядер.
Atlantis-
Цитата(jorikdima @ Dec 2 2016, 21:49) *
Если ксть СДРАМ, которой обычно много, вы уверены, что вообще нужна дин. память? Тем более только в одном месте, как сказали.

Начал немного сомневаться. В принципе, можно обойтись и статической. Но мне надо заполнять массивы разной длины. Наверно, я мог бы создать один гигантский массив размером во всю СДРАМ, а потом заполнять его, сохраняя адрес и размер выделенного кусочка. Но это же, по сути, делает и malloc. То есть я как бы избавил себя от лишней работы.
novikovfb
Цитата(Atlantis- @ Dec 5 2016, 10:33) *
Начал немного сомневаться. В принципе, можно обойтись и статической. Но мне надо заполнять массивы разной длины. Наверно, я мог бы создать один гигантский массив размером во всю СДРАМ, а потом заполнять его, сохраняя адрес и размер выделенного кусочка. Но это же, по сути, делает и malloc. То есть я как бы избавил себя от лишней работы.

если в один момент времени нужен только один экземпляр этого массива - конечно, лучше статически выделить кусок достаточно большого размера и не мучиться. Вот если этих массивов много и они создаются и уничтожаются в произвольном порядке - тогда необходимо malloc/free.
Atlantis-
Цитата(novikovfb @ Dec 5 2016, 13:04) *
если в один момент времени нужен только один экземпляр этого массива - конечно, лучше статически выделить кусок достаточно большого размера и не мучиться. Вот если этих массивов много и они создаются и уничтожаются в произвольном порядке - тогда необходимо malloc/free.

В один момент времени нужно от 1 до 15 экземпляров массива. Причем, возможна ситуация, когда из одного экземпляра массива читаются данные, а другой экземпляр уничтожается, создается новый другого размера и туда данные записываются.
AlexandrY
Цитата(Atlantis- @ Dec 2 2016, 14:18) *
Не уверен, что точно понял, что Вы имеете ввиду. На осциллографе у меня есть режим Auto и Normal, был включен второй - когда засеченный импульс не уплывает, а остается на экране.


Persistence это вот такой вид как внизу.
Платформа Kinetis MK66 180 МГц, компилятор IAR, оптимизация максмимальная

Запись процесса выделения 1500 блоков памяти случайного размера, но не более 255 байт с помощью malloc
Нажмите для просмотра прикрепленного файла

Запись процесса освобождения 1500 блоков с помощью free.
Нажмите для просмотра прикрепленного файла

Ну что сказать..., юзайте malloc. Он вполне себе детерминированный.

Но все равно потом пожалеете. biggrin.gif
Valentine Loginov
Просто пройду мимо и плюсану тех, кто говорил про memory pool'ы (что там у вас, 15 статически аллоцированных массивов максимальной длины).
Atlantis-
Цитата(Valentine Loginov @ Dec 8 2016, 10:42) *
Просто пройду мимо и плюсану тех, кто говорил про memory pool'ы (что там у вас, 15 статически аллоцированных массивов максимальной длины).

их не 15, их может быть 15 максимум, может быть один, занимающий почти всю память, может быть два и т.д.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.