Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform
Шрифт:
2. Клиент теперь посылает сообщение потоку администратора
3. Клиент соединяется с администратором процессов на узле
4. Теперь клиент посылает запрос непосредственно нужному серверу. Маршрут следования сообщения здесь идентичен описанному в предыдущем пункте, за исключением того, что на этот раз связь с сервером осуществляется напрямую, а не через администратор процессов.
После того как пройдены этапы 1 и 3, все дальнейшие коммуникации осуществляются аналогично этапу 4. В вышеприведенном примере все сообщения типа open, read и close идут по маршруту, описанном в этапе 4. Заметьте, что вся последовательность рассмотренных событий была запущена вызовом open, но само сообщение open все равно дошло до сервера-адресата так, как это описано этапом 4.
Мы еще вернемся к сообщениям, используемым функциями open, read и close (а также другими функциями) в главе «Администраторы ресурсов».
Особенности обмена сообщениями в сети
Итак, как только соединение установлено, все дальнейшие операции обмена сообщениями осуществляются в соответствии с этапом 4, как указано на рисунке. Это может привести вас к ошибочному представлению, что передача сообщений по сети идентична локальной. К сожалению, это не так. Вот список отличий:
• более длительные задержки;
• функция ConnectAttach возвращает признак успешного соединения независимо от того, является ли узел доступным или нет — реальный признак ошибки проявляется только при первой попытке передать
• функция MsgDeliverEvent не обеспечивает достаточной надежности;
• функции MsgReply, MsgRead, MsgWrite являются блокирующими вызовами (в локальном варианте они не являлись таковыми);
• функция MsgReceive не будет принимать все данные, посланные клиентом; сервер будет должен вызывать функцию MsgRead для получения окончательных остальных данных.
Поскольку передача сообщений теперь выполняется в некоторой среде, а не прямым копированием «память-память» под управлением ядра, можно смело ожидать, что затраты времени на передачу сообщения будут существенно выше (100-Мбитный Ethernet в сравнении с 128-битным динамическим ОЗУ с тактированием 100 МГц будет ориентировочно на один или два порядка медленнее). В дополнение к этому также будут сказываться накладные расходы протокола и повторные попытки передачи в сбойных сетях.
Когда вы вызываете функцию ConnectAttach, вы задаете ей идентификаторы ND, PID и CHID. Все, что при этом происходит в QNX/Neutrino, заключается в возврате ядром идентификатора соединения драйверному потоку
Когда сервер вызывает функцию MsgDeliverEvent локально, ответственность за доставку события целевому потоку ложится на ядро. В сетевом варианте сервер также может вызывать функцию MsgDeliverEvent, но на этот раз ядро доставит «заготовку» этого события администратору
Чтобы уберечь функции MsgReply, MsgRead и MsgWrite от вышеупомянутой проблемы MsgDeliverEvent, эти функции при использовании их в сети преобразуются в блокирующие вызовы. В локальном случае они бы просто передали данные и разблокировались; в сети же мы должны либо удостовериться, что данные были доставлены клиенту (в случае MsgReply), либо собственно передать данные по сети клиенту или от него (в случае двух других функций).