реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> FreeRTOS + lwIP, Ошибка выделения памяти
_Mikhail_
сообщение Feb 4 2015, 09:31
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 55
Регистрация: 19-04-11
Пользователь №: 64 477



Добрый день!
Имеются FreeRTOS 8 + lwIP 1.4.1 + LPC2478.
Столкнулся с такой проблемой. Работаю через Netconn API. Шлю на плату TCP пакеты (утилитой netcat передаю файлы по X Мб). Какое-то время пакеты проходят через стек нормально (10...20...40 Мб). Но в какой-то момент времени стек все чаще и чаще начинает выдавать отказ в выделении памяти под принятый пакет (memp_malloc_fn), пока прием совсем не "захлебывается". При этом передача от платы через другое соединение работает нормально. Принятые пакеты netconn_recv не обрабатываю, а просто отбрасываю (пока), затем удаляю буфер netbuf_delete. Стеки, кучи операционки большие и пустые. В lwipopts.h тоже памяти выделено достаточно. Стек по какой-то причине выделяет больше пулов, чем освобождает. Причину утечки никак найти не могу. На вход стека с mac пакеты выдаю корректные (по крайней мере так думаю).
Может кто сталкивался с подобной проблемой, в каком направлении копать?

Прикрепленный файл  ethernetif.zip ( 1.65 килобайт ) Кол-во скачиваний: 85
Go to the top of the page
 
+Quote Post
WitFed
сообщение Feb 5 2015, 12:01
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 271
Регистрация: 6-12-11
Из: Taganrog
Пользователь №: 68 701



На заступ надо провериться -- вдруг данных пишется больше, чем ожидалось (или железо пинается не на те адреса, выгрузка "в молоко"), портятся системные области, а там уже и "рух" недалеко.
Если нет такого "системного" средства в ОС, надо как-то "встрять" в каждое выделение/освобождение памяти, выделять на 16 байт больше, заливать первые 8 чем-то "особым", типа "DEADBEAF", последние 8 аналогично и возвращать указатель +8, ну а при возврате -- проверять на "особость". Обычно "вдаль" сразу никто не заступает, и так ловится большинство проблем.
Если этот заступ, конечно, был давно, определить причину будет трудно, ибо придётся отмотать момент выделения данного куска, кому он был нужен и для чего.
Тогда нужно стабилизировать наступление глюка: например, "принимать" пакеты не из физики, а из рандомного генератора. Вдруг при его стабильном стартовом значении и дальше всё будет повторяться 1в1...

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

Реентерабельность вдруг где хромает, семафор где-то "застреливают" аппаратной выгрузкой, возвращаемое значение при захвате не анализируют полностью...

Абсолютно детерминированная "повторябельность на N-м такте" при лечении глюков может сильно помочь, её надо добиваться в первую очередь. Тогда, в принципе, можно остановиться на любом предыдущем и проследить всё остальное. Где-то и "назад" могут степать отладчики, но жить в эту пору прекрасную... wink.gif

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

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

TCP в данном случае достаточно нехороший протокол (там много форматных излишеств ради восстановления пропавших пакетов, которые в локалке очень трудно сейчас "задушить"), легче через UDP попытаться вести "обстрел".
Go to the top of the page
 
+Quote Post
_Mikhail_
сообщение Feb 9 2015, 08:03
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 55
Регистрация: 19-04-11
Пользователь №: 64 477



Цитата(WitFed @ Feb 5 2015, 16:01) *
На заступ надо провериться -- вдруг данных пишется больше, чем ожидалось (или железо пинается не на те адреса, выгрузка "в молоко"), портятся системные области, а там уже и "рух" недалеко.
Если нет такого "системного" средства в ОС, надо как-то "встрять" в каждое выделение/освобождение памяти, выделять на 16 байт больше, заливать первые 8 чем-то "особым", типа "DEADBEAF", последние 8 аналогично и возвращать указатель +8, ну а при возврате -- проверять на "особость". Обычно "вдаль" сразу никто не заступает, и так ловится большинство проблем.
Если этот заступ, конечно, был давно, определить причину будет трудно, ибо придётся отмотать момент выделения данного куска, кому он был нужен и для чего.
Тогда нужно стабилизировать наступление глюка: например, "принимать" пакеты не из физики, а из рандомного генератора. Вдруг при его стабильном стартовом значении и дальше всё будет повторяться 1в1...

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

