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

 
 
3 страниц V   1 2 3 >  
Reply to this topicStart new topic
> Использование очереди сообщений
Harvester
сообщение Nov 27 2009, 08:25
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 338
Регистрация: 1-02-06
Из: Королев, М.О.
Пользователь №: 13 846



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

Помогите пожалуйста разобраться с использованием очереди сообщений.
У меня есть процесс (A), периодически передающий пакеты по UART. Второй процесс (cool.gif может в произвольные моменты требовать от
него передачи пакетов, определяемых пользователем. Для этого я собираюсь использовать очередь сообщений.
Но ведь в очередь заносится только указатель на пакет, а как быть с самими данными, особенно если пришло несколько запросов подряд?

Правильно ли я понимаю, что мне необходимо помимо очереди создать что-то вроде кольцевого буфера и обернуть функции POST и PEND для очереди сообщений в свои функции, которые будут брать/класть указатель из/в очереди, извлекать данные из буфера и обслуживать указатели этого буфера?

Спасибо.

PS. Пока писал сообщение, в голову пришла ещё одна мысль - процесс B динамически выделяет память, а процесс A после вычитывания сообщения её освобождает.


--------------------
-Да как так-то?/-Да как-то так/-Ну так-то да
Go to the top of the page
 
+Quote Post
Dima_G
сообщение Nov 27 2009, 08:32
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699



Все зависит от того - что подразумеватеся под элементом очереди. Если буфер (+указатель на следующий элемент), то дополнительного пула не нужно))))

Динамически выделять / освобождать память не сильно хорошая идея в embedded системах
Go to the top of the page
 
+Quote Post
Harvester
сообщение Nov 27 2009, 08:45
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 338
Регистрация: 1-02-06
Из: Королев, М.О.
Пользователь №: 13 846



Цитата(Dima_G @ Nov 27 2009, 11:32) *
Все зависит от того - что подразумеватеся под элементом очереди. Если буфер (+указатель на следующий элемент), то дополнительного пула не нужно))))

Динамически выделять / освобождать память не сильно хорошая идея в embedded системах


В большинстве осей, в той же uC/OS в очереди хранятся именно указатели.

А по второму замечанию - полностью согласен. Потому, наверное, эта идея пришла только в самый последний момент (как самая негодная) smile.gif

Сообщение отредактировал Harvester - Nov 27 2009, 08:47


--------------------
-Да как так-то?/-Да как-то так/-Ну так-то да
Go to the top of the page
 
+Quote Post
Dima_G
сообщение Nov 27 2009, 08:53
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699



Цитата(Harvester @ Nov 27 2009, 12:45) *
В большинстве осей, в той же uC/OS в очереди хранятся именно указатели.


Ну а что мешает сделать свою очередь?

Ни либо на указателях я бы делал так:
хранил отдельно пул буферов

Создал бы очередь - обозвал бы ее FreeQueue
Создал бы очередь в драйвере - назвал TxQueue;

Далее - приложение берет из очереди FreeQueue указатель (считай - буфер), заполняет буфер и помещает указатель на него в TxQueue

Драйвер обнаруживет в TxQueue пакет, обрабатывает его (передает), и помещает в FreeQueue


как-то так smile.gif
Go to the top of the page
 
+Quote Post
Harvester
сообщение Nov 27 2009, 11:38
Сообщение #5


Местный
***

Группа: Участник
Сообщений: 338
Регистрация: 1-02-06
Из: Королев, М.О.
Пользователь №: 13 846



Цитата(Dima_G @ Nov 27 2009, 11:53) *
Ну а что мешает сделать свою очередь?

Ни либо на указателях я бы делал так:
хранил отдельно пул буферов

Создал бы очередь - обозвал бы ее FreeQueue
Создал бы очередь в драйвере - назвал TxQueue;

Далее - приложение берет из очереди FreeQueue указатель (считай - буфер), заполняет буфер и помещает указатель на него в TxQueue

Драйвер обнаруживет в TxQueue пакет, обрабатывает его (передает), и помещает в FreeQueue


как-то так smile.gif

А ведь так можно вообще обойтись без очереди - использовать пул буферов и счётный семафор!


--------------------
-Да как так-то?/-Да как-то так/-Ну так-то да
Go to the top of the page
 
+Quote Post
zltigo
сообщение Nov 27 2009, 11:59
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(Harvester @ Nov 27 2009, 14:38) *
А ведь так можно вообще обойтись без очереди - использовать пул буферов и счётный семафор!

Нафига организовывать очередь руками из дополнительного буфера и семафора, если их поддержка УЖЕ ЕСТЬ в системе.
Если очередь можно пользовать только для указателей, то нужно только добавить к ней один буфер и все.

Цитата(Harvester @ Nov 27 2009, 11:45) *
В большинстве осей, в той же uC/OS в очереди хранятся именно указатели.

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


