Главная страница Взаимодействие нетривиальных процессов 4. В разделе 15.3 мы отмечали, что для создаваемых вызовом cloor create дверей автоматически устанавливается бит FD CLOEXEC. Однако мы можем вызвать fcntl после возврата из cloor create и сбросить этот бит. Что произойдет, если мы сделаем это, вызовем exec, а затем обратимся к процедуре сервера из клиента? 5. В листингах 15.23 и 15.24 добавьте вывод текущего времени в вызовах printf сервера и клиента. Запустите клиент и сервер. Почему первый экземпляр процедуры сервера возвращается через две секунды после запуска? 6. Удалите блокировку, защищающую дескриптор fd в листингах 15.17 и 15.18, и убедитесь, что программа больше не работает. Какая при этом возникает ошибка? 7. Если мы хотим лишь испытать возможность отмены потока с процедурой сервера, нужно ли нам устанавливать процедуру создания сервера? 8. Проверьте, что вызов doorrevoke дает возможность завершиться работающим с данной процедурой потокам. Выясните, что происходит при вызове door cal 1 после аннулирования процедуры. 9. В нашем решении предыдущего упражнения и в листинге 15.17 мы говорим, что дескриптор двери должен быть глобальным, если он нужен процедуре сервера или процедуре создания сервера. Это утверждение, вообще говоря, неверно. Перепишите решение предыдущего упражнения, сохранив fd в качестве автоматической переменной функции main. 10. В программе листинга 15.18 мы вызывали pthread attr init и pthread attr destroy каждый раз, когда создавался поток. Является ли такое решение оптимальным? ГЛАВА 16 Пакет Sun RPC 16.1. Введение Когда мы разрабатываем приложение, мы встаем перед выбором: 1. Написать одну большую монолитную программу, которая будет делать все. 2. Разделить приложение на несколько процессов, взаимодействующих друг с другом. Если мы выбираем второй вариант, перед нами опять встает вопрос: 2.1. предполагать ли, что все процессы выполняются на одном узле, что допускает использование средств IPC для взаимодействия между ними, либо 2.2. допускать возможность запуска части процессов на других узлах, что требует какой-либо формы взаимодействия по сети. Взгляните на рис. 15.1. Верхняя ситуация соответствует варианту 1, средняя - варианту 2.1, а нижняя - варианту 2.2. Большая часть этой книги посвящена обсуждению случая 2.1, то есть взаимодействию процессов в пределах одного узла с помощью таких средств IPC, как передача сообщений, разделяемая память и, возможно, некоторых форм синхронизации. Взаимодействие между потоками одного процесса или разных процессов является частным случаем этого сценария. Когда мы выдвигаем требование поддержки возможности сетевого взаимодействия между составляющими приложения, для разработки чаще всего используется явное сетевое программирование. При этом в программе используются вызовы интерфейсов сокетов или XTI, о чем рассказывается в [24]. При использовании интерфейса сокетов клиенты вызывают фзшкции socket, connect, read и write, а серверы вызывают socket, bind, listen, accept, read и write. Большая часть знакомых нам приложений (браузеры, серверы Web, клиенты и серверы Telnet) написаны именно так. Альтернативным способом разработки распределенных приложений является неявное сетевое программирование. Оно осуществляется посредством удаленного вызова процедур (remote procedure call - RPC). Приложение кодируется с использованием тех же вызовов, что и обычное несетевое, но клиент и сервер могут находиться на разных узлах. Сервером называется процесс, предоставляющий другому возможность запускать одну из составляющих его процедур, а клиентом - процесс, вызывающий процедуру сервера. То, что клиент и сервер находятся на разных узлах и для связи между ними используется сетевое взаимодействие, большей частью остается скрыто от программиста. Одним из критериев оценки качества пакета RPC является именно скрытость лежащего в основе интерфейса сети. Пример в качестве примера использования RPC перепищем листинги 15.1 и 15.2 для использования Sun RPC вместо дверей. Клиент вызывает процедуру сервера с аргументом типа 1 ong, а возвращаемое значение представляет собой квадрат аргумента. В листинге 16.1 приведен текст первого файла, square.х. Листинг 16.1. Файл спецификации RPC sunrpc/squarel/square.x 1 struct squarejn { /* входные данные (аргумент) */ 2 long argl: 3 }: 4 Struct square out { /* возвращаемые данные (результат) */ 5 long resl; 6 }: 7 program SQUARE PROG { 8 version SQUARE VERS { 9 square out SQUAREPROC(square in) = 1: /* номер процедуры = 1 */ 10 } = 1: /* номер версии */ 11 } = 0x31230000; /* номер программы */ Файлы с расщирением . х называются файлами спецификации RPC. Они определяют процедуры сервера, их аргументы и возвращаемые значения. Определение аргумента и возвращаемого значения 1-6 Мы определяем две структуры - одну для аргументов (одно поле типа 1 ong) и одну для результатов (тоже одно поле типа long). Определение программы, версии и процедуры 7-11 Мы определяем программу RPC с именем SQUARE PROG, состоящую из одной версии (SQUARE VERS), а эта версия представляет собой единственную процедуру сервера с именем SQUAREPROC. Аргументом этой процедуры является структура square 1n, а возвращаемым значением - структура square out. Мы также присваиваем этой процедуре номер 1, как и версии, а программе мы присваиваем 32-разрядный щестнадцатеричный номер. (О номерах программ более подробно говорится в табл. 16.1.) Компилировать спецификацию нужно программой rpcgen, входящей в пакет Sun RPC. Теперь напищем функцию mai п клиента, который будет осуществлять удаленный вызов процедуры. Текст программы приведен в листинге 16.2. Листинг 16.2. Функция main клиента, делающего удаленный вызов процедуры sunrpc/squarel/client.c 1 #include unpipc.h /* наш заголовочный файл */ 2 #lnclude square.h /* создается rpcgen */
|
© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |