|
          В настоящее время существует четыре способа связи между процессами, работающими на разных ЭВМ.
Рассмотрим каждый из них в отдельности.
          Стандартные операции вызова процедур предусматривают передачу в процедуру исходных параметров для его работы и возврат в вызывающую программу результатов работы процедуры. В локальной ЭВМ передача в процедуру исходных параметров для её работы и возврат в вызывающую программу, результатов работы процедуры производится через СТЕК (специализированная область оперативной памяти ЭВМ доступ, к которой производится не по адресу, а по очерёдности поступления в СТЕК информации в соответствии с принципом FILO (первый пришел, последний вышел)).
Связь на основе потоков данных Чтение или запись части сообщений ! ! ! Вы можете пройти тест нажав эту ссылку
          Процедура- это фрагмент программы, оформленный стандартным образом и доступный для использования другими программами с помощью стандартных операций вызова процедур.
          Удаленный вызов процедур подразумевает , выполнение процедуры на другой ЭВМ, что делает невозможными передачу данных через СТЕК.
          Проблемы выполнения удаленных процедур:
          Удаленный вызов процедур осуществляется с помощью технологий RPC. Идея RPC состоит в том, чтобы с точки зрения программиста или пользователя, удаленный вызов процедур выглядел также как локальный, т.е. ни программист, ни вызывающая программа не должны уведомляться о том, что вызываемая процедура находится на ЭВМ и наоборот.
Реализация удаленного вызова процедур в системе QNX
Обращение к удаленным объектам
          Объект - это стандартно оформленный программный модуль, содержащий данные и операции над этими данными. Данные, содержащиеся в объекте в программирование называются состоянием, а операции над этими данными методы. Доступ к методам можно получить через интерфейс объекта, предоставляемый системами программирования. Объект может реализовывать множество интерфейсов. В свою очередь для описания интерфейса, также может существовать несколько объектов. Распределенный объект – это объект интерфейс которого находится на другой ЭВМ, чем сам объект. Характерная особенность распределенных объектов заключается в том, что их состояние, т.е. данные не распределяются. Они лаколизованны на одной ЭВМ. С других ЭВМ доступны только интерфейсы реализованные в объекте.
          При обращении клиента к распределенному объекту управление передаётся программе реализации интерфейса объекта аналогичной клиентской заглушке и называется заместителем . Заместитель осуществляет транзит параметров от вызывающей программы к ОС клиентской ЭВМ и обратно как это делает клиентская заглушка. На стороне сервера транзит параметров от ОС сервера к методам объекта и обратно осуществляет аналог серверной заглушке, называемой программа скелетон . Объекты распределенных систем существуют в формах принятых в том или ином языке программирования.
          С использованием технологий RMI.
При обращении к RMI клиент использует ссылку, содержащую сетевой адрес сервера и полный путь к объекту на сервере, включая локальный идентификатор объекта в адресном пространстве сервера. Также ссылка вкодирется в СТЕК протоколов используемых для взаимодействия клиента и сервера.
          С использованием системы DCE RPC.
При обращении DCE RPC клиент определяет серверу:
          Сервер поддерживает таблицу объектов с помощью которой по полученной информации идентификаторов объекта и интерфейса, идентифицирует объект, к которому подключился объект. Затем сервер выбирает запрошенный метод и передаёт ему параметры.
          Применяется при необходимости передачи данных без их обработки на сервере.
Связь по средствам сообщений может применяться в коммуникациях как ориентированных, так и неориентированных на установление соединения.
          При сохранной или резидентной связи по средствам сообщений отправитель не контролирует состояние процесса получателя в момент отправки сообщения, в тоже время сообщение не будет потерянно и будет доставлено процессу получателю сразу, как только он будет готов его принять. При нерезидентной связи по средствам сообщений, сообщение существует в системе только в момент его передачи процессом-отправителем. Если по какой-либо причине процесс-получатель не имеет возможности принять сообщение, то оно теряется.
          Связь по средствам сообщений может быть синхронной , когда процесс-отправитель блокируется до получения ответа от процесса-получателя о приёме сообщения. Связь по средствам сообщений может быть асинхронной , когда процесс-отправитель продолжает свою работу недожидаясь квитанции от процесса-получателя.
          В системах нерезидентной связи по средствам сообщений применяется стандарт пересылки сообщений – MPI(основан на – « сокетах беркли »). Это абстрактная конечная точка коммуникаций, в которую прикладная программа записывает данные необходимые для передачи по сети и из которой она может считывать поступающую по сети информацию.
          ОС предоставляет прикладной программе набор команд или приметивов, с помощью которых программа может создать «сокет», назначить ему локальный адрес, переслать или принять данные и разорвать соединение.
Реализация связи посредством сообщений в системе QNX
          Применяется при передаче информации не имеющих четких ограничений по объему и времени передачи.
          Различают три режима передачи потоков данных:
          Потоки данных могут быть дискретными , т.е. потоки байт или потоки слов и непрерывными – потоки бит. Также потоки данных могут быть простыми , т.е. содержащие только одну последовательность данных и комплексными , т.е. содержащими несколькими связанными потоками данных называемых вложенными потоками данных.
          Временные зависимости потоков данных выражаются в виде требований к качеству обслуживания описывающих, что должна сделать распределенная система, для того чтобы гарантировать сохранение в потоке данных заданных временных соотношений.
          Для передачи потоков данных распределённая система должна захватить ресурсы, удовлетворяющие требования к качеству обслуживания.
Реализация cвязи на основе потоков данных в системе QNX
Связь между процессами в QNX
          Микроядро QNX поддерживает три важнейшие формы связи между процессами: сообщения, прокси и сигналы.
          Теперь рассмотрим эти формы в отдельности:
          Сообщения в QNX - это пакеты байт, которые синхронно передаются от одного процесса к другому. QNX при этом не анализирует содержание сообщения. Передаваемые данные понятны только отправителю и получателю и никому более.
          Примитивы передачи сообщений
          Для непосредственной связи друг с другом взаимодействующие процессы используют следующие функции языка программирования Си:
          Эти функции могут быть использованы как локально, т.е. для связи между процессами на одном компьютере, так и в пределах сети, т.е. для связи между процессами на разных узлах.
         Следует заметить, однако, что далеко не всегда возникает необходимость использовать функции Send(), Receive() и Reply() в явном виде. Библиотека функций языка Си в QNX построена на основе использования сообщений - в результате, когда процесс использует стандартные механизмы передачи данных (такие, как, например, программный канал - pipe ), он косвенным образом использует передачу сообщений.
          Процесс A посылает сообщение процессу B, который получает его, обрабатывает и посылает ответ
          На рисунке изображена последовательность событий, имеющих место, когда два процесса, процесс A и процесс B, используют функции Send(), Receive() и Reply() для связи друг с другом:
          Заметьте, что если бы процесс B вызвал Receive() до того, как ему было послано сообщение, то он бы попал в состояние RECEIVE-блокирован до получения сообщения. В этом случае процесс-отправитель сообщения немедленно после посылки сообщения попал бы в состояние REPLY-блокирован.
          Синхронизация процессов
          Передача сообщений не только позволяет процессам обмениваться данными, но и предоставляет механизм синхронизации выполнения нескольких взаимодействующих процессов.
          Давайте снова рассмотрим приведенный выше рисунок. После того как процесс A вызвал функцию Send(), он не может продолжать выполнение до тех пор, пока не получит ответ на посланное сообщение. Это гарантирует, что выполняемая процессом B по запросу процесса A обработка данных будет завершена прежде, чем процесс A продолжит выполнение. Более того, после вызова процессом B запроса на получение данных Receive(), он не может продолжать выполнение до тех пор, пока не получит следующее сообщение. К содержанию
          Блокированные состояния
          Когда процессу не разрешается продолжать выполнение, т.к. он должен ожидать окончания определенной стадии протокола передачи сообщения, - процесс называется блокированным.
          Возможные блокированные состояния процессов приведены в следующей таблице:
          Изменение состояния процессов в типичном случае передачи сообщения.
          Использование Send(), Receive() и Reply()
          Давайте теперь более подробно рассмотрим вызовы функций Send(), Receive() и Reply(). Воспользуемся рассмотренным выше примером передачи сообщения от процесса A к процессу B.
          Функция Send()
          Предположим, что процесс А выдает запрос на передачу сообщения процессу В.Это выполняется посредством вызова функции Send( ).
          Send( pid, smsg, rmsg, smsg_len, rmsg_len )
          При вызове функции Send() используются следующие аргументы:
          Обратите внимание, что будет передано не более smsg_len байт и не более чем rmsg_len байт будет получено в качестве ответа - это гарантирует, что не произойдет случайного переполнения буферов.
          Функция Receive()
          Вызвав запрос Receive(), процесс B может получить сообщение, направленное ему процессом A.
          Receive( Pid,0, msg, msg_len )
          Вызов функции Receive() содержит следующие аргументы:
          Если значения аргументов smsg_len в вызове функции Send() и msg_len в вызове функции Receive() отличаются, друг от друга, то наименьшее из них определяет размер данных, которые будут переданы.
          Функция Reply() После успешного получения сообщения от процесса A, процесс B должен ответить процессу A, вызвав функцию Reply().
          Reply( pid, reply, reply_len )
