Вход/Регистрация
Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform
вернуться

Кёртен Роб

Шрифт:
Функция MsgReceivePulse

Функции MsgReceive и MsgReceivev могут принимать либо стандартное сообщение, либо импульс. Однако, возможны ситуации, когда вы пожелаете принимать только импульсы. Лучшим примером этого является ситуация с сервером, когда вы приняли запрос от клиента на выполнение чего-нибудь, но не можете выполнить этот запрос сразу (возможно, из-за длительной операции, связанной с аппаратными средствами). В таких случаях следует, как правило, настроить аппаратные средства (или таймер, или что-нибудь еще) на передачу вам импульса всякий раз, когда происходит некое значительное событие.

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

В таком случае вам потребуется обеспечить возможность «выборочного» приема только импульсов. Тут-то и становится актуальной функция MsgReceivePulse:

#include <sys/neutrino.h>

int MsgReceivePulse(int chid, void *rmsg, int rbytes,

 struct _msg_info *info);

Видно, что ее параметры те же, что и у функции MsgReceive — идентификатор канала, буфер (и его размер), и параметр info — мы обсуждали его в параграфе «Кто послал сообщение?» Заметьте, что параметр info не применяется в импульсах. Вы можете спросить, почему он представлен в списке параметров. Ответ незамысловат: так было проще сделать. Просто передайте NULL!

Функция MgsReceivePulse способна принимать только импульсы. Так, если бы у вас был канал с множеством потоков, блокированных на нем с помощью функции MsgReceivePulse (и ни одного потока, блокированного на нем с помощью функции MsgReceive), и некий клиент попытался бы отправить вашему серверу сообщение, то этот клиент остался бы заблокированным по передаче (Send-blocked) до тех пор, пока какой-либо поток сервера не вызовет MsgReceive. Тем временем функция MsgReceivePulse будет спокойно принимать импульсы.

Единственное, что можно гарантировать при совместном применении функций MsgReceivePulse и MsgReceive, — что функция MsgReceivePulse обеспечит прием исключительно импульсов. Функция MsgReceive сможет принимать как импульсы, так и обычные сообщения! Это происходит потому, что применение функции MsgReceivePulse зарезервировано специально для случаев, где нужно исключить получение сервером обычных сообщений.

Это немного вводит в замешательство. Так как функция MsgReceive может принимать и обычные сообщения, и импульсы, а функция MsgReceivePulse может принимать только импульсы, то как быть с сервером, в котором применяются обе функции? Общий ответ такой. У вас есть пул потоков, выполняющих MsgReceive. Этот пул потоков (один или более потоков — это зависит от числа клиентов, которое вы хотели бы обслуживать одновременно) отвечает за обработку запросов от клиентов.

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

Функция MsgDeliverEvent

Как было упомянуто выше в параграфе «Иерархический принцип обмена», существуют ситуации, когда приходится нарушать естественное направление передач.

Такой случай возможен, когда у вас есть клиент, который посылает серверу сообщение и при этом не хочет блокироваться, а результат может быть доступен только через некоторое время. Конечно, вы могли бы частично решить эту проблему путем применения многопоточных клиентов, выделяя в клиенте отдельный поток для блокирующих вызовов сервера, но это не всегда с успехом работает в больших системах, поскольку при большом количестве серверов количество ждущих потоков было бы слишком велико. Но допустим, вы не хотите здесь использовать многопоточность, а вместо этого вам нужно, чтобы сервер ответил клиенту сразу, и чем-то вроде «Заказ принят; я скоро вернусь». Здесь, поскольку сервер ответил, клиент теперь свободен продолжать свою работу. После того как сервер отработает запрос клиента, ему потребуется как-то сказать клиенту «Проснись, вот твой заказ.» Очевидно, как мы это уже видели при анализе иерархического принципа обмена, сервер не должен передавать сообщения клиенту, потому что если клиент в это же время отправит сообщение серверу, это может вызывать взаимную блокировку. Так как же сервер может послать сообщение клиенту без нарушения иерархического принципа?

  • Читать дальше
  • 1
  • ...
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: