Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Ответы СПЗ.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
113.15 Кб
Скачать
  1. Передача сообщений со стороны клиента

Int MsgSend – клиент посылает сообщение.( int coid – идентификатор соединенный с целевым сервером.

Const void *smsg – указатель на передаваемое сообщение

Int styles – размер сообщения

Void rmsg – указатель на буфер для ответного сообщения

Int rbytes); - его размер.

Пример: # include <sys/neutrino.h>

Char smsg= <<буфер вывода>>;

Char rms[200];

Int coid; //установить соединение

Coid=Connect Attach(0,77,1,0,0);

If (coid==-1){ fprint stder,<<ошибка\n>>); -- обработка ошибочной ситуации.

Perror(null);

Exit(EXIT_FAILURE);

}

Полсать сообщение if (MsgSend(coid strlen (smsg)+1,rmsg);

  1. Участие сервера в обмене сообщениями

1)Сервер создает к-л

intCannelCreate(unsigned flags)- создать к-л

2)обработка сообщения

Сервер обрабатывает сообщение в 2 этапа

-Recive- этап приема сообщения

-Reply – этап ответа

Соответств функции :

-msgrecive(..)

-msgreply(..)

  1. Общая структура сервера

Для создания сервера используются сокеты.

Для создания сокета используется системный вызов socket.

s = socket(domain, type, protocol);

Этот вызов основывается на информации о коммуникационном домене и типе сокета.

Функция socket создает конечную точку для коммуникаций и возвращает файловый дескриптор, ссылающийся на сокет, или -1 в случае ошибки. Данный дескриптор используется в дальнейшем для установления связи.

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

Для связывания сокета с адресом и номером порта используют системный вызов bind:

bind(s, name, namelen);

Когда сервер желает предложить один из своих сервисов, он связывает сокет с общеизвестным адресом, ассоциирующимся с данным сервисом, и пассивно слушает этот сокет. Для этих целей используется системный вызов listen:

error=listen(s, qlength);

где s это дескриптор сокета, а qlength это максимальное количество запросов на установление связи, которые могут стоять в очереди, ожидая обработки сервером

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

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

обычная функция записи, с помощью которой мы пишем в файлы и т.п.

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

сlose(S)

где S – дескриптор закрываемого сокета.

  1. Особенности обмена сообщениями. Каналы и потоки

Сообщения являются основным способом взаимодействия между процессами в QNX

в QNX сообщения являются синхронными, то есть процесс, пославший сообщение, требует обязательного ответа на него.

Обмен сообщениями обеспечиваются вызовами микроядра:

Send() - посылка сообщения:

Recive() - прием сообщения;

Reply() - посылка ответа.

Для взаимодействия процессов необходима "встреча" готовности одного процесса (Процесса A) передать сообщение и готовности другого процесса (Процесса B) принять сообщение. 

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

Несколько процессов могут послать сообщения одновременно одному адресату. В этом случае сообщения могут обрабатываться (получаться адресатом) либо в порядке их поступления, либо в соответствии с приоритетами отправителей.

Еще один вызов микроядра -Crecive() - позволяет процессу проверить наличие сообщений для него и, таким образом, избежать RECIVE-блокировки.

В QNX Neutrino программные потоки взаимодействуют не напрямую

друг с другом, а через специальные объекты, называемые каналом

(Channel) и соединением (Connection) Поток сервера (Server), ко-

торый желает получить сообщение, сначала создает канал; другой поток –

клиент (Client), который желает послать сообщение к потоку сервера, дол-

жен создать соединение с каналом. Каналы и соединения после своего

создания получают идентифицирующие номера – малые целые числа, ко-

торые берутся из пространства файловых дескрипторов. Последнее озна-

чает, что сообщение может быть послано через файловый дескриптор не-

зависимо от того, как он был получен.

С соединением связаны 2 идентификатора – coid на стороне клиента и

scoid на стороне сервера. Для передачи сообщений используется только идентификатор клиента – coid, идентификатор scoid – это внутренний иден-

тификатор, используемый ядром для маршрутизации ответного сообщения

от сервера к клиенту.

По умолчанию приоритет потока, получающего сообщения через ка-

нал, устанавливается равным приоритету потока, пославшего сообщение.

ChannelCreate() Создать канал для приема сообщений

ChannelDestroy() Уничтожить канал

ConnectAttach() Создать соединение для передачи сообщения

ConnectDetach() Уничтожить соединение

Свойства канала определяются словом флагов, которое является

единственным аргументом функции ChannelCreate

QNX является многопроцессорной системой. В самой QNX отсутствуют потоки (threads), но они реализованы несколько необычным

Потоки в QNX ведут себя скорее как дочерние процессы, порожденные родительским процессом, чем как фактические потоки. Когда поток QNX создается некоторым процессом, то для него будет использоваться тот же сегмент кода и данных, как и для родительского процесса, что имеет место и в случае обычных потоков. Тем не менее, к некоторым специальным объектам, создаваемым родительским процессом, таким как таймеры и дескрипторы файлов, доступ со стороны потока невозможен.