Чтение онлайн

на главную - закладки

Жанры

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

Кёртен Роб

Шрифт:

С другой стороны, функция MsgReply может передавать данные (как видно из ее третьего и четвертого параметров) и заставляет функцию MsgSend клиента возвратить значение, переданное MsgReply в качестве второго аргумента. Переменная errno клиента остается нетронутой.

В общем случае, если вам нужно только сообщить о результатах действия («прошло/не прошло»), лучше применять функцию MsgError. Если бы вы возвращали данные, здесь была бы необходима функция MsgReply. Обычно, когда вы возвращаете данные, вторым параметром функции MsgReply

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

Определение идентификаторов узла, процесса и канала (ND/PID/CHID) нужного сервера

Ранее мы отметили, что для соединения с сервером функции ConnectAttach необходимо указать дескриптор узла (Node Descriptor — ND), идентификатор процесса (process ID — PID), а также идентификатор канала (Channel ID — CHID). До настоящего момента мы не обсуждали, как именно клиент находит эту информацию.

Если один процесс создает другой процесс, тогда это просто — вызов создания процесса возвращает идентификатор вновь созданного процесса. Создающий процесс может либо передать собственные PID и CHID вновь созданному процессу в командной строке, либо вновь созданный процесс может вызвать функцию getppid для получения идентификатора родительского процесса, и использовать некоторый «известный» идентификатор канала.

А что если у нас два совершенно чужих процесса? Это возможно, например, в том случае, если сервер создан некоей третьей стороной, а вашему приложению нужно уметь общаться с этим сервером. Реально мы должны найти ответ на вопрос: «Как сервер объявляет о своем местонахождении?»

Существует множество способов сделать это; мы рассмотрим только три из них, в порядке возрастания «элегантности»:

1. Открыть файла с известным именем и сохранить в нем ND/PID/CHID. Такой метод является традиционным для серверов UNIX, когда сервер открывает файл (например,

/etc/httpd.pid
), записывает туда свой идентификатор процесса в виде строки ASCII и предполагают, что клиенты откроют этот файл прочитают из него идентификатор.

2. Использовать для объявления идентификаторов ND/PID/CHID глобальные переменные. Такой способ обычно применяется в многопоточных серверах, которые могут посылать сообщение сами себе. Этот вариант по самой своей природе является очень редким.

3. Занять часть пространства имен путей и стать администратором ресурсов. Мы поговорим об этом в главе «Администраторы ресурсов».

Первый подход относительно прост, но он чреват «загрязнением файловой системы», когда в каталоге

/etc
лежит куча файлов
*.pid
. Поскольку файлы устойчивы (имеется в виду, что они выживают после смерти создающего их процесса и перезагрузки машины), очевидного способа стереть эти файлы не существует — разве что использовать этакую программную «старуху с косой», постоянно проверяющую, не пора ли прибрать кого-то из них.

Имеется и другая связанная с этим подходом проблема. Поскольку процесс, который создал файл, может умереть, не удалив этот файл, то вы не сможете узнать, жив ли еще этот процесс, пока не попробуете передать ему сообщение. И это ещё не самое страшное — еще хуже, если комбинация ND/PID/CHID указанная в файле, оказывается настолько старой, что может быть повторно использована другой программой! Получив «чужое» сообщение, эта программа в лучшем случае его проигнорирует его, а ведь может и предпринять некорректные действия. Так что такой подход исключается.

Второй подход, где мы используем глобальные переменные для объявления значений ND/PID/CHID, не является общим решением проблемы, поскольку в нем предполагается способность клиента обратиться к этим глобальным переменным. А поскольку для этого требуется использование разделяемой памяти, это не будет работать в сети! Так что этот метод обычно используется либо в

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

Что реально происходит, так это то, что один поток в программе является клиентом, а другой поток — сервером. Поток-сервер создает канал и затем размещает идентификатор канала в глобальной переменной (идентификаторы узла и процесса являются одинаковыми для всех потоков в процессе, так что объявлять их не обязательно). Поток-клиент затем берет этот идентификатор канала и выполняет по нему функцию ConnectAttach.

Третий подход — сделать сервер администратором ресурса — является определенно самым прозрачным и поэтому рекомендуемым общим решением. Механизм того, как это делается, изложен в главе «Администраторы ресурсов», а пока все, что вы должны об этом знать — это то, что сервер регистрирует некое имя пути как свою «область ответственности», а клиенты обращаются к нему обычным вызовом функции open.

Не сочту лишним подчеркнуть:

Файловые дескрипторы POSIX в QNX/Neutrino реализованы через идентификаторы соединений, то есть дескриптор файла уже является идентификатором соединения! Органичность этой схемы в том, что поскольку дескриптор файла, возвращаемый функцией open, фактически является идентификатором соединения, клиенту не нужно выполнять какие-либо дополнительные действия, чтобы использовать это соединение. Например, когда клиент после вызова open вызывает функцию read, передавая ей полученный дескриптор, это с минимальными накладными расходами транслируется в функцию MsgSend.

А что насчет приоритетов?

А что произойдет, если сообщение серверу передадут одновременно два процесса с разными приоритетами?

Сообщения всегда доставляются в порядке приоритетов.

Если два процесса посылают сообщения «одновременно», первым доставляется сообщение от процесса с высшим приоритетом.

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

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

Чтение и запись данных

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

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

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

Интересные события разворачиваются на стороне сервера. Сервер вызывает функцию MsgReceive для приема сообщения от клиента. В зависимости от того, как вы спроектировали вашу систему сообщений, сервер может знать, а может и не знать, насколько велико сообщение клиента. Как сервер может не знать, каков реальный размер сообщения? Возьмем наш пример с файловой системой. Предположим, что клиент делает так:

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

Кодекс Крови. Книга Х

Борзых М.
10. РОС: Кодекс Крови
Фантастика:
фэнтези
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга Х

Легат

Прокофьев Роман Юрьевич
6. Стеллар
Фантастика:
боевая фантастика
рпг
6.73
рейтинг книги
Легат

Защитник. Второй пояс

Игнатов Михаил Павлович
10. Путь
Фантастика:
фэнтези
5.25
рейтинг книги
Защитник. Второй пояс

Счастье быть нужным

Арниева Юлия
Любовные романы:
любовно-фантастические романы
5.25
рейтинг книги
Счастье быть нужным

Огненный князь 3

Машуков Тимур
3. Багряный восход
Фантастика:
фэнтези
боевая фантастика
попаданцы
5.00
рейтинг книги
Огненный князь 3

Гром над Академией Часть 3

Машуков Тимур
4. Гром над миром
Фантастика:
фэнтези
5.25
рейтинг книги
Гром над Академией Часть 3

Не грози Дубровскому! Том III

Панарин Антон
3. РОС: Не грози Дубровскому!
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Не грози Дубровскому! Том III

Не отпускаю

Шагаева Наталья
Любовные романы:
современные любовные романы
эро литература
8.44
рейтинг книги
Не отпускаю

Флеш Рояль

Тоцка Тала
Детективы:
триллеры
7.11
рейтинг книги
Флеш Рояль

Приручитель женщин-монстров. Том 4

Дорничев Дмитрий
4. Покемоны? Какие покемоны?
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Приручитель женщин-монстров. Том 4

Кодекс Охотника. Книга XVIII

Винокуров Юрий
18. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга XVIII

Польская партия

Ланцов Михаил Алексеевич
3. Фрунзе
Фантастика:
попаданцы
альтернативная история
5.25
рейтинг книги
Польская партия

Курсант: Назад в СССР 7

Дамиров Рафаэль
7. Курсант
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Курсант: Назад в СССР 7

Белые погоны

Лисина Александра
3. Гибрид
Фантастика:
фэнтези
попаданцы
технофэнтези
аниме
5.00
рейтинг книги
Белые погоны