Операционная система UNIX - Андрей Робачевский
Шрифт:
Интервал:
Закладка:
Семантика вызова
Вызов локальной процедуры однозначно приводит к ее выполнению, после чего управление возвращается в головную программу. Иначе дело обстоит при вызове удаленной процедуры. Невозможно установить, когда конкретно будет выполняться процедура, будет ли она выполнена вообще, а если будет, то какое число раз? Например, если запрос будет получен удаленной системой после аварийного завершения программы сервера, процедура не будет выполнена вообще. Если клиент при неполучении отклика после определенного промежутка времени (тайм-аута) повторно посылает запрос, то может создаться ситуация, когда отклик уже передается по сети, повторный запрос вновь принимается на обработку удаленной процедурой. В этом случае процедура будет выполнена несколько раз.
Таким образом, выполнение удаленной процедуры можно характеризовать следующей семантикой:
□ Один и только один раз. Данного поведения (в некоторых случаях наиболее желательного) трудно требовать ввиду возможных аварий сервера.
□ Максимум раз. Это означает, что процедура либо вообще не была выполнена, либо была выполнена только один раз. Подобное утверждение можно сделать при получении ошибки вместо нормального отклика.
□ Хотя бы раз. Процедура наверняка была выполнена один раз, но возможно и больше. Для нормальной работы в такой ситуации удаленная процедура должна обладать свойством идемпонентности (от англ. idemponent). Этим свойством обладает процедура, многократное выполнение которой не вызывает кумулятивных изменений. Например, чтение файла идемпонентно, а добавление текста в файл — нет.
Представление данных
Когда клиент и сервер выполняются в одной системе на одном компьютере, проблем с несовместимостью данных не возникает. И для клиента и для сервера данные в двоичном виде представляются одинаково. В случае удаленного вызова дело осложняется тем, что клиент и сервер могут выполняться на системах с различной архитектурой, имеющих различное представление данных (например, представление значения с плавающей точкой, порядок следования байтов и т.д.)
Большинство реализаций системы RPC определяют некоторые стандартные виды представления данных, к которым должны быть преобразованы все значения, передаваемые в запросах и откликах.
Например, формат представления данных в RPC фирмы Sun Microsystems следующий:
Порядок следования байтов Старший — последний Представление значений с плавающей точкой IEEE Представление символа ASCIIСеть
По своей функциональности система RPC занимает промежуточное место между уровнем приложения и транспортным уровнем. В соответствии с моделью этому положению соответствуют уровни представления и сеанса. Таким образом, RPC теоретически независим от реализации сети, в частности, от сетевых протоколов транспортного уровня.
Программные реализации системы, как правило, поддерживают один или два протокола. Например, система RPC разработки фирмы Sun Microsystems поддерживает передачу сообщений с использованием протоколов TCP и UDP. Выбор того или иного протокола зависит от требований приложения. Выбор протокола UDP оправдан для приложений, обладающих следующими характеристиками:
□ Вызываемые процедуры идемпонентны.
□ Размер передаваемых аргументов и возвращаемого результата меньше размера пакета UDP — 8 Кбайт.
□ Сервер обеспечивает работу с несколькими сотнями клиентов. Поскольку при работе с протоколами TCP сервер вынужден поддерживать соединение с каждым из активных клиентов, это занимает значительную часть его ресурсов. Протокол UDP в этом отношении является менее ресурсоемким.
С другой стороны, TCP обеспечивает эффективную работу приложений со следующими характеристиками:
□ Приложению требуется надежный протокол передачи
□ Вызываемые процедуры неидеипонентны
□ Размер аргументов или возвращаемого результата превышает 8 Кбайт
Выбор протокола обычно остается за клиентом, и система по-разному организует формирование и передачу сообщений. Так, при использовании протокола TCP, для которого передаваемые данные представляют собой поток байтов, необходимо отделить сообщения друг от друга. Для этого, например, применяется протокол маркировки записей, описанный в RFC1057 "RPC: Remote Procedure Call Protocol specification version 2", при котором в начале каждого сообщения помещается 32-разрядное целое число, определяющее размер сообщения в байтах.
По-разному обстоит дело и с семантикой вызова. Например, если выполняется с использованием ненадежного транспортного протокола (UDP), система выполняет повторную передачу сообщения через короткие промежутки времени (тайм-ауты). Если приложение-клиент не получает отклик, то с уверенностью можно сказать, что процедура была выполнена ноль или большее число раз. Если отклик был получен, приложение может сделать вывод, что процедура была выполнена хотя бы однажды. При использовании надежного транспортного протокола (TCP) в случае получения отклика можно сказать, что процедура была выполнена один раз. Если же отклик не получен, определенно сказать, что процедура выполнена не была, нельзя.[82]
Как это работает?
По существу, собственно система RPC является встроенной в программу- клиент и программу-сервер. Отрадно, что при разработке распределенных приложений, не придется вникать в подробности протокола RPC или программировать обработку сообщений. Система предполагает существование соответствующей среды разработки, которая значительно облегчает жизнь создателям прикладного программного обеспечения. Одним из ключевых моментов в RPC является то, что разработка распределенного приложения начинается с определения интерфейса объекта — формального описания функций сервера, сделанного на специальном языке. На основании этого интерфейса затем автоматически создаются заглушки клиента и сервера. Единственное, что необходимо сделать после этого, — написать фактический код процедуры.
В качестве примера рассмотрим RPC фирмы Sun Microsystems.
Система состоит из трех основных частей:
□ rpcgen(1) — RPC-компилятор, который на основании описания интерфейса удаленной процедуры генерирует заглушки клиента и сервера в виде программ на языке С.
□ Библиотека XDR (eXternal Data Representation), которая содержит функции для преобразования различных типов данных в машинно- независимый вид, позволяющий производить обмен информацией между разнородными системами.
□ Библиотека модулей, обеспечивающих работу системы в целом.
Рассмотрим пример простейшего распределенного приложения для ведения журнала событий. Клиент при запуске вызывает удаленную процедуру записи сообщения в файл журнала удаленного компьютера.
Для этого придется создать как минимум три файла: спецификацию интерфейсов удаленных процедур log.x (на языке описания интерфейса), собственно текст удаленных процедур log.c и текст головной программы клиента main() — client.c (на языке С) .
Компилятор rcpgen(1) на основании спецификации log.x создает три файла: текст заглушек клиента и сервера на языке С (log_clnt.c и log_svc.с) и файл описаний log.h, используемый обеими заглушками.
Итак, рассмотрим исходные тексты программ.
log.xВ этом файле указываются регистрационные параметры удаленной процедуры — номера программы, версии и процедуры, а также определяется интерфейс вызова — входные аргументы и возвращаемые значения. Таким образом, определена процедура RLOG, в качестве аргумента принимающая строку (которая будет записана в журнал), а возвращаемое значение стандартно указывает на успешное или неудачное выполнение заказанной операции.
program LOG_PROG {
version LOG_VER {
int RLOG(string) = 1;
} = 1;
} = 0x31234567;
Компилятор rpcgen(1) создает файл заголовков log.h, где, в частности, определены процедуры:
log.h/*
* Please do not edit this file.
* It was generated using rpcgen.
*/
#ifndef _LOG_H_RPCGEN
#define _LOGH_H_RPCGEN
#include <rpc/rpc.h>
/* Номер программы */
#define LOG_PROG ((unsigned long)(0x31234567))
#define LOG_VER ((unsigned long)(1)) /* Номер версии */
#define RLOG ((unsigned long)(1)) /* Номер процедуры */
extern int *rlog_1();