Реентерабельность вдруг где хромает, семафор где-то "застреливают" аппаратной выгрузкой, возвращаемое значение при захвате не анализируют полностью...

Абсолютно детерминированная "повторябельность на N-м такте" при лечении глюков может сильно помочь, её надо добиваться в первую очередь. Тогда, в принципе, можно остановиться на любом предыдущем и проследить всё остальное. Где-то и "назад" могут степать отладчики, но жить в эту пору прекрасную... wink.gif

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

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

TCP в данном случае достаточно нехороший протокол (там много форматных излишеств ради восстановления пропавших пакетов, которые в локалке очень трудно сейчас "задушить"), легче через UDP попытаться вести "обстрел".


Я кое-что из предложенного уже перепробовал. И точки останова ставил, и собирал статистику выделений-освобождений и т.д. и т.п. Не догадался подсовывать на вход стека сгенерированные данные. Повторяемости нет. С длинами пакетов все нормально, с семафорами, критическими секциями тоже все в порядке. Трудность в том, что что-то ломается значительно раньше, чем это уже проявляется.

Пока остановился на том, что полноценный стек для моей задачи не нужен (просто хотелось его пощупать). Время, которое я мог себе позволить на решение этой проблемы, закончилось.
Сейчас уже проще самому написать простейшую реализацию UDP, чем сейчас и занялся. А с потерей пакетов разбираться буду уже на прикладном уровне.
Дальше планирую работать с кортексами, а там есть уже готовые связки (почти официальные, только до ума довести, под себя подстроить) стека, ОС (например в LPCExpresso). Возможно там такой проблемы уже не будет.
Но вообще разобраться было бы интересно. При случае кое-что из предложенного попробую. Спасибо.
Go to the top of the page
 
+Quote Post
den_po
сообщение Feb 9 2015, 11:48
Сообщение #4


Частый гость
**

Группа: Участник
Сообщений: 139
Регистрация: 9-11-12
Из: Санкт-Петербург
Пользователь №: 74 315



Память выделяется с помощью pvPortMalloc?
Go to the top of the page
 
+Quote Post
_Mikhail_
сообщение Feb 9 2015, 13:54
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 55
Регистрация: 19-04-11
Пользователь №: 64 477



Цитата(den_po @ Feb 9 2015, 15:48) *
Память выделяется с помощью pvPortMalloc?


На сколько я понял, то LwIP имеет свой механизм выделения памяти. При беглом просмотре он потокобезопасен.

В том варианте, в каком я использую стек, он выделяет память единожды, а потом выделяет/освобождает пулы под/от данные, не пользуясь функциями типа malloc. Я в этот механизм не вмешиваюсь. У меня получается, что заканчиваются свободные пулы при p = pbuf_alloc( PBUF_RAW, len, PBUF_POOL ) (и дальше по цепочке до memp_malloc_fn).

Но пробовал и другие варианты, результат аналогичен.

Мне кажется, что проблема явно не в самом стеке, а в его порте (emac.c, ethernetif.c) или я что-то не правильно настроил в lwipopts.h

Go to the top of the page
 
+Quote Post
den_po
сообщение Feb 9 2015, 14:31
Сообщение #6


Частый гость
**

Группа: Участник
Сообщений: 139
Регистрация: 9-11-12
Из: Санкт-Петербург
Пользователь №: 74 315



Цитата(_Mikhail_ @ Feb 9 2015, 18:54) *
На сколько я понял, то LwIP имеет свой механизм выделения памяти.

В общем да, но зависит от.
На всякий случай можно перепроверить константы MEM_* и MEMP_*
lwip\src\include\lwip\opt.h
lwipopts.h
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 7th July 2025 - 16:52
Рейтинг@Mail.ru


Страница сгенерированна за 0.01403 секунд с 7
ELECTRONIX ©2004-2016