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

Кёртен Роб

Шрифт:
Многопоточный сервер

С позиции клиента многопоточные серверы неотличимы от однопоточных. Фактически, разработчик сервера может запросто «включить многопоточность», запустив еще один или несколько потоков.

В любом случае, сервер может по-прежнему использовать несколько процессоров в SMP-системе, даже если «клиент» у него только один.

Что это означает? Давайте вернемся к примеру о фрактальной графике. Когда субсервер получает от сервера запрос на «вычисления», ему ничто не мешает запустить несколько потоков и начать обработку данного запроса на нескольких процессорах сразу. На самом деле, чтобы приложение лучше масштабировалось в сетях, в которых есть как мультипроцессоры SMP, так и однопроцессорные машины, сервер и субсервер могут сначала обменяться информацией о том, сколько у субсервера имеется в распоряжении процессоров. Это даст серверу знать, сколько запросов субсервер может обслужить одновременно. Тогда сервер сможет перенаправлять многопроцессорным субсерверам больше запросов, чем однопроцессорным, равномерно распределяя нагрузку между вычислительными мощностями.

Применение обмена сообщениями

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

Архитектура и структура

Мы рассуждали о «клиентах» и «серверах». Я также использовал три ключевые выражения:

• «Клиент посылает (sends) сообщение серверу»;

• «Сервер принимает (receives) сообщение от клиента»;

• «Сервер отвечает (replies) клиенту».

Я преднамеренно использовал именно эти выражения, потому что они в точности соответствуют действительным именам функций, которые используются для передачи сообщений в QNX/Neutrino.

Ниже приводится (в алфавитном порядке) полный список функций QNX/Neutrino, относящихся к обмену сообщениями:

• ChannelCreate, ChannelDestroy;

• ConnectAttach, ConnectDetach;

• MsgDeliverEvent;

• MsgError;

• MsgRead, MsgReadv;

• MsgRecieve, MsgRecievePulse, MsgRecievev;

• MsgReply, MsgReplyv;

• MsgSend, MsgSendc, MsgSendsv, MsgSendsvnc, MsgSendvs, MsgSendvsnc, MsgSendv, MsgSendvnc;

• MsgWrite, MsgWritev.

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

Минимальный полезный набор функций включает в себя функции ChannelCreate, ConnectAttach, MsgReply, MsgSend и MsgRecieve.

Разобьем обсуждение на две части: отдельно обсудим функции, которые применяются на стороне клиента, и отдельно — те, что применяются на стороне сервера.

Клиент

Клиент, который желает послать запрос серверу, блокируется до тех пор, пока сервер не завершит обработку запроса. Затем, после завершения сервером обработки запроса, клиент разблокируется, чтобы принять «ответ».

Это подразумевает обеспечение двух условий: клиент должен «уметь» сначала установить соединение с сервером, а потом обмениваться с ним данными с помощью сообщений — как в одну сторону (запрос — «send»), так и в другую (ответ — «reply»).

Установление соединения

Итак, рассмотрим теперь функции по порядку. Первое, что мы должны сделать — это установить соединение. Это мы сделаем с помощью функции ConnectAttach, описанной следующим образом:

#include <sys/neutrino.h>

int ConnectAttach(int nd, pid_t pid, int chid,

 unsigned index, int flags);

Функции ConnectAttach передаются три идентификатора: идентификатор nd — дескриптор узла (Node Descriptor), идентификатор pid — идентификатор процесса (process ID) и идентификатор chid — идентификатор канала (channel ID).

Вместе эти три идентификатора, которые обычно записываются в виде «ND/PID/CHID», однозначно идентифицируют сервер, с которым клиент желает соединиться. Аргументы index и flags мы здесь просто проигнорируем (установим их в ноль).

Итак, предположим, что мы хотим подсоединиться к процессу, находящемуся на нашем узле и имеющего идентификатор 77, по каналу с идентификатором 1. Ниже приведен пример программы для выполнения этого:

int coid;

  • Читать дальше
  • 1
  • ...
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • ...

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

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

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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