Цитата(Dima_G @ Nov 27 2009, 11:32) *
Динамически выделять / освобождать память не сильно хорошая идея в embedded системах

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


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Dima_G
сообщение Nov 27 2009, 12:23
Сообщение #7


Местный
***

Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699



Цитата(zltigo @ Nov 27 2009, 15:59) *
Нафига организовывать очередь руками из дополнительного буфера и семафора, если их поддержка УЖЕ ЕСТЬ в системе.
Если очередь можно пользовать только для указателей, то нужно только добавить к ней один буфер и все.


Под буфером, Вы имеете в виду - циклический буфер?

Мне большей частью удобнее НЕ использовать системные очереди. Исключительно из-за их "сишной" природы, как следствие - потери информации о типе вложенного объекта
Go to the top of the page
 
+Quote Post
Harvester
сообщение Nov 27 2009, 12:47
Сообщение #8


Местный
***

Группа: Участник
Сообщений: 338
Регистрация: 1-02-06
Из: Королев, М.О.
Пользователь №: 13 846



Цитата(zltigo @ Nov 27 2009, 14:59) *
Нафига организовывать очередь руками из дополнительного буфера и семафора, если их поддержка УЖЕ ЕСТЬ в системе.

Вообще-то это не я придумал. Это написал Лабросс в книге по uC/OS, как пример использования счетного семафора.

Цитата(zltigo @ Nov 27 2009, 14:59) *
Если очередь можно пользовать только для указателей, то нужно только добавить к ней один буфер и все.

Действительно, как-то сразу не подумал. Ведь ядро уже контролирует заполненность очереди. И если очередь не полна,
значит, как минимум, одно из самых ранних сообщение уже вычитано и отправитель может писать данные в очередную секцию кольцевого буфера.
Это действительно проще связного списка.

Спасибо!

Сообщение отредактировал Harvester - Nov 27 2009, 12:47


--------------------
-Да как так-то?/-Да как-то так/-Ну так-то да
Go to the top of the page
 
+Quote Post
zltigo
сообщение Nov 27 2009, 13:03
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(Dima_G @ Nov 27 2009, 15:23) *
Под буфером, Вы имеете в виду - циклический буфер?

Совершенно не имеет значения какой - любой, какой оптимален для данного типа данных, нагрузки и прочего. Довольно часто очень просто и удобно реализуются линейные под фрейм расположенные внутри кольцевого. А если фреймы фиксированной длинны, то сам бог велел так делать - 0 недостатков.
Цитата
Мне большей частью удобнее НЕ использовать системные очереди. Исключительно из-за их "сишной" природы, как следствие - потери информации о типе вложенного объекта

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


Цитата(Harvester @ Nov 27 2009, 15:47) *
И если очередь не полна,значит, как минимум, одно из самых ранних сообщение уже вычитано и отправитель может писать данные в очередную секцию кольцевого буфера.

И если полна, то тоже может, ибо должны быть ДВА указателя - на чтение, который проходит через очередь до процесса передачи читающий из буфера передачи и отдельно болтающийся указатель на запись, по которому вне зависимости (ну кроме контроля за фатальным переполнением) от наличия в буфере непереданных фреймов осуществляется запись.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Harvester
сообщение Nov 27 2009, 13:41
Сообщение #10


Местный
***

Группа: Участник
Сообщений: 338
Регистрация: 1-02-06
Из: Королев, М.О.
Пользователь №: 13 846



Цитата(zltigo @ Nov 27 2009, 16:03) *
И если полна, то тоже может, ибо должны быть ДВА указателя - на чтение, который проходит через очередь до процесса передачи читающий из буфера передачи и отдельно болтающийся указатель на запись, по которому вне зависимости (ну кроме контроля за фатальным переполнением) от наличия в буфере непереданных фреймов осуществляется запись.

Что-то теперь я совсем запутался. 07.gif Как может указатель на запись"отдельно болтаться", если именно его необходимо класть в очередь после заполнения фрейма буфера. И потом, если уж мы используем два указателя, т.е. организуем кольцевой буфер, то какой смысл в очереди? Проще ведь будет использовать счетный семафор, да и по ресурсам выгоднее.


--------------------
-Да как так-то?/-Да как-то так/-Ну так-то да
Go to the top of the page
 
+Quote Post
Dima_G
сообщение Nov 27 2009, 14:57
Сообщение #11


Местный
***

Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699



Цитата(zltigo @ Nov 27 2009, 16:03) *
Еруда полная, а не причина, либо тип фиксирован, либо Вы его по любому будете восстанавливать по, например, заголовку.


Реализации универсальных сишных очередей, которые я видел - обычно работают с void указателем на элемент:

Код
push(void* pObj_);
void* pop();


соответственно, никто не застрахован от ошибок

В С++ можно использовать такой подход

