Организация обмена сообщениями на основе «семейных» процессов
Организация обмена сообщениями на основе «семейных» процессов
Рассмотрим, как можно организовать обмен сообщениями между потоками, принадлежащими процессам, связанным «родственными узами». Для простоты изложения, чтобы в дальнейшем не формулировать «поток, принадлежащий процессу», будем рассматривать однопоточные процессы и говорить (в традициях QNX 4) «обмен сообщениями между процессами».
Итак, пусть некий родительский процесс порождает на другом узле дочерний процесс. Под порождением будем подразумевать «запуск с узла», то есть запуск процесса, выполняемый утилитой on с опцией -f. Для порождения используем функцию spawn():
char* args[] = { "/net/904-3/home/ZZZ/bin/TestChild", NULL};
...
spawn("/home/ZZZ/bin/TestChild", 0, NULL, &InhProc, args, NULL);
Рассмотрим вначале проблемы, стоящие перед дочерним процессом при его желании связаться с родительским. Как уже указывалось, для создания соединения ему необходимо «знать» триаду соединения.
Пусть процессу-клиенту известно символьное имя узла, на котором функционирует искомый адресат. (При описываемой здесь «семейной» архитектуре разрабатываемой системы символьные имена обычно жестко определены и поэтому зачастую просто записываются в конфигурационном файле, откуда процессы всегда могут получить символьное имя нужного узла.) Для того чтобы получить дескриптор узла по известному имени, можно вызвать функцию netmgr_strtond(), которая преобразует имя узла в его дескриптор.
Однако вызов этой функции дочерним процессом приводит к неожиданному (по крайней мере, так было со мной...) на первый взгляд результату: функция возвращает дескриптор узла «с точки зрения» родительского процесса! Иными словами, нулевой дескриптор приписывается не узлу, на котором «живет» дочерний процесс, а узлу с родительским процессом. Другие дескрипторы тоже соотносятся с именами узлов так, как это выполняется на узле с родителем — порожденный процесс, унаследовав от родителя текущую рабочую и корневую директории, тем самым остался, если можно так выразиться, душой на своей исторической родине.
В [4] (глава Дмитрия Алексеева «Утилита on») этот вопрос был достаточно хорошо освещен и было сказано, что для решения проблемы следует перед порождением процесса вызвать функцию chroot() с именем узла, на котором процесс будет порожден (и при необходимости «обратным» вызовом chroot() с именем узла процесса-родителя после вызова spawn()). Это позволяет порожденному процессу обрести новую корневую директорию на том узле, где он выполняется. И тогда вызовы netmgr_strtond() будут возвращать дескрипторы узлов именно с точки зрения того узла, на котором функционирует порожденный процесс.
Далее, если дочерний процесс запущен на удаленном узле, то вызванная им функция getppid() в качестве родительского процесса возвращает совсем даже не идентификатор «фактического» родителя, а идентификатор процесса io-net, что, может быть, формально и верно, но по существу это издевательство (особенно для «мигрантов» с QNX 4, где они получали идентификатор виртуального канала и обращались с ним как с обычным идентификатором процесса). Итак, для того чтобы порожденный процесс знал свое «отчество», проще всего родителю передать свой идентификатор дочернему процессу при его рождении в параметре списка argv[].
Я бы рекомендовал также не уповать на то, что дескрипторы каналов, создаваемые процессами-адресатами отправляемых сообщений, всегда будут равны 1. По ряду причин это далеко не всегда так. И для надежности лучше просто передавать этот дескриптор в аргументах при порождении процесса.
Таким образом, родительский процесс при порождении дочернего процесса должен передать ему в списке аргументов свой идентификатор и дескриптор созданного канала и косвенно, посредством вызова chroot(), имя узла, на котором дочерний процесс запускается. После этого порожденный процесс способен правильно собрать триаду, необходимую для выполнения MsgSend().
Теперь обсудим проблемы, стоящие перед родительским процессом. Если мы хотим отсылать сообщения с родительского процесса на порожденный, то два из трех членов триады родительский процесс может легко получить: дескриптор узла — с помощью функции netmgr_strtond(), а идентификатор порожденного процесса возвращается функцией spawn(). Но вот с дескриптором канала опять появляется риск «не угадать». Кроме того, если родитель породит дочерний процесс и немедленно после этого попытается подсоединиться к каналу, который должен создать этот процесс, то, вероятнее всего, функция ConnectAttach() вернет -1, поскольку порожденный процесс еще не успеет к тому времени создать канал. Значит, понадобится цикл на N попыток с паузой в ожидании открытия.
Не проще ли тогда просто выполнить синхронизацию? То есть родительскому процессу дождаться сообщения от дочернего процесса, которое будет означать, что порожденный процесс выполнил все необходимые действия по своему развертыванию и в частности создал канал. И теперь совершенно естественно передать в этом синхронизирующем сообщении дескриптор созданного канала. После принятия сообщения родительский процесс имеет все необходимые ему данные для выполнения функции отсылки сообщения MsgSend().
При подобной иерархической структуре системы по типу «родитель-ребенок» общение между порожденными процессами, если таковое требуется, обеспечивается с помощью родительского процесса. Породив один из процессов и получив от него дескриптор канала, родительский процесс может при порождении еще одного процесса передать ему полную триаду «старшего» дочернего процесса, позволяющую новому процессу установить с ним соединение.
Ниже приводится образец кода, реализующего этот подход. Обратите внимание на значение аргумента index, задаваемое в вызовах функции ConnectAttach() равным _NTO_SIDE_CHANNEL. В примерах из [1], книги, безусловно, основополагающей для любого программиста под QNX 6, для упрощения изложения это значение устанавливается в 0. Однако значение, равное _NTO_SIDE_CHANNEL, гарантирует, что возвращаемое функцией значение идентификатора соединения будет взято не из того же пространства, из которого выделяются файловые дескрипторы; в противном случае возникают проблемы, достаточно определенно обрисованные в описании функции ConnectAttach(), приведенном в технической документации QNX.
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКДанный текст является ознакомительным фрагментом.
Читайте также
Применение обмена сообщениями
Применение обмена сообщениями Теперь, когда мы рассмотрели базовые концепции обмена сообщениями и выяснили, что он используется даже в таких обычных повседневных вещах как библиотека языка Си, давайте рассмотрим кое-какие детали.Архитектура и структураМы рассуждали о
Особенности обмена сообщениями в сети
Особенности обмена сообщениями в сети Итак, как только соединение установлено, все дальнейшие операции обмена сообщениями осуществляются в соответствии с этапом 4, как указано на рисунке. Это может привести вас к ошибочному представлению, что передача сообщений по сети
Анализ обмена сообщениями
Анализ обмена сообщениями В QNX4 клиент мог найти сервер двумя способами:• используя глобальное пространство имен;• выполнение open() в отношении администратора ввода/вывода.«Клиент/сервер» с использованием глобального пространства именЕсли взаимоотношения
Приложение Организация обмена сообщениями (Владимир Зайцев)
Приложение Организация обмена сообщениями (Владимир Зайцев) Обмен сообщениями (message passing) является основой архитектуры ОС QNX, на которой строится значительная часть служебных функций системы. Несмотря на свою «элементарность», он является удобным (и в силу своей
Обмен сообщениями на основе менеджера ресурсов
Обмен сообщениями на основе менеджера ресурсов Описанный выше способ построения функционирующей в сети системы процессов может быть реализован далеко не всегда. Зачастую клиенту не известна полная триада, позволяющая ему создать соединение с сервером. Вспомним, что в
Пример обмена сообщениями с помощью менеджера ресурсов
Пример обмена сообщениями с помощью менеджера ресурсов Код файла заголовков #define NET_OPER "/net/904-3"#define NET_REG "/net/Bed-Test"// Максимальная длина обычного стандартного сообщения.#define MESSIZE_MAX 100// Максимальная длина инвентаризационного имени процесса#define PROC_NAME_MAX 100struct IdLabel_t { // Структура,
2.4.2. Клиент для мгновенного обмена сообщениями Pidgin
2.4.2. Клиент для мгновенного обмена сообщениями Pidgin Практически каждый пользователь Интернета использует ICQ или другой сервис для мгновенного обмена сообщениями. У нас популярнее ICQ, а на Западе - другие сервисы, например AOL AIM.Сейчас мы поговорим о том, как настроить Pidgin
12.2.4. Выбор программы для мгновенного обмена сообщениями. Настройка проприетарных клиентов для работы через Tor
12.2.4. Выбор программы для мгновенного обмена сообщениями. Настройка проприетарных клиентов для работы через Tor Таких программ тоже предостаточно. Вот неполный список клиентов для мгновенного обмена сообщениями с открытым кодом:? Instantbird (http://www.instantbird.com/) – поддерживает
1.2. Фундаментальные концепции, лежащие в основе понятия зрелости производственных процессов
1.2. Фундаментальные концепции, лежащие в основе понятия зрелости производственных процессов Согласно словарю Вебстера, процесс является «системой операций для производства чего-либо… последовательностью действий, изменений или функций, предназначенных для
Глава 5 ICQ и другие системы мгновенного обмена сообщениями
Глава 5 ICQ и другие системы мгновенного обмена сообщениями ICQ: установка и получение собственного номера. Обмен сообщениямиТонкости ICQАльтернативные клиенты ICQСети MSN и JabberЭкономим на телефоне с помощью SkypeЭлектронная почта, безусловно, хорошее средство общения, но далеко
Программы для обмена мгновенными сообщениями
Программы для обмена мгновенными сообщениями Когда возникла первая система обмена мгновенными сообщениями (Instant Messaging), ее использовали в основном для развлечения. Сегодня с помощью таких систем деловые люди ведут переговоры и управляют сделками. Мгновенные сообщения
Хранение семейных тайн: ключевое слово protected
Хранение семейных тайн: ключевое слово protected Вы уже знаете, что открытые элементы непосредственно доступны отовсюду, а приватные элементы недоступны для объектов вне класса, определяющего эти элементы. Язык C#, занимающий лидирующие позиции среда многих других
2.2.3 Организация операций обмена с дисками
2.2.3 Организация операций обмена с дисками Операции ввода-вывода, как правило, образуют наиболее медленную компоненту обработки баз данных. Поэтому от их реализации существенно зависит общая продуктивность сервера. Для оптимизации ввода-вывода и повышения надежности в
Глава 19 Болталка ICQ. Программа для мгновенного обмена сообщениями
Глава 19 Болталка ICQ. Программа для мгновенного обмена сообщениями 19.1. Что такое ICQ ICQ — один из самых популярных сервисов мгновенного обмена сообщениями. Это своего рода Интернет-пейджер. Аббревиатура ICQ означает «I seek you» («Я ищу тебя»), в России эту программу принято