|
Система обмена сообщения между отдельными модулями программы |
|
|
|
May 26 2013, 22:46
|

Частый гость
 
Группа: Свой
Сообщений: 129
Регистрация: 28-09-10
Из: Москва
Пользователь №: 59 793

|
Цитата(Слесарь @ May 27 2013, 01:47)  Использование системы сообщений, это прекрасный и естественный образ программирования, когда приходят сообщения, тут сразу информация о актуальности данных и сами данные. Не всегда. В вашем примере если функция вывалится до (или вы забудите написать) DeleteMessage(), сразу получите проблему. Вообще принято сообщение удалять из очереди при его обработке, т.е. в GetMessage. И очередь событий нужна, когда у вас действительно ОЧЕРЕДЬ, т.е. одинаковых событий может быть больше чем одно и они должны выполняться в последовательности их поступления. А судя по вашему примеру это явно избыточные функции. Есть более простые решения, например: задайте структуру типа {int flag;int data1;...} Определите массив таких структур с числом элементов соответствующим общему количеству сообщений. Определите ваши сообщения типа #define MESSAGE_SIM900_DTMF 1 /*Индекс в массиве*/ И ваша функция GetMessage будет возвращать структуру из массива по индесу. flag - используете как флаг актуальноти или счетчик обращений.
|
|
|
|
|
May 27 2013, 06:45
|
Гуру
     
Группа: Свой
Сообщений: 2 884
Регистрация: 7-11-09
Из: Ростовская обл.
Пользователь №: 53 484

|
Цитата(zöner @ May 27 2013, 01:08)  очень просто - через вторую стат.переменную (напр. t_rdy). Такой стиль программирования не для меня. С таким стилем приходится много думать и помнить, с этим постоянно проблемы. Вы сами подумайте, одно дело видеть как сигнал поступает и вы его обрабатываете, или другое дело вы сами заботитесь о том чтоб удостоверится о наличие сигнала дополнительной переменной или функцией чтоб потом сигнал обработать. какой стиль более естественный для восприятия? Цитата(Petr_I @ May 27 2013, 01:46)  Не всегда. В вашем примере если функция вывалится до (или вы забудите написать) DeleteMessage(), сразу получите проблему. Вообще принято сообщение удалять из очереди при его обработке, т.е. в GetMessage. И очередь событий нужна, когда у вас действительно ОЧЕРЕДЬ, т.е. одинаковых событий может быть больше чем одно и они должны выполняться в последовательности их поступления. А судя по вашему примеру это явно избыточные функции.
Есть более простые решения, например: задайте структуру типа {int flag;int data1;...} Определите массив таких структур с числом элементов соответствующим общему количеству сообщений. Определите ваши сообщения типа #define MESSAGE_SIM900_DTMF 1 /*Индекс в массиве*/ И ваша функция GetMessage будет возвращать структуру из массива по индесу. flag - используете как флаг актуальноти или счетчик обращений. Я подвожу к тому чтоб создать некий шаблон оформления программ, на автомате создаем Task() функцию для каждого модуля ПО, как было описано выше в эту функцию поочередно передается процессор, если никаких действий выполнять не требуется, из функции необходимо сделать возврат. В начале функции удаляем все старые сообщения которые могут быть посланы функцией, далее проверяем нет ли новых сообщений которые эта функция может обработать от других модулей, обрабатываем их, и на последок, если произошли события, отправляем новые сообщения из этой функции, возвращаем процессор для других задач. Так поступает любой программный модуль. Будет удобно создать конструктор который будет генерировать основной шаблон функции Task. Вы работали когда-нить с MSVS ? Кликаешь вызов конструктора, в окне конструктора вводишь список всех обрабатываемых сообщений, вводишь список сообщений которые будут посылаться из модуля, вводишь другие параметры и нажимаешь ОК, конструктор создает общий шаблон фукции на C, далее программист просто впишет код обработчиков тех или иных входящих сообщений, опишет события при которых будут посланы исходящие сообщения. Никакой путаницы быть не должно. А если еще многое спрятать под макросы, то должно получиться очень читабельно. хотя макросы я не очень люблю ДА. Очередь сообщений должна быть правильной, сначала старые одноименные сообщения, потом только новые. Единственно что сейчас меня беспокоит в таком подходе, это если делать временное тактирование для кождого модуля через систему сообщений. Допустим, в системе требуется самая минимальная задержка для программного обработчика протокола 1-wire, это 6 мкс. , то есть модуль генерирующий сообщения о времени должен каждые 6 мкс слать сообщение MESSAGE_TACT_6MKS, это сообщение должно просуществовать пока не исполнятся все модули ПО и удалиться. Не будет ли разовая работа всех модулей занимать больше времени чем 6 мкс? сообщения могут накапливаться и не успевать вовремя выполняться.
|
|
|
|
|
May 27 2013, 14:26
|
Гуру
     