Вызов функции Reply() содержит следующие аргументы:
          Если значения аргументов reply_len при вызове функции Reply() и rmsg_len при вызове функции Send() отличаются друг от друга, то наименьшее из них определяет размер передаваемых данных.
          Reply-управляемый обмен сообщениями
          Пример обмена сообщениями, который мы только что рассмотрели, иллюстрирует наиболее распространенный случай использования сообщений - случай, когда для процесса, выполняющего функции сервера, нормальным является состояние RECEIVE-блокирован в ожидании каких-либо запросов клиента. Это называется send-управляемый обмен сообщениями: процесс-клиент инициирует действие, посылая сообщения, ответ сервера на сообщение завершает действие.
          Существует и другая модель обмена сообщениями, не столь распространенная, как рассмотренная выше, хотя в некоторых ситуациях она даже более предпочтительна: reply-управляемый обмен сообщениями, при котором действие инициируется вызовом функции Reply(). В этом случае процесс-"работник" посылает серверу сообщение, говорящее о том, что он готов к работе. Сервер не отвечает сразу, а "запоминает", что работник готов выполнить его задание. В последствии сервер может инициировать действие, ответив ожидающему задание работнику. Процесс-работник выполнит задание и завершит действие, послав серверу сообщение, содержащее результаты своей работы.
          Дополнительные сведения
          При разработке программ, использующих передачу сообщений, необходимо иметь в виду следующее:
          Несмотря на такую кажущуюся простоту, вызов функции Send() делает гораздо больше, чем простой вызов библиотечной подпрограммы. Функция Send() может прозрачно для вызывающей программы передать запрос на другой узел сети, где и будет в действительности выполняться обслуживающий запрос код. При этом также может быть задействована параллельная обработка данных без издержек на создание нового процесса. Процесс-сервер может сразу, как только станет возможным, вызвать функцию Reply(), позволяя тем самым запрашивавшему процессу возобновить выполнение и, в то же время, продолжить выполнение самому.         
          Сервер получил сообщение от клиента A и клиента B (но еще не ответил им). Сообщения от клиентов C, D, E еще не получены.
К содержанию
          Дополнительные возможности