Цитата
template <class ELEMENT>\
class TClQueue
{
push(ELEMENT* pclEl_);
ELEMENT* pop();

};



В эту очередь получится запихать либо ELEMENT, либо производные от него
Go to the top of the page
 
+Quote Post
Andron_
сообщение Nov 27 2009, 15:12
Сообщение #12


.NET developer
***

Группа: Свой
Сообщений: 218
Регистрация: 20-10-07
Из: Новосибирск
Пользователь №: 31 532



Цитата
Динамически выделять / освобождать память не сильно хорошая идея в embedded системах


а можно аргументировать? сам применяю new/delete и пытаюсь понять - будут грабли или нет.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Nov 27 2009, 15:42
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(Harvester @ Nov 27 2009, 16:41) *
Что-то теперь я совсем запутался. 07.gif Как может указатель на запись"отдельно болтаться", если именно его необходимо класть в очередь после заполнения фрейма буфера.

Вопросы кто чем для кого является smile.gif возможен взгляд с разных сторон smile.gif. В очередь кладется указатель чтения - по нему процесс передачи читает из буфера, то, что он будет передавать smile.gif. Указатель записи это принадлежность функции, которая заполняет буфер передачи - по нему будет занесен фрейм и его значение до занесения фрейма будет помещено в очередь.
Цитата
И потом, если уж мы используем два указателя, т.е. организуем кольцевой буфер, то какой смысл в очереди? Проще ведь будет использовать счетный семафор, да и по ресурсам выгоднее.

То, что Вы пытаетесь описать, вообще буфера не требует smile.gif, поскольку Вы упорно предполагаете, что в кольцевом буфере по определению рассчитанном на МНОГО фреймов лежит ОДИН. Для одного нужен ОДИН указатель - нет вопросов. Если Мы действительно используем кольцевой буфер, как буфер, а не лишнюю приблуду, то в нем могут лежать МНОГО фреймов, для них нужно МНОГО указателей. Эти указатели и лежат в очереди до того момента, когда процесс передачи извлечет очередной и начнет по нему вытаскивать из буфера информацию.



Цитата(Dima_G @ Nov 27 2009, 17:57) *
соответственно, никто не застрахован от ошибок

Поверье мне, что ошибок Вы и так наделаете.
Цитата
В С++ можно использовать такой подход

Ненужные выкрутасы на ровном месте для ЧАСТНОГО случая. Ничего, кроме лишнего разнообразия в решении не дает.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Dima_G
сообщение Nov 27 2009, 16:11
Сообщение #14


Местный
***

Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699



Цитата(zltigo @ Nov 27 2009, 18:42) *
Поверье мне, что ошибок Вы и так наделаете.

Ненужные выкрутасы на ровном месте для ЧАСТНОГО случая. Ничего, кроме лишнего разнообразия в решении не дает.


Это я уже обсуждать не буду, а то тема сведется к холивару С vs С++.
Остановимся на том, что почему-то мне так удобнее smile.gif


Цитата(Andron_ @ Nov 27 2009, 19:12) *
а можно аргументировать? сам применяю new/delete и пытаюсь понять - будут грабли или нет.


Можно столкнуться с фрагментацией памяти
Ненормированное время выделения памяти
Нереентерабельность выделения памяти
Ну и мое ИМХО - при статическом распределении ресурсов система более предсказуема smile.gif

вот, почитайте - зедсь есть немного про это
http://www.embedded.com/story/OEG20020222S0026

Сообщение отредактировал Dima_G - Nov 27 2009, 16:15
Go to the top of the page
 
+Quote Post
zltigo
сообщение Nov 27 2009, 16:49
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(Dima_G @ Nov 27 2009, 19:11) *
Это я уже обсуждать не буду, а то тема сведется к холивару С vs С++.
Остановимся на том, что почему-то мне так удобнее smile.gif

C++ тут АБСОЛЮТНО ни причем - на любом языке можете наваять оберток не имеющих никакого смысла и главное годящихся только для частного случая. Изобразить, например, "специальную очередь" для какого-либо фрейма можно по любому, только кроме лишнего исходного текста и лишних сущностей такие выкрутасы не дают ничего.



Цитата(Dima_G @ Nov 27 2009, 19:11) *
Можно столкнуться с фрагментацией памяти

А можно и нет, если принять меры.
Цитата
Ненормированное время выделения памяти

Ну не надо использовать, например, линукс с файлами подкачки и прочим. Хотя именно в том-же линуксе драйвера делают и много много более мрачные системные вызовы smile.gif
Цитата
Нереентерабельность выделения памяти

Ну это если совсем без головы на плечах.
Цитата
Ну и мое ИМХО - при статическом распределении ресурсов система более предсказуема smile.gif

Эх, конечно. Только вот если с ресурсами напряг и всем нарезать их про запас не хватает?


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 21st July 2025 - 18:46
Рейтинг@Mail.ru


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