Группа: Свой
Сообщений: 2 884
Регистрация: 7-11-09
Из: Ростовская обл.
Пользователь №: 53 484

|
Цитата(AlexandrY @ May 27 2013, 11:12)  Хоть я и не улавливаю тут полностью вашу идею, но скажу что в RTOS не видел никогда чтобы сообщения сами удалялись в сервисах RTOS. Я подозреваю, что это вызвало бы создания моря таймеров и потерю производительности. Задачи приемники просто останавливаются при ожидании сообщений, а задачи передатчики либо всегда могут передать сообщение (в виде флагов) либо получают ошибку переполнения сервиса (конвейеры, майлбоксы, пайпы и т.д.) при сильном запаздывании задачи приемника. Чтобы сообщение было отправлено и жило бы своей жизнью (само бы удалилось без ведома основного приложения) это нонсенс, который точно приведет рано или поздно к повреждению крыши у программиста.  Да. Вы не поняли суть идеи и не посмотрели представленный код. Сообщения подчищает отправитель после того как сообщения гарантированно побывали во всех модулях ПО. В моей системе задачи не останавливаются при ожидании сообщений, задачи не задерживают процессор если сообщения не поступали, отдают процессор для других очередных задач.
|
|
|
|
|
May 27 2013, 17:58
|
Гуру
     
Группа: Свой
Сообщений: 2 884
Регистрация: 7-11-09
Из: Ростовская обл.
Пользователь №: 53 484

|
Цитата(AlexandrY @ May 27 2013, 17:42)  задача не тупо должна отдавать управление следующей по списку, которой управление тоже может быть в данный момент не нужно, а передавать управление строго туда где оно необходимо в силу назревших событий или поступивших сообщений. В двоичных системах управление передается всем задачам поочередно, и только сами задачи знают назрела ли необходимость что-либо исполнять. никакого централизованного знатока нет. например в PC для каждой задачи выделяется около 45 мкс времени, если задача не уложилась в этот срок с выполнением своей работы, управление отбирается принудительно внешним управляющим модулем(диспетчером), если успела, то возвращает управление самостоятельно раньше срока. Не знаю откуда вы взяли что процессорное время раздается как-то иначе, не последовательно для каждой из задач. Цитата(AlexandrY @ May 27 2013, 17:42)  И здесь я вас поздравлю. Вы готовы к использованию RTOS!  Нет. Еще не готов. У самого как-то пока не плохо получается управляться с ресурсами процессора. Не забывайте что ОС стали популярны только тогда, когда стали выполнять всю черновую работу программ, например диски и файлы, что не актуально в среде МК.
|
|
|
|
|
May 28 2013, 09:19
|
Местный
  
Группа: Свой
Сообщений: 289
Регистрация: 6-12-05
Пользователь №: 11 864

|
Цитата Нет. Еще не готов. У самого как-то пока не плохо получается управляться с ресурсами процессора. Не забывайте что ОС стали популярны только тогда, когда стали выполнять всю черновую работу программ, например диски и файлы, что не актуально в среде МК. RTOS для контроллера нужна в первую очередь для параллельного выполнения задач. Если Вам нужно в каком то модуле ожидать данные длительное время (на пример пока датчик температуры производит измерение. Для примера ds18b20 измеряет около 0.7 секунд) то остальные задачи будут параллельно выполняться а не ждать пока отработает этот модуль. Конечно это можно реализовать с помощью цифровых автоматов и каждый раз когда вы заходите в этот модуль проверять не прошло ли время ожидания, но такой способ усложняет код и увеличивает время написания программы. RTOS не нужна в двух случаях: 1) - это когда у контроллера очень мало ресурсов (например мало оперативной памяти) 2) когда на контроллере выполняется всего лишь одна задача.
|
|
|
|
|
May 31 2013, 06:02
|
Знающий
   
Группа: Участник
Сообщений: 837
Регистрация: 8-02-07
Пользователь №: 25 163

|
Во-первых, Вам нужно избавиться от суперлупа и воткнуть ртос. Это увеличит производительность Вашего процессора без изменения логики работы. Во-вторых, код с отправкой сообщений интересный. Мне нравится. В-третьих, я для себя тоже сделал многопоточную очередь сообщений - для того, чтобы перетаскивать обработку данных из контекста одного потока в контекст другого. Сразу скажу, на си это выглядит довольно криво, съедает избыточную память и в большинстве случаев очередь как таковая не требуется - создаётся очередь из одного элемента. Для того, чтобы не было переполнения при отсутствии приёмника сообщений, я сделал ограничение размера в конструкторе очереди. Для того, чтобы не было фрагментации памяти, память под очередь выделяется статически на этапе компиляции.
Да, кстати, аналогичный Вашему код есть и у меня в проекте. По сути это защищенная от многопоточного доступа переменная. У нас вместо SendMessage и GetMessage используется WriteRegister и ReadRegister.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|