13. Сеть Qnet
Распределенная среда ОС QNX Neutrino
Ранее в этом руководстве уже был рассмотрен механизм
обмена сообщениями в контексте отдельного узла (см. раздел "Межзадачное
взаимодействие в ОС QNX Neutrino" в главе 3). Однако истинная сила ОС QNX
Neutrino заключается в том, что ее механизм межзадачного
взаимодействия способен прозрачным образом работать внутри целой сети микроядер.
Замечание
В этой главе
описывается собственная сеть ОС QNX Neutrino, работающая по
протоколу Qnet. О сетевом взаимодействии по протоколу TCP/IP
см. в главе 14.
В основе
собственной сети ОС QNX Neutrino лежит протокол Qnet, который
реализуется в виде сети сильносвязанных доверяемых (trusted)
машин. Протокол Qnet позволяет этим машинам эффективно
обмениваться ресурсами с минимальными накладными расходами. В
сети Qnet можно пользоваться стандартными утилитами (cp, mv и т. д.) для
управления файлами в любом месте сети, как если бы эти файлы
находились на вашей собственной машине. Кроме того, протокол
Qnet не выполняет аутентификацию удаленных запросов, так как
файлы защищаются обычными правами доступа, применяемыми для
пользователей и пользовательских групп. Можно не только иметь
доступ к файлам, но и запускать или останавливать процессы (в том числе различные
администраторы) на любой машине в сети Qnet.
Возможности
распределенных вычислений в сети Qnet позволяют эффективно
выполнять следующие задачи:
-
использовать удаленную файловую
систему;
-
масштабировать приложения с
невероятной легкостью;
-
создавать приложения, в которых
используется множество процессов, прозрачным образом
взаимодействующих между собой посредством механизма обмена
сообщениями;
-
с легкостью переносить выполнение
приложения с одного процессора или симметричной
мультипроцессорной машины на несколько однопроцессорных
машин и распределять все процессы между этими
процессорами;
-
разбивать приложение на несколько
процессов, выполняющих разные функции (при этом процессы
координируют свою работу с помощью механизма обмена
сообщениями);
-
использовать собственную службу
удаленного вызова процедур сети Qnet.
Более того, поскольку протокол Qnet позволяет
перенести механизм обмена сообщениями на всю сеть, другие
формы межзадачного взаимодействия (например, сигналы, очереди
сообщений, именованные семафоры) также могут применяться в
этой сети.
Для понимания
механизма межзадачного взаимодействия в сети Qnet рассмотрим
два процесса, которые должны взаимодействовать: клиентский
процесс и серверный процесс (в данном случае процесс,
реализующий работу администратора последовательного порта). В
случае одного узла, клиент просто вызывает функции open(), read(), write() и т. д. Как будет
рассмотрено далее, высокоуровневые POSIX-вызовы (как,
например, open()) в действительности порождают
ряд низкоуровневых вызовов ядра, управляющих обменом
сообщениями (ConnectAttach(), MsgSend() и т. д.). Однако, для клиента все эти
функции оказываются "под поверхностью" и ему нет необходимости
заботиться о них — он просто вызывает open() и все.
fd =
open("/dev/ser1",Q_RDWR....);
/*Открыть
последовательное устройство*/
Теперь рассмотрим
случай простой сети с двумя машинами: на одной находится
клиентский процесс, на другой — серверный (рис. 13.1).
Рис. 13.1. Простая сеть, в которой клиент и сервер
находятся на разных машинах.
Программный код, необходимый для реализации
клиент-серверного взаимодействия, идентичен тому, который используется в случае с одним
узлом, за важным исключением: путевое имя. Путевое имя будет содержать префикс, задающий
узел, на котором расположена данная служба (/dev/ser1). Как будет рассмотрено далее,
этот префикс преобразуется в дескриптор узла, предназначенный
для последующего низкоуровневого вызова ядра ConnectAttach(). Каждый узел в сети имеет свой
дескриптор, который служит единственным признаком, по которому
можно определить, как работает ОС — в сети или автономно.
Более подробно
о дескрипторах узлов см. в главе о прозрачном распределенном
сетевом взаимодействии по протоколу Qnet в электронном
документе «QNX Neutrino Realtime Operation System. Programmer's Guide».
Разрешение имен и поиск
При запуске сети Qnet пространство путевых имен всех
узлов данной сети добавляется к вашему узлу. Напомним, что
путевое имя — это символьное имя, которое сообщает
программе путь, по которому следует искать файл в иерархии
каталогов, начинающейся с корневого каталога /.
Пространство
имен путей на удаленных узлах отображается с префиксом /net (каталог, по умолчанию создаваемый
администратором протокола Qnet lsm-qnet.so).
Например,
удаленный узел node1 будет отображаться следующим
образом:
/net/node1/dev/socket
/net/node1/dev/ser1
/net/node1/home
/net/node1/bin
....
Итак, при работе в сети Qnet можно обращаться к
файлам или администраторам на других удаленных узлах так же,
как при открытии файлов локально на своем собственном узле.
Это значит, что можно иметь доступ к файлам или
администраторам на других узлах сети Qnet, как если бы они
находились на вашем локальном узле.
Например,
приведенный ранее пример с функцией open(). Если необходимо открыть последовательное
устройство не на своей локальной машине, а на узле node1, нужно указать следующий путь:
fd =
open("/net/node1/dev/ser1",Q_RDWR...);
/*Открыть
последовательное устройство на узле node1*/
Каким же образом клиент в архитектуре "клиент-сервер"
может определить, какой дескриптор узла необходимо
использовать для сервера?
Клиент
использует пространство
имен путей файловой
системы
для "поиска" адреса сервера. В случае с одной машиной
результатом этого поиска будет дескриптор узла, идентификатор
процесса и идентификатор канала. В случае сети Qnet результат
будет тот же самый, за одним единственным исключением: значение дескриптора узла.
Если
дескриптор узла
|
то
сервер
|
0 (или
ND_LOCAL_NODE)
|
локальный
(т. е. "данный узел")
|
ненулевой
|
удаленный
|
Файловый
дескриптор (идентификатор соединения)
В обоих
случаях — локальная машина или сеть Qnet —
практически это означает, что когда клиент присоединяется к
серверу, он получает файловый дескриптор (или, в случае вызова
ядра (например, ConnectAttach()), идентификатор соединения).
Этот файловый дескриптор затем используется для всех
последующих операций обмена сообщениями. Следует обратить
внимание на то, что, с точки зрения клиента, файловый
дескриптор идентичен как в случае локальной машины, так и в
случае сети Qnet.
Сущность простой
операции open()
Вернемся к
примеру с функцией open(). Например, клиент на одном узле
(lab1) должен использовать
последовательный порт (/dev/ser1)
на другом узле (lab2). В этом случае клиент
выполняет функцию open() по следующему путевому имени:
/net/lab2/dev/ser1
На рис. 13.2
показано, какие операции применяются, когда клиент выполняет
функцию open() по путевому имени /net/lab2/dev/ser1.

Рис. 13.2. Обмен сообщениями между клиентом и сервером по сети
Qnet
Последовательность
операций
1. Клиент отправляет сообщение
локальному администратору процессов с вопросом о разрешении
путевого имени /net/lab2/dev/ser1.
Так как сетевой
администратор lsm-net
отвечает за все
пространство имен /net, администратор процессов
возвращает сообщение переадресации, в котором указывает, что
клиент должен связаться с локальным администратором сети для
получения нужной информации.
2. Клиент отправляет сообщение локальному
администратору сети с тем же вопросом о разрешении путевого
имени.
Локальный
администратор сети отвечает сообщением переадресации с указанием
дескриптора узла, идентификатора процесса и идентификатора
канала администратора процессов узла lab2,
таким образом пересылая запрос на разрешение имени пути на узел
lab2.
3. Клиент создает соединение с
администратором процессов узла lab2 и еще раз отправляет запрос на разрешение путевого
имени.
Администратор
процессов на узле lab2 возвращает еще одно сообщение
переадресации, на этот раз с указанием дескриптора узла,
идентификатора канала и идентификатора процесса драйвера
последовательного порта на своем собственном узле.
4. Клиент создает соединение с
последовательным портом на узле lab2 и, наконец, получает идентификатор соединения,
который может использовать для последующих операций обмена
сообщениями.
После этого, с
точки зрения клиента, обмен сообщениями по данному
идентификатору соединения происходит так же, как и в случае
локального обмена. Здесь нужно обратить внимание на то, что с
этого момента все последующие операции обмена сообщениями будут
происходить напрямую между клиентом и сервером.Ключевая особенность,
которую следует иметь в виду, здесь состоит в том, что клиент не
знает о происходящих операциях — все они обрабатываются
внутри POSIX-вызова open(). Клиент только выполняет функцию
open() и получает файловый дескриптор
(или сообщение об ошибке).
Замечание
При разрешении имени на каждом
последующем шаге из запроса клиента удаляются те компоненты
имени, которые были разрешены. Это происходит автомагически внутри
администратора ресурсов. Таким образом, на шаге 2 в
приведенном ранее описании запрос локальному сетевому
администратору относится только к lab2/dev/ser1. На шаге 3
запрос относится только к dev/ser1, так как это
все, что должен знать администратор ресурсов узла lab2. И, наконец, на
шаге 4 запрос относится только к ser1, так как это
все, что должен знать драйвер последовательного порта.
Служба глобальных имен
В приведенных примерах удаленные службы или файлы
расположены на известных узлах или по известным именам
путей. Например, последовательный порт узла lab1 находится по пути /net/lab1/dev/ser1.
Служба
глобальных имен (Global Name Service, GNS) позволяет
определить местонахождение служб по их именам независимо от
того, находятся ли они в локальной системе или на удаленном
узле. Например, если необходимо обнаружить модем в сети, можно
просто применить поиск по имени "модем". В результате вместо
использования статичного пути, GNS-сервер будет искать службу
с именем "модем". GNS-сервер можно конфигурировать таким
образом, чтобы он обслуживал все или только часть узлов в сети
Qnet. Кроме того, в сети может быть несколько GNS-серверов.
Именование сетевых
ресурсов
Как упоминалось выше, префикс путевых имен /net используется администратором ресурсов lsm-qnet наиболее часто. При разрешении имен в
сетевом пространстве путевых имен используются определенные
термины.
Распознаватели
У сетевого
администратора существуют три распознавателя (resolver).
-
en_ionet — рассылает
широковещательные запросы по сети (схожим образом с
протоколом TCP/IP ARP). Это распознаватель по умолчанию.
-
dns — этот распознаватель действует
следующим образом: берет имя узла, добавляет точку (.) и следом домен узла и отправляет
полученный результат функции gethostbyname() протокола TCP/IP.
-
file — предназначен для поиска
доступных узлов (в том числе соответствующего сетевого
адреса) в статическом файле.
Качество
обслуживания (QoS) и резервированные
соединения
Политика
качества обслуживания (QoS) — это тот вопрос, который
часто возникает в сетях высокой готовности, а также в системах
управления реального времени. В сетях Qnet служба QoS по сути
сводится к выбору
среды передачи.
В системе с несколькими сетевыми интерфейсами протокол Qnet
выберет тот, который больше соответствует заданной политике
качества обслуживания.
Замечание
Если в системе
предусмотрен только один сетевой интерфейс, то служба QoS не
применяется.
Политики качества
обслуживания
Протокол Qnet
поддерживает передачу по нескольким сетям. Для этого предусмотрены следующие политики
качества обслуживания, которые определяют, каким образом
протокол Qnet должен выбирать сетевой протокол для передачи:
-
loadbalance (по умолчанию) —
протокол Qnet позволяет использовать любые доступные
сетевые каналы связи и может распределять передачу данных
между ними;
-
preferred — позволяет
использовать только один канал связи и игнорировать все
остальные сети (кроме случаев, когда выбранный канал
оказывается недоступен);
-
exclusive — при этой политике
качества обслуживания используется только заданный канал
связи и игнорируются все остальные, даже если выбранный
канал оказывается недоступен.
Для получения
преимущества от использования QoS в Qnet, нужно физически
разделить сети. Например, рассмотрим сеть с двумя узлами и
хабом, где каждый узел имеет два подключения к хабу:
Рис. 13.3.
Qnet и одна сеть.
Если канал,
который используется в данный момент, становится недоступен,
Qnet обнаруживает это, но не может переключиться на другой
канал, потому что оба канала подключены к одному хабу.
Приложение само должно исправить ошибку; затем приложение
повторно устанавливает соединение, а Qnet переключается на
рабочий канал.
Теперь рассмотрим ту же самую сеть, но с двумя
хабами:
Если сети физически разделены и канал становится
недоступен, Qnet автоматически переключается на другой канал,
в зависимости от QoS, который выбран. Приложение не узнаёт,
что первый канал не доступен.
Можно указать опцию tx_retries модулю lsm-qnet.so, чтобы ограничить количество
попыток при повторной передаче в Qnet, а значит
контролировать, как долго Qnet будет ждать, чтобы решить, что
канал недоступен. Следует учесть, что если количество попыток
повторных передач слишком маленькое, то Qnet не будет
допускать потери пакетов и может постоянно считать, что канал
недоступен.
Далее политики QoS будут рассмотрены более подробно.
loadbalance
Протокол Qnet решает, какие каналы связи использовать
для передачи пакетов данных в зависимости от текущей нагрузки
и пропускной способности каналов, определенной сетевым
администратором io-pkt*. Пакет данных ставится в
очередь на передачу по тому каналу связи, который способен
быстрее других доставить пакет до удаленной точки назначения.
Такой порядок обеспечивает, во-первых, эффективную пропускную
способность между узлами по рабочим каналам связи (а эта
пропускная способность является суммой пропускных способностей
по всем доступным каналам), а во-вторых, в случае сбоя каналов
связи, — ограничение передачи данных оптимальным
способом.
Если какой-то
канал связи обрывается, протокол Qnet обеспечит переключение
передачи на другой доступный канал. В первый раз такое
переключение происходит в течение нескольких секунд, так как
сетевой драйвер на неисправном канале связи сначала применяет
таймаут, затем делает повторную попытку, а потом канал
обрывается. После этого протокол Qnet уже "знает", что данный
канал не работает, и поэтому не будет использовать его для передачи пользовательских
данных. (Эта особенность является значительным улучшением в
сравнении с QNX 4.)
Пока протокол
Qnet перераспределяет нагрузку между доступными каналами
связи, он будет периодически отправлять служебные пакеты на
неисправный канал для того, чтобы обнаружить его
восстановление. Если канал связи восстанавливается, протокол
Qnet вновь помещает его в список доступных каналов.
Замечание
Политика качества
обслуживания loadbalance применяется по умолчанию.
preferred
При использовании этой политики задается
предпочтительный канал связи. Протокол Qnet будет использовать
только этот канал, при условии, что он остается
работоспособным. В случае сбоя данного канала связи, протокол
Qnet переключится на другие доступные каналы и продолжит
передачу данных в соответствии с политикой loadbalance.
Как только
предпочтительный канал связи восстанавливается, протокол Qnet
возвращается к этому каналу и снова использует только его,
игнорируя все остальные до тех пор, пока предпочтительный
канал не откажет опять.
exclusive
Эта политика
качества обслуживания используется в тех случаях, когда
необходимо привязать передачу данных только к одному каналу
связи. Независимо от того, сколько доступно других каналов,
протокол Qnet будет использовать только заданный канал. Если
этот канал связи откажет, протокол Qnet НЕ будет использовать другие каналы.
В каких случаях
может понадобиться политика качества обслуживания exclusive? Например, имеется две сети.
Одна из них работает быстрее другой, есть приложение, которое
обменивается большими объемами данных. С помощью этой политики
можно ограничить передачу только посредством быстрой сети для
того, чтобы в случае ее сбоя избежать перегрузки более
медленной сети.
Задание политик
качества обслуживания
Политика
качества обслуживания задается как часть путевого имени.
Например, для того чтобы открыть доступ к /net/lab2/dev/ser1 с QoS-политикой exclusive, можно использовать следующее
имя пути:
/net/lab2~exclusive:en0/dev/ser1
QoS-параметр всегда начинается с символа тильды (~). Таким образом, в приведенном примере протоколу
Qnet дается команда использовать исключительно интерфейс en0 даже
в том случае, если он даст сбой.
Символьные
ссылки
Для различных
путевых имен с заданными QoS-политиками можно назначать
символьные ссылки:
ln -sP
/net/lab2~preferred:en1 /remote/sql_server
Данная команда присвоит "абстрактное" имя /remote/sql_server узлу lab2
с QoS-политикой предпочтительного использования (preferred) канала en1.
Замечание
Именное
пространство /net зарезервировано протоколом
Qnet, поэтому в нем нельзя создавать символьные ссылки.
Благодаря
возможности использовать символьные ссылки на путевые имена,
получается множество серверов в сети, предоставляющих одну и
ту же службу. Если один сервер отказывает, абстрактное путевое
имя может быть "переназначено" на путевое имя другого сервера.
Например, если узел lab2
отказывает, то программа-монитор может выявить это и выдать
следующую инструкцию:
rm
/remote/sql_server
ln -sP /net/lab1
/remote/sql_server
В результате служба будет переназначена с lab2 на lab1. Преимущество здесь состоит в
том, что при написании приложений можно использовать абстрактные
"имена служб" вместо точных имен узлов.
Примеры
Несколько
примеров использования сетевого администратора.
Замечание
Сетевой администратор
lsm-qnet ОС QNX Neutrino
по сути представляет собой разделяемый объект, который
инсталлируется в исполняемый модуль io-pkt*.
Локальные сети
Если ОС QNX
Neutrino используется в небольшой локальной сети, то можно
обойтись одним распознавателем en_ionet, который используется по умолчанию. При разрешении
неизвестного имени узла, распознаватель рассылает запрос имени
по всей локальной сети, и узел, который имеет это имя,
отвечает на данный запрос идентификационным сообщением. После
разрешения имени оно помещается в кеш для последующего
использования.
Если ОС QNX
Neutrino используется в небольшой локальной сети, то можно
обойтись одним распознавателем en_ionet, который используется по умолчанию. При разрешении
неизвестного имени узла, распознаватель рассылает запрос имени
по всей локальной сети, и узел, который имеет это имя,
отвечает на данный запрос идентификационным сообщением. После
разрешения имени оно помещается в кеш для последующего
использования.
Поскольку
распознаватель ndp включается по умолчанию при
запуске администратора сети lsm-qnet.so, можно просто задать, например, такие инструкции:
ls /net/lab2/
Если в локальной сети пользователя есть машина с именем
lab2, то после этой инструкции можно
увидеть содержание корневого каталога этой машины.
Удаленные сети
Замечание
Для обеспечения
безопасности сети необходимо установить межсетевой экран
(firewall) перед выходом в Интернет. Более подробную
информацию можно найти в документации на OpenBSD по адресу
ftp://ftp3.usa.openbsd.org/pub/OpenBSD/doc/pf-faq.pdf.
Для разрешения
удаленных имен протокол Qnet использует службу доменных имен
(Domain Name System, DNS). Для включения DNS-службы при работе
администратора сети lsm-qnet.so следует задать имя этого распознавателя в команде mount:
mount -Tio-pkt
-o"mount=:,resolve=dns,mount=.com:.net:.edu"
/lib/dll/lsm-qnet.so
В этом примере протокол Qnet будет использовать обе службы: как распознаватель en_ionet (заданный первой командой mount=), так и DNS-службу, предназначенную для
разрешения удаленных имен.
Для разрешения
удаленных имен протокол Qnet использует службу доменных имен
(Domain Name System, DNS). Для включения DNS-службы при работе
администратора сети npm-qnet.so следует задать имя этого распознавателя в команде mount:
mount Tio net o"mount=:,resolve=dns,mount=.com:.net:.edu" /lib/dll/npm-qnet.so
В этом примере протокол Qnet будет использовать обе службы: как распознаватель ndp (заданный первой командой mount=), так и DNS-службу, предназначенную для
разрешения удаленных имен.
Необходимо
отметить, что в этом примере было задано несколько типов
доменных имен (mount=.com:.net:.edu) в качестве точек монтирования
просто для того, чтобы сделать разрешение имен более надежным.
Таким образом,
при вводе, например, инструкции:
ls
/net/qnet.qnx.com/repository
будет выведено содержание каталога repository, расположенного на сайте qnet.qnx.com.
Специализированные
драйверы устройств
В большинстве
случаев можно использовать стандартные драйверы QNX для
реализации сети Qnet в локальной сети или для инкапсуляции
Qnet-сообщений по протоколу IP (TCP/IP) с тем, чтобы
обеспечить маршрутизацию Qnet-пакетов на удаленные сети. Если
необходимо создать между двумя процессорами сеть с высокой
степенью связности с использованием высокоскоростной среды
передачи данных (например, PCI или RapidIO).
Можно легко
использовать подобную высокопроизводительную среду передачи,
так как сетевой протокол Qnet может напрямую взаимодействовать
с драйверами оборудования. В данном случае администратор io-pkt* отсутствует. Требуется только
добавить в самом низу уровня Qnet небольшой модуль, который
должен выполнять передачу и прием пакетов. Сделать это
довольно просто благодаря стандартному внутреннему
программному интерфейсу между остальной частью сети Qnet и
добавленным к ее нижнему уровню модулю интерфейса драйвера.
Qnet
поддерживает разные интерфейсы передачи и приема пакетов
данных, поэтому добавление других интерфейсов может быть
сделано довольно легко. Протокол Qnet имеет оригинальный
транспортный механизм (называемый "L4"), который можно
конфигурировать с учетом разных максимальных размеров
передаваемого блока данных (Maximum Transmission Unit, MTU),
применения (или не применения) пакетов уведомления (ACK) или
CRC-кодов и так далее, что позволяет наиболее эффективным
образом использовать возможности (например, гарантированную
надежность) имеющейся среды передачи.
Также можно
использовать комплект разработчика для платформы Qnet, который
позволяет писать специализированные драйверы и/или
модифицировать компоненты протокола Qnet в соответствии с
требованиями конкретного приложения.
11
Игра слов. В
оригинале: automagically. — Прим. перев.