|
Программирование >> Структура ядра и системные вызовы
Серверная программа вызывается либо без аргументов, либо со спеии-фикацией nettype. Если аргумент nettype отсутствует, по умолчанию принимается значение netpath . / Сначала серверный процесс вызывает функцию RPC svc::RPC svc, которая создает интерфейс к серверному процессу для RPC-функции с заданным номером программы, номером версии и значением nettype. Затем сервер вызывает функцию RPC svc::runJune, которая регистрирует футхкцию printmsg как вызываемую клиентом RPC-функцию, после чего активрирует svc mn для отслеживания клиентских RPC-запросов. Для обработки поступившего клиентского RPC-запроса функция svc run вызывает функцию RPC svc::dispatch, которая проверяет RPC-номер клиентской процедуры и аутентификацию клиента (если это необходимо). Затем вызывается затребованная RPC-функция. Эта функция активизирует функцию RPCsvcr.getargs, которая извлекает значения аргумента клиента. RPC-функция передает возвращенное значение клиенту с помощью функции RPC svc::reply. Последний фрагмент исходного кода, который необходимо включить в наш пример, представляет собой отдельный С-файл {RPC.Q, содержащий определения статических переменных RPCsvcr.numProg и RPCsvcr.progList. Переменная RPC svc::progList является указателем на динамический массив, в котором отслеживается каждая RPC-функция, соответствующая уникальной комбинации номера программы, номера версии и номера процедуры. Переменная RPC svc::numProg содержит число достоверных элементов массива RPC svc::progList. Файл RPC. С имеет следующий вид: tinclude RPC.h int RPC svc::numProg = 0; RPCPROG INFO *RPC svc::progList = 0; Клиентская и серверная программы printmsg компилируются (в системе Solaris 2.x) и запускаются следующим образом: % СС -DSYSV4 -с RPC.C % СС -DSYSV4 msg cls2.C PRC.о -о msg cls2 -Isocket -Insl % СС -DSYSV4 msg cls2.C PRC.о -о msg cls2 -Isocket -Insl % msg svc2 & [135] % msg cls2 fruit Hello RPC world clnt: call printmsg succeeds В этом примере и клиентский, и серверный процессы выполняются на машине fruit. Серверная программа запускается в фоновом режиме, а клиентская - с аргументом Hello RPC world. После вьшолнения клиентской программы серверная программа выводит на системной консоли машины fruit сообщение server: Hello RPC world. . Чтобы пользователи лучше разбирались в том, как работают классы RPC, в следующих разделах мы рассмотррш низкоуровневые API удаленных вызовов Уфоцедур. 12..1. Функция svc create Синтаксис функции svc create имеет следующий вид: #include <rpc/rpc.h> int svc create (void (*dispatch)(struct svc req*, SVCXPRT*), uJong prognum, uJong versnum, char* nettype Функция svccreate создает конечную точку транспортировки для заданного значения nettype в серверном процессе. Сервер контролирует все RPC-обращения к функции с указанными номерами программы и версии. Для каждого из этих RPC-запросов вызывается функция dispatch, которая отвечает на запрос. Возможные значения аргумента nettype приведены в разделе 12.3.1. Функция dispatch определяется пользователем и принимает два аргумента. Первый аргумент содержит информацию о клиентском RPC-вызове, которая используется для ответа на этот вызов. В частности, тип данных struct svc req указывается в заголовке <фс/8УС.И> следующим образом: struct svc req u long rq prog; /* номер сервисной программы */ u long rq vers; /* номер сервисного протокола */ u long rq proc; /* требуемая процедура */ struct opaque auth rq cred; /* необработанная аутентификационная информация */ caddr t rq clntcred; ?\7* обработанная аутентификационная информация только дпя чтения */ struct svcsxprt* rq xprt; iT* соответствующий метод транспортировки */ где поля rp prog, rq vers и rqj>roc содержат номер программы, номер версии и номер процедуры RPC-функции, которую хочет вызвать клиент. Поля rq cred и rqclntcred содержат данные клиента, доступные функции dispatch для его аутентификации. Поле rq xprt содержит информацию о механизме транспортировки, используемом клиентом; функция dispatch, как правило, это поле игнорирует. Второй аргумент svcjcreate - указатель на конечную точку транспортировки. Он передается RPC-функции, которая использует его для получения значений аргументов функции от клиента. Кроме того, он служит для передачи клиенту возвращаемых значений. При успешном выполнении эта функция возврашает ненулевой указат на конечную точку транспортировки, а в случае неудачи - нуль. В ONC для создания обработчиков RPC-серверов используются слеф/ю-щие функции: #include <rpc/rpc.h> SVCXPRT* svctcpjcreate (int svr addr, const u long sendbuf si2e, const u long recvbuf size); j SVCXPRT* svcudpjcreate (int svr addr); f Функции svctcp create и svcudp create - это TCP- и UDP-версии функции svc create. Они организуют взаимодействие клиентского и серверного процессов с применением гнезд. Значение аргумента svcaddr - это номер порта гнезда, используемый RPC-сервером для связи со своими клиентами. Номер порта гнезда может быть задан как RPC ANYSOCK, т.е. это может быть любой номер порта, присвоенный хост-системой. Наконец, значения аргументов sendbuf size и recvbuf size задают размеры буферов для обмена данными между сервером и его клиентами. 12.5.2. Функция svc run Синтаксис функции svcnin имеет следующий вид: #include <rpc/rpc.h> void svc run (void); Эту функцию вызывает RPC-сервер. Она отслеживает клиентские RPC-запросы и для обслуживания поступившего запроса активизирует функцию dispatch, которая была зарегистрирована через API svccreate, svcjpjcreate или svc tli create. Функция svc run не возвращает никаких значений. 12.5.3. Функция svc getargs Функция svc getargs имеет следующий синтаксис: #include <rpc/rpc.h> boot t svc getargs (SVCXPRT* xprt, xdrproc t* func, caddr t argp); Она вызывается RPC-функцией серверного процесса для того, чтобы выбрать аргументы, переданные клиентским процессом. Аргумент xprt - это указатель на назначенный клиентскому процессу механизм транспортировки. Аргумент argp содержит адрес переменной, которой присваиваются значения аргументов клиента. Аргумент/мис представляет собой указатель на XDR-функцию, которая используется для десериализации значений аргументов клиента в формат данных хост-машины сервера. При успешном выполнении эта функция возвращает значение TRUE, а в случае неудачи - FALSE. 12.5.4. Функция svc sendreply Синтаксис функции svcjsendreply имеет следующий вид: #include <rpc/rpc.h> boot t svcjsendreply (SVCXPRT* xprt, xdrproc t* func, caddr t resultp); Она вызывается RPC-функцией в серверном процессе для передачи возвращаемых значений в клиентский процесс. Аргумент xprt - это указатель на назначенный клиентскому процессу механизм транспортировки. Аргумент resultp содержит адрес переменной, в которую помещаются возвращаемые функцией значения. Аргумент firnc представляет собой указатель на XDR-функцию, которая используется для сериализации возвращаемого значения в формат XDR. При успешном выполнении эта функция возвращает значение TRUE, а в случае неудачи - FALSE. 12.5.5. Функция clnt create Функция clnt create имеет следующий синтаксис: #include <rpc/rpc.h> CLIENT* cintjcreate (char* hostnm, u long prognum, u long versnum, const char* nettype); Данная функция создает указатель CLIENT* для связи с RPC-сервером. Аргумент hostnm - это имя компьютера, на котором работает RPC-сервер. Аргументы prognum и versnum идентифицируют RPC-сервер по номеру программы и номеру версии. Аргумент nettype показывает, какой транспортный протокол используется для связи с серверным процессом. Возможные значения аргумента nettype приведены в разделе 12.3. L При неудачном завершении функция clnt create возвращает NULL, а в случае успеха - ненулевой указатель на клиента. Если функция завершилась неудачно, пользователи могут с помощью API clnt pcreateerror просмотреть на стандартном устройстве выводе более подробное сообщение об ошибке. Функция clntjpcreateerror имеет следующий прототип: void dntjjcreateerror (const char* msg prefix string); Аргумент msg prefix string - это определяемая пользователем строка сообщения, которую функция выводит вместе с сообщением об ошибке. 12.5.6. Функция clnt call Синтаксис функции clntjcall имеет следующий вид : #include <rpc/rpc.h> enum clnt stat c 7? car (CLIENT* clntp, u long funcnum, xdrproc t argfunc, caddr t argp, xdrproc t resfunc, caddr t resp, struct timeval timv); Она вызывается в клиентском процессе для вызова RPC-функции. Аргумент clntp - это указатель, полученный из API clntjcreate, clntjpjcreate или clntjlijcreate. Аргумент funcnum - это номер процедуры RPC-функции. Аргумент агфпс представляет собой адрес XDR-функции, которая применяется для сериализации данных входных аргументов клиента в формат XDR перед передачей в RPC-функцию. Аргумент resfunc - это адрес XDR-функции, которая используется для десериализации возвращаемых значений RPC-функции в формат данных клиента. Аргумент timv задает продолжительность тайм-аута для данного вызова (в секундах или микросекундах). При успешном выполнении функция clnt call возврашает значение RPCSUCCESS, а в случае неудачи - ненулевой код завершения. Если функция завершилась неудачно, пользователи могут с помощью API clnt per-ror просмотреть на стандартном устройстве вывода подробное сообщение об ошибке. Функция clnt perror имеет следующий прототип: void c/ntjierror (const CLIENT* clntp, const char* msg prefix); Аргумент msg prefix - это определяемая пользователем строка сообщения, которую функция выводит вместе с сообщением об ошибке. Аргумент clntp является указателем, который идентифицирует вызывающий процесс. 12.6. Управление набором RPC-программ и версий с помощью классов RPC можно создать серверный процесс, который управляет несколькими RPC-программами. Каждая программа может содержать одну и более версий набора RPC-функций. Чтобы разобраться в том, как это осуществляется, рассмотрим пример. В этом примере серверная программа обслуживает две RPC-программы: PR0G1NUM и PR0G2NUM. Программа PR0G1NUM содержит две версии (VERS1NUM и VERS2NUM) RPC-функции с номером процедуры PR0C1-NUM и одну версию (VERS1NUM) RPC-функции с номером процедуры PR0C2NUM. Вторая программа (PR0G2NUM) состоит из одной RPC-функции с номером версии VERS2NUM и номером процедуры PR0C2NUM. Объявления этих номеров программ, версий и процедур содержатся в заголовке test.h: fifndef TEST H fdefine TEST H fdefine PROGINUM fdefine PR0G2NUM 0x20000010 0x20000015 fdefine VERSlNUMirA Ох1л.! ♦ define VERS2NUMqY 0x2 ,K 0x1 0x2 tdefine PROCINUM tdefine PR0C2NUM fendif Программа RPC-сервера называется tesljsvc.C: finclude RPC.h tinclude test.h /* RPC-функция: progno=l, vers=l, proc no=l */ int funcl l l (SVCXPRT* xprt) cerr funcl l l calledXn ; svclp->reply(xprt, (xdrproc t)xdr void, 0); return RPC SUCCESS; /* RPC-функция: progno=l, vers=l, proc no=2 */ int funcl l 2 (SVCXPRT* xprt) cerr funcl l 2 calledXn ; svclp->reply(xprt, (xdrproc t)xdr void, 0); return RPC SUCCESS;
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |