MyBooks.club
Все категории

Олег Цилюрик - QNX/UNIX: Анатомия параллелизма

На сайте mybooks.club вы можете бесплатно читать книги онлайн без регистрации, включая Олег Цилюрик - QNX/UNIX: Анатомия параллелизма. Жанр: Программное обеспечение издательство -,. Доступна полная версия книги с кратким содержанием для предварительного ознакомления, аннотацией (предисловием), рецензиями от других читателей и их экспертным мнением.
Кроме того, на сайте mybooks.club вы найдете множество новинок, которые стоит прочитать.

Название:
QNX/UNIX: Анатомия параллелизма
Издательство:
-
ISBN:
-
Год:
-
Дата добавления:
16 сентябрь 2019
Количество просмотров:
358
Читать онлайн
Олег Цилюрик - QNX/UNIX: Анатомия параллелизма

Олег Цилюрик - QNX/UNIX: Анатомия параллелизма краткое содержание

Олег Цилюрик - QNX/UNIX: Анатомия параллелизма - описание и краткое содержание, автор Олег Цилюрик, читайте бесплатно онлайн на сайте электронной библиотеки mybooks.club
Книга адресована программистам, работающим в самых разнообразных ОС UNIX. Авторы предлагают шире взглянуть на возможности параллельной организации вычислительного процесса в традиционном программировании. Особый акцент делается на потоках (threads), а именно на тех возможностях и сложностях, которые были привнесены в технику параллельных вычислений этой относительно новой парадигмой программирования. На примерах реальных кодов показываются приемы и преимущества параллельной организации вычислительного процесса. Некоторые из результатов испытаний тестовых примеров будут большим сюрпризом даже для самых бывалых программистов. Тем не менее излагаемые техники вполне доступны и начинающим программистам: для изучения материала требуется базовое знание языка программирования C/C++ и некоторое понимание «устройства» современных многозадачных ОС UNIX.В качестве «испытательной площадки» для тестовых фрагментов выбрана ОСРВ QNX, что позволило с единой точки зрения взглянуть как на специфические механизмы микроядерной архитектуры QNX, так и на универсальные механизмы POSIX. В этом качестве книга может быть интересна и тем, кто не использует (и не планирует никогда использовать) ОС QNX: программистам в Linux, FreeBSD, NetBSD, Solaris и других традиционных ОС UNIX.

QNX/UNIX: Анатомия параллелизма читать онлайн бесплатно

QNX/UNIX: Анатомия параллелизма - читать книгу онлайн бесплатно, автор Олег Цилюрик

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

Приложение

Организация обмена сообщениями

(Владимир Зайцев)

Обмен сообщениями (message passing) является основой архитектуры ОС QNX, на которой строится значительная часть служебных функций системы. Несмотря на свою «элементарность», он является удобным (и в силу своей «нативности» чрезвычайно эффективным!) механизмом для непосредственной организации взаимодействия между процессами. Особый же шарм этого механизма заключается в том, что вместе с передачей данных как таковой можно естественным образом (на основе блокировок Send/Receive/Reply) организовать синхронизацию взаимодействующих процессов.

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

Вместе с тем переход от QNX 4 к QNX 6 вызвал изменения в реализации механизма обмена сообщениями и, как следствие, API-функций. Причиной этого стал переход от однопоточных к многопоточным процессам, при этом обмен сообщениями стал осуществляться не между процессами[43], а между потоками. Соответственно изменился и «адресат» сообщения. В QNX 4 в этом качестве выступал процесс и его можно было однозначно определить по его идентификатору — действительному (при работе на одном узле) или идентификатору виртуального канала («virtual circuit») при межузловых сообщениях. Таким образом, для того чтобы передать сообщение (функцией из семейства Send*()) в адрес некоего сервера, процессу-клиенту достаточно было «знать» этот идентификатор. Получал он его, как правило, либо от «родителя» искомого процесса, либо через сервис глобального пространства имен (qnx_name_attach() и qnx_name_locate()).

Теперь же, в QNX 6, в качестве «адресата» сообщения стал выступать идентификатор соединения (coid), и именно он требуется при вызове функций семейства MsgSend*(). Для создания же соединения с сервером клиенту необходимо «знать» триаду соединения: идентификатор этого процесса-сервера (pid), дескриптор узла (nd), на котором сервер выполняется, и идентификатор созданного сервером канала (chid).

Вторым «возмущением», привнесенным QNX 6 в привычную и сложившуюся технику разработок, явился переход от идентификаторов узлов (nid), которые являлись уникальными в пределах сети и однозначно определяли каждый узел, к дескрипторам узлов (nd), которые уникальны только в пределах каждого данного узла, но не в сети. Уникальность в пределах сети теперь должны обеспечивать символьные имена узлов.

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

Организация обмена сообщениями на основе «семейных» процессов

Рассмотрим, как можно организовать обмен сообщениями между потоками, принадлежащими процессам, связанным «родственными узами». Для простоты изложения, чтобы в дальнейшем не формулировать «поток, принадлежащий процессу», будем рассматривать однопоточные процессы и говорить (в традициях 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().


Олег Цилюрик читать все книги автора по порядку

Олег Цилюрик - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки mybooks.club.


QNX/UNIX: Анатомия параллелизма отзывы

Отзывы читателей о книге QNX/UNIX: Анатомия параллелизма, автор: Олег Цилюрик. Читайте комментарии и мнения людей о произведении.

Прокомментировать
Подтвердите что вы не робот:*
Подтвердите что вы не робот:*
Все материалы на сайте размещаются его пользователями.
Администратор сайта не несёт ответственности за действия пользователей сайта..
Вы можете направить вашу жалобу на почту librarybook.ru@gmail.com или заполнить форму обратной связи.