QNX также предоставляет следующие дополнительные возможности по передаче сообщений:
         Условный прием сообщений
         Чтение или запись части сообщений
         Составные сообщения (сообщения, состоящие из нескольких частей)
          Обычно, когда процесс хочет принять сообщение, он вызывает функцию Receive() для ожидания прихода сообщения. Это обычный способ получения сообщений, который пригоден в большинстве случаев.
          Однако возможна ситуация, когда процессу необходимо определить, имеются ли ожидающие приема сообщения, не попадая при этом в состояние RECEIVE-блокирован в случае их отсутствия. Например, процессу требуется опрашивать работающее с высокой скоростью устройство, которое не способно генерировать прерывание, и в то же время он должен отвечать на сообщения от других процессов. В этом случае процесс может использовать функцию Creceive(), которая либо прочитает ожидающее приема сообщение, либо немедленно вернет управление процессу в случае отсутствия ожидающих приема сообщений.
          Например, менеджер ввода/вывода может принимать данные в виде сообщений, которые состоят из заголовка фиксированной длины и следующих за ним данных переменной длины. В заголовке указывается размер данных (от 0 до 64 Кбайт). В этом случае менеджер ввода/вывода может сначала принять только заголовок сообщения, а затем использовать функцию Readmsg() для чтения данных переменной длины непосредственно в соответствующий буфер вывода. Если размер данных превышает размер буфера, то менеджер может неоднократно вызывать функцию Readmsg() по мере освобождения буфера вывода. Аналогичным образом, функция Writemsg() может быть использована для поэтапного копирования данных в выделенный для ответного сообщения буфер непосредственно в теле процесса, пославшего сообщение, уменьшая, таким образом, потребность менеджера ввода/вывода в выделении внутренних буферов.
          До сих пор мы рассматривали сообщения как непрерывную последовательность байт. Однако сообщения часто состоят из двух или более отдельных частей. Например, сообщение может иметь заголовок фиксированной длины, за которым следуют данные переменной длины. Для того чтобы избежать копирования частей такого сообщения во временные промежуточные буферы при передаче или приеме, может быть использовано составное сообщение, состоящее из двух или более отдельных буферов сообщений. Именно благодаря этой возможности менеджеры ввода/вывода QNX, такие как Dev и Fsys, достигают своей высокой производительности.
          Следующие функции позволяют обрабатывать составные сообщения:
          Составные сообщения могут быть описаны с помощью специальной mx структуры. Микроядро объединяет части такого сообщения в единый непрерывный поток данных.
          Зарезервированные коды сообщений
          QNX начинает все сообщения с 16-ти битного слова, называемого кодом сообщения. Заметим, однако, что это не является обязательным для вас требованием при написании собственных программ. QNX использует коды сообщений в следующих диапазонах:
          Прокси - это форма неблокирующего сообщения, особенно подходящего для извещения о наступлении события, когда посылающий процесс не нуждается в диалоге с получателем. Единственная функция прокси состоит в посылке фиксированного сообщения определенному процессу, который является владельцем прокси. Подобно сообщениям, прокси могут быть использованы в пределах всей сети.
      Используя прокси, процесс или обработчик прерывания может послать сообщение другому процессу, не блокируясь и не ожидая ответа.
          Вот некоторые примеры использования прокси:
          Для создания прокси используется функция языка Си qnx_proxy_attach(). Любой другой процесс или обработчик прерывания, которому известен идентификатор прокси, может воспользоваться функцией языка Си Trigger() для того, чтобы заставить прокси передать заранее заданное сообщение. Запрос Trigger() обрабатывается Микроядром.
          Прокси может быть "запущено" неоднократно - каждый раз при этом оно посылает сообщение. Прокси может накапливать очередь длиной до 65535 сообщений.
         
Процесс-клиент запускает прокси 3 раза, в результате чего сервер получает 3 "консервированных" сообщения от прокси.
          Сигналы являются традиционным способом асинхронной связи, которая используется в течение многих лет в различных операционных системах.
          QNX поддерживает большой набор сигналов, соответствующих стандарту POSIX, кроме того, сигналы, исторически присущие некоторым UNIX-системам, и ряд сигналов, уникальных для QNX.
          Как породить сигнал
          Считается, что сигнал доставлен процессу тогда, когда выполняется определенное в процессе для данного сигнала действие. Процесс может посылать сигнал самому себе.
          Получение сигналов
          Процесс может принять сигнал одним из трех способов, в зависимости от того, как в процессе определена обработка сигналов:
          В промежутке времени между моментом, когда сигнал порожден, и моментом, когда он доставлен, сигнал называется ожидающим. Для процесса ожидающими одновременно могут быть несколько различных сигналов. Сигналы доставляются процессу, когда планировщик ядра делает этот процесс готовым к выполнению. Процесс не должен строить никаких предположений относительно порядка, в котором будут доставлены ожидающие сигналы.
          Управление обработкой сигналов
          Чтобы задать желаемый способ обработки для каждого из сигналов, вы можете использовать функции языка Си signal() стандарта ANSI или sigaction() стандарта POSIX.
          Функция sigaction() предоставляет большие возможности по управлению обработкой сигналов.
          Вы можете изменить способ обработки сигнала в любой момент времени. Если вы укажете, что сигнал данного типа должен игнорироваться, то все ждущие сигналы такого типа будут немедленно отброшены.
          Обработчики сигналов
          Некоторые специальные замечания касаются процессов, которые ловят сигналы посредством обработчиков сигналов.
          Вызов обработчика сигнала аналогичен программному прерыванию. Он выполняется асинхронно по отношению к остальной части процесса. Таким образом, существует вероятность того, что обработчик сигнала будет вызван во время выполнения любой из имеющихся в программе функций (включая библиотечные функции).
          Если в вашей программе не предусмотрен возврат из обработчика сигнала, то могут быть использованы функции siglongjmp() либо longjmp() языка Си, однако, функция siglongjmp() предпочтительнее. При использовании функции longjmp() сигнал остается блокированным.
          Блокирование сигналов
          Иногда может возникнуть необходимость временно запретить получение сигнала, не изменяя метод его обработки. QNX предоставляет набор функций, которые позволяют блокировать получение сигналов. Блокированный сигнал остается ожидающим; после разблокирования он будет доставлен вашей программе.
          Пока ваша программа выполняет обработчик сигнала для определенного типа сигнала, QNX автоматически блокирует этот сигнал. Это означает, что нет необходимости заботиться о вложенных вызовах обработчика сигнала. Каждый вызов обработчика сигнала - это неделимая операция по отношению к доставке следующих сигналов этого типа. Если ваш процесс выполняет нормальный возврат из обработчика, сигнал автоматически разблокируется.
          Сигналы и сообщения
          Существует важное взаимодействие между сигналами и сообщениями. Если ваш процесс SEND-блокирован или RECEIVE-блокирован в момент получения сигнала, и вы предусмотрели обработчик сигнала, происходят следующие действия:
          Если процесс был SEND-блокирован в момент получения сигнала, то проблемы не возникает, потому что получатель еще не получил сообщение. Но если процесс был RECEIVE-блокирован, то вы не узнаете, было ли обработано посланное им сообщение и, следовательно, не будете знать, следует ли повторять Send( ).
          Процесс, играющий роль сервера (т.е. получающий сообщения), может запросить, чтобы он получал извещение всякий раз, когда его процесс-клиент получает сигнал, находясь в состоянии REPLY-блокирован. В этом случае клиент становится SIGNAL-блокированным с ожидающим сигналом. Сервер получает специальные сообщения, описывающие тип сигнала. Сервер может затем выбрать один из следующих вариантов:          
ИЛИ
          Когда сервер отвечает процессу, который был SIGNAL-блокирован, то сигнал выдается непосредственно после возврата из функции Send( ), вызванной клиентом (процессом-отправителем).
 Введение  Связь между процессами  Архитектура QNX  Именование в QNX  QNX в реальном времени  Тест