Прием импульса
Прием импульса
Прием импульса выполняется очень просто: короткое, четко определенное сообщение передается функции MsgReceive(), как будто поток отправил обычное стандартное сообщение. Единственное различие состоит в том, что вы не сможете применить функцию MsgReply() к такому сообщению, поскольку, кроме всего прочего, общая идея импульса состоит в том, что это сообщение по своей сути является асинхронным. В данном разделе мы рассмотрим другую функцию, MsgReceivePulse(), применение которой полезно при обработке импульсов.
Единственно что забавляет при работе с импульсами — это то, что идентификатор отправителя, который возвращается функцией MsgReceive() при их приеме, имеет нулевое значение. Это верный индикатор того, что принятое сообщение является импульсом, а не стандартным сообщением клиента. В коде серверов вы будете часто видеть фрагменты, подобные представленному ниже:
#include <sys/neutrino.h>
rcvid = MsgReceive(chid, ...);
if (rcvid == 0) { // Это импульс
// Определить тип импульса
// Обработать его
} else { // Это обычное сообщение
// Определить тип сообщения
// Обработать его
}
Что внутри импульса?
Итак, вы принимаете сообщение с нулевым идентификатором отправителя. Что у него внутри? Вот фрагмент заголовочного файла <sys/neutrino.h>:
struct _pulse {
_uint16 type;
_uint16 subtype;
_int8 code;
_uint8 zero[3];
union sigval value;
_int32 scoid;
};
Элементы type и subtype равны нулю (это еще один признак того, что перед нами импульс); содержимое элементов code и value определяется отправителем. В общем случае элемент code будет указывать на причину, по которой был отправлен импульс, а параметр value будет содержать 32 бита данных, ассоциируемых с данным импульсом. Эти два поля и есть те самые 40 бит контента; другие поля пользователем не настраиваются.
Ядро резервирует отрицательные значения параметра code, оставляя 127 значений для программистов — для использования по своему усмотрению.
Элемент value в действительности является элементом типа union:
union sigval {
int sival_int;
void *sival_ptr;
};
Поэтому (в развитие примера с сервером, представленного выше) вы часто будете видеть программу, подобную этой:
#include <sys/neutrino.h>
rcvid = MsgReceive(chid, ...
if (rcvid == 0) { // Импульс
// Определить тип импульса
switch (msg.pulse.code) {
case MY_PULSE_TIMER:
// Сработал один из наших таймеров,
// надо что-то делать...
break;
case MY_PULSE_HWINT:
// Импульс получен от обработчика прерывания.
// Надо заглянуть в поле «value»...
val = msg.pulse.value.sival_int;
// Сделать что-нибудь по этому поводу...
break;
case _PULSE_CODE_UNBLOCK:
// Это импульс от ядра, разблокирующий клиента
// Сделать что-нибудь по этому поводу...
break;
//и так далее...
}
} else { // Обычное сообщение
// Определить тип сообщения
// Обработать его
}
В этой программе предполагается, конечно, что вы описали структуру msg так, чтобы она содержала элемент «struct _pulse pulse;», и что определены константы MY_PULSE_TIMER и MY_PULSE_HWINT. Код импульса _PULSE_CODE_UNBLOCK — один из тех самых отрицательных кодов, зарезервированных для ядра, как это было упомянуто выше. Вы можете найти полный список этих кодов (а также краткое описание поля value) в <sys/neutrino.h>.
Функция 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() принимает только импульсы, а значит, ее применение гарантирует, что пока вы ждете импульса, к вам ненароком не просочится никакой клиентский запрос.
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКЧитайте также
Прием клиентских запросов соединения
Прием клиентских запросов соединения Наконец, сервер может ожидать соединения с клиентом, используя функцию accept, возвращающую новый подключенный сокет, который будет использоваться в операциях ввода/вывода. Заметьте, что исходный сокет, который теперь находится в
Прием и отправка сообщений
Прием и отправка сообщений Общаться, общаться! И немедленно. Благо именно эта функция в программе главная… А сам процесс общения просто до банальности. Хотите написать письмо – щелкаете по имени нужного контакта. Можно вызвать окно сообщений и из контекстного меню
Прием платы за товары и услуги в Интернете
Прием платы за товары и услуги в Интернете Скачайте эту интеллект-карту по адресу: http://smartinfomarketing.ru/book-leads.htmТеперь давайте поговорим об организации приема оплаты за ваши товары, коучинги, тренинги, интернет-семинары. Пройдемся по основным
Прием и отправка сообщений
Прием и отправка сообщений С приемом сообщений по «аське» проблем возникнуть не должно: в момент, когда на ваш компьютер поступает письмо от одного из пользователей ICQ, цветок программы в системном трее сменяется на значок подмигивающей записки. Щелкните по нему – и
Передача и прием дейтаграмм UDP
Передача и прием дейтаграмм UDP Класс QUdpSocket может использоваться для отправки и приема дейтаграмм UDP. UDP — это ненадежный, ориентированный на дейтаграммы протокол. Некоторые приложения применяют протокол UDP, поскольку с ним легче работать, чем с протоколом TCP. По протоколу
Прием поступающих событий
Прием поступающих событий Использование событий в C# позволяет также упростить регистрацию обработчиков событий вызывающей стороны. Вместо необходимости указывать пользовательские вспомогательные методы, вызывающая сторона просто использует операции += и -= (которые в
1.19. Прием пользовательского текстового ввода с помощью UITextField
1.19. Прием пользовательского текстового ввода с помощью UITextField Постановка задачи Необходимо принимать через пользовательский интерфейс программы текст, вводимый
Прием и обработка SMS-сообщений
Прием и обработка SMS-сообщений Итак, мы научились отправлять SMS-сообщения из своей программы. Но было бы неплохо научить приложения принимать подобные сообщения. Для приема сообщений существует пространство имен MessageInterception, которое находится в сборке
18.4.5. Прием потока ввода без применения шаблонных команд
18.4.5. Прием потока ввода без применения шаблонных команд После шаблонной части необязательно указывать команды; если после шаблонной части команды отсутствуют, до перехода к дальнейшей обработке выполняется фильтрация нежелательных откликов.Если в отдел учета следует
Прием «кулисы»
Прием «кулисы» Этот эффектный композиционный прием заключается в том, что объект помещают в своего рода «рамку». Очень интересные фотографии получаются, когда съемка ведется из арки ворот, из пещеры, да и просто сквозь ветви куста, – при этом объект получается
Глава 1 ПРИЕМ КАБЕЛЬНЫХ И ЭФИРНЫХ ТЕЛЕКАНАЛОВ
Глава 1 ПРИЕМ КАБЕЛЬНЫХ И ЭФИРНЫХ ТЕЛЕКАНАЛОВ Наверное, у каждого человека сегодня есть дома телевизор, а чаще их даже несколько. Многие любят смотреть телепередачи, сидя в кресле, расслабляясь после рабочего дня. Примерно у половины владельцев телевизоров дома есть еще и
Глава 5 ПРИЕМ СПУТНИКОВЫХ ТЕЛЕКАНАЛОВ
Глава 5 ПРИЕМ СПУТНИКОВЫХ ТЕЛЕКАНАЛОВ Собрав и настроив систему для просмотра телевидения на домашнем компьютере, осталось разобраться с программами, позволяющими просматривать видео на компьютере, – с виртуальными телевизорами. Обычно в комплекте с DVB-тюнером идет
Глава 11 Отправка и прием факсов
Глава 11 Отправка и прием факсов Лучше всего с отправкой и приемом факсов справляются, конечно, факсовые аппараты. Однако если вам неожиданно понадобилось, например, принять факс, а такого устройства нет, можно вполне использовать для этой цели возможности компьютера, тем
Секретный прием
Секретный прием Скажу вам по секрету: нужно записывать свои цели. Пока они находятся у вас в голове, они не так конкретны, как вам кажется. Они слишком туманны. Невозможно оценить их, рассказать о них кому-нибудь. С ними невозможно работать.Процесс изложения на бумаге
Прием и просмотр сообщений
Прием и просмотр сообщений Сразу же после запуска Почта Windows проверит, есть ли соединение с Интернетом. При его отсутствии будет предложено подключиться к Сети или работать в автономном режиме. После установки соединения программа проверит наличие новой корреспонденции