|
Программирование >> Структура ядра и системные вызовы
perror( sysinfо ); return -1; else strcpy(host,argv[3]); return 0; int main( int argc, char* argv[l) ( char buf(801, host[80]; int port=-l, cltsl port=-l, rc, flags=0; if (argc < 2) ( cerr usage: argv[0] <serviceIport no> <cltsl serviceIno> [<host>]\n ; return 1; /* проверить, указан ли номер порта */ (void)sscanf(argv[l], %d . Sport); (void) sscanf (argv[2], %d ,scltsl port); tli *sp; if (port==-l) ( if (gethost(argc, argv, host, sizeof host) < 0) return 2; sp = new tli( host, argv(l], 1 ); } else sp = new tli (port, 1); if (!sp I I !sp->good()} ( cerr clts2: create transport endpoint object failsXn ; return 2; /* присвоить имя конечной точке транспортировки */ If (sp->Bind() < 0) ( cerr clts2: bind failsXn ; return 3; if (port==-l) rc = sp->writeto(MSG2,strlen(MSG2)+1, 0, argv[2], host); else rc = sp->writeto(MSG2, strlen(MSG2)+1, 0, cltsl port); if (rc < 0) ( cerr clts2: writeto failsXn ; return 4; struct t unitdata *ud = 0; if (sp->readfrom(buf, sizeof buf, flags, ud) < 0) ( cerr clts2: readfrom filsXn ; return 5; cerr clts2: read msg: buf Xn ; if ( (sp->writeto(MSG3, strlen(MSG3}+1, flags, ud) < 0) cerr clts2: writeto failsXn ; return 6; return 0; Программа tli clts2 очень похожа на программу tli cltsl. Отличие состоит в том, что она может вызываться не в одном, а в двух вариантах: во-первых, с назначенным целочисленным адресом и целочисленным адресом процесса tli cltsl (для случая локального соединения); во-вторых, с именем своего сервиса и именем сервиса tli cltsl, за которым может следовать необязательное хост-имя машины (при установлении Internet-соединения). Если указывается имя сервиса, это имя должно быть занесено в файл /etc/services. Если хост-имя не указывается, берется хост-имя локальной машины. Работа программы tli clts2 начинается с создания конечной точки TLI по заданным аргументам командной строки. Если необходимо создать конечную точку транспортировки для Internet, то вызывается функция gethost, которая выявляет хост-имя локальной маишны из аргумента командной строки (если он есть) или посредством вызова функции sysinfo. После создания конечной точки TLI процесс присваивает ей имя, а затем посылает сообшение MSG2 в процесс tli cltsl. После передачи сообшения MSG2 процесс ждет, когда процесс tlijcltsl пошлет ему сообшение MSGI. По его получении процесс направляет сообшение на стандартный вывод. Наконец, процесс посылает в процесс tlicltsl сообшение MSG1 и завершается. Конечная точка транспортировки, созданная процессом, уничтожается функцией-деструктором ТЫ::~ТЫ. Приведенный ниже протокол отражает взаимодействие процессов tli cltsl и tli clts2. Создаваемые в ходе взаимодействия конечные точки транспортировки имеют адреса, значения которых являются целыми числами. Конечной точке транспортировки процесса tlijcltsl присваивается адрес 1, а процесса tli clts2 - адрес 2: , ,. -, . л ., * СС -о tli % СС -о tli % tli cltsl bind: 1 % tli clts2 bind: 2 cltsl: read msg: clts2: read msg: cltsl: read msg: [1] + Done tli cltsl clts2 l & t-ll dltl№iWlhel tli clts2.Crslunsi- Hello MSG2 Hello MSGl Hello MSG3 cltsl 1 from clts2 from cltsl from clts2 Чтобы эту программу можно было выполнять с использованием хост-имен и имен сервисов, в файле /etc/services необходимо создать следующие записи: utstl 4046/udp utst2 4047/udp Здесь utstl - это имя сервиса, используемого процессом tlijdtsl, а utst2 - имя сервиса, используемое процессом tli clts2. Оба сервиса используют провайдер транспорта UDP, который предусматривает проведение сеанса связи без установления соединения. Следующий протокол отражает взаимодействие этих же процессов, осуществляемое с использованием конечных точек транспортировки и сети Internet: % tli cltsl utstl & bind: 135123 % tli clts2 utst2 utstl bind: 135124 cltsl: read msg: Hello MSG2 from clts2 clts2: read msg: Hello MSGl from cltsl cltsl: read msg: Hello MSG3 from clts2 [1] + Done tli cltsl utstl Обратите внимание: результат данного сеанса связи идентичен результату, полученному при работе с локальными конечными точками транспортировки. Перекомпилировать программы tli cltsl.Cwi tli clts2.Cне нужно. Эти же программы можно выполнять на разных мащинах, включенных в локальную сеть. Предположим, что программа tli cltsl выполняется на мащине с именем fruit, а программа tli clts2 - на мащине apple. Как вызываются эти программы, описано ниже. Запускаем программу tlijcltsl на мащине fruit. fruit % tli cltsl utstl & [1425] Запускаем программу tli clts2 на мащине apple: apple % tli clts2 utst2 utstl fruit После того как между компьютерами будет установлено соединение, выходные сообщения tlijcltsl будут выводиться на экран мащины fruit, а сообщения tli clts2 - на экран мащины apple. работающим на разных мащинах. Это очень важно для любого серьезного приложения архитектуры клиент/сервер, где сервер обычно работает на мощном компьютере, а клиентские процессы - на настольных мащинах пользователей. В данной главе подробно описывается синтаксис интерфейсов прикладного программирования гнезд и ТЫ. Приводятся примеры программ, иллюстрирующие применение этих механизмов. Определяются класс sock и класс ТЫ, инкапсулирующие эти API и позволяющие пользователям, которые рещили применить такие конструкции для создания приложений IPC, сократить затраты времени на программирование. Интерфейс транспортного уровня более гибок в применении, чем гнезда, потому что он поддерживает почти все транспортные протоколы. При организации взаимодействия с помощью гнезд может использоваться ограниченное число протоколов, причем гнезда разных типов поддерживают различные наборы протоколов. Кроме того, в ТЫ применяются более эффективные методы управления памятью (функции tjalloc и t Jree), информирования об ошибках в пересылке сообщений (t error, t rcvuderr, tjook) и осуществления разрыва соединений (tli snddis, tli rcvdis, tlijsndrel, tli rcvrel). Поэтому ТЫ позволяет пользователям создавать более-развитые приложения для IPC. Однако ТЫ используется только в UNIX System V.3 и V.4, тогда как гнезда представлены во всех последних разновидностях UNIX (BSD 4.2, 4.3, 4.4 и UNIX System V.4). Более того, на сегодняшний день уже имеется множество IPC-приложений, построенных на основе использования гнезд. Следовательно, если главными факторами для разработчиков приложений являются мобильность и совместимость с уже существующими приложениями, им следует ориентироваться на гнезда, а не на ТЫ. 11.8. Заключение В этой главе рассмотрены такие средства межпроцессного взаимодействия, как гнезда BSD UNIX и интерфейс транспортного уровня (ТЫ) UNIX System V.3/V.4. Гнезда и ТЫ более эффективны, чем сообщения, разделяемая память и семафоры, так как они позволяют взаимодействовать процессам. ГЛАВА Удаленные вызовы процедур Удаленные вызовы процедур (Remote procedure calls, RPC) - это механизм, с помощью которого один процесс активизирует другой процесс на этой же или удаленной машине для выполнения какой-то функции от своего имени. RPC напоминает вызов локальной функции: процесс вызывает функцию и передает ей данные, а затем ожидает, когда она возвратит результат. Специфика заключается в том, что эту функцию вьшолняет другой процесс. Такое взаимодействие процессов обязательно протекает по схеме клиент/сервер, в которой процесс, активизирующий RPC, является клиентским, а процесс, выполняющий RPC-функцию,- серверным. Серверный процесс обеспечивает доступ к одной или нескольким сервисным функциям, которые могут вызываться его клиентами. Удаленные вызовы процедур используются в сетевых приложениях для подключения к сетевым ресурсам других машин. Например, в распределенной базе данных серверным является процесс управления БД, обеспечивающий поиск и хранение данных в ее файлах. Клиентские процессы - внешние программы БД, которые позволяют пользователям запрашивать и обновлять данные. Клиентские процессы преобразуют команды пользователя в RPC и направляют их серверному процессу. Значения, возвращаемые RPC-функ-циями, сообщаются пользователю клиентскими процессами. Рассмотрим еще один пример применения RPC: серверный процесс запускается на высокопроизводительном компьютере, а клиентские - на менее мощных. Когда клиентскому процессу нужно выполнить задание с большим объемом вычислений, он с помощью RPC активизирует серверный процесс, и задание выполняется на сервере. Таким образом обеспечивается более равномерная нагрузка на компьютеры и поддерживается приемлемый уровень производительности клиентского компьютера.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |