Académique Documents
Professionnel Documents
Culture Documents
Dpto. Computacin
Ingeniera Telemtica
Sistemas Distribuidos
Laboratorio 1: Generacin de un programa distribuido con rpcgen.
Objetivo
Esta prctica tiene como finalidad que el alumno sea capaz de crear un programa distribuido
tomando como entrada un programa que originalmente se ejecuta en una mquina local.
Para conseguir este objetivo, se muestra mediante un ejemplo cmo, a partir de un programa local
que visualiza la hora del sistema, se determinan qu procedimiento se ejecutarn de manera
remota y cules de manera local.
Los procedimientos que van a ejecutarse de manera remota van a formar parte de una servicio,
que llamaremos rhora. La interfaz del protocolo de este servicio se describe en el lenguaje XDRL,
y recibe el nombre de rhora.x
Tras someter dicha interfaz al generador rpcgen y basndonos en el conjunto de ficheros
obtenidos en lenguaje C, construiremos un cliente que pida la hora y un servidor que soporte
dicho servicio.
Para finalizar el ejemplo, pondremos en ejecucin el servidor y, mediante un cliente,
comprobaremos que el servidor satisface adecuadamente las peticiones que se le pidan.
La obtencin de la hora
A continuacin vamos a ver, con ms detalles, los pasos que se deben seguir para distribuir una
aplicacin local tomando como ejemplo el programa hora.c
1. Copia, compilacin del programa hora.c
2. Eleccin del conjunto de procedimientos que se situarn en la mquina remota.
3. Creacin de una especificacin en lenguaje XDRL del servicio remoto con nombre rhora.x
4. Compilacin de la interfaz rhora.x para que genere los ficheros correspondientes en
lenguaje C.
5. Escrituras de las rutinas de interfaz del lado del cliente y del servidor.
6. Compilacin y enlace del programa cliente.
7. Compilacin y enlace del programa servidor.
8. Puesta en marcha del servidor y ejecucin del cliente.
hora.c
main
obten_segundos
obten_fecha
escribe_hora
Mquina Local
A la hora de considerar qu procedimientos se pueden mover a una mquina remota, hay que
tener en cuenta los recursos que necesitar cada procedimiento. Por ejemplo, escribe_hora
accede a al salida estndar del proceso (la pantalla) por lo que este procedimiento debera
permanecer local. En general: es difcil mover a una mquina remota procedimientos que realizan
operaciones de entrada/salida o manejan descriptores de ficheros locales.
Tambin hay que considerar la ubicacin de los datos a los que accede cada procedimiento.
Aunque no es ste el caso, podra haber una aplicacin que gestionara un diccionario a travs de
procedimientos, que actuaran sobre una gran base de datos. Parece razonable pensar que si los
procedimientos se ubican remotamente, la base de datos debera ubicarse en el mismo servidor
que los procedimientos, para evitar transmitir por la red el contenido de la base de datos. En
general: los procedimientos deben situarse en la misma mquina donde se ubican los datos sobre
los que actan ya que la transmisin de estructuras grandes de datos como argumentos es
ineficaz.
Por ltimo, hay que observar si los procedimientos contienen llamadas al sistema locales. Si se
decide que sean remotas y el sistema operativo remoto no soporta la misma interfaz de llamadas,
habr que sustituir las antiguas llamadas locales por las que soporte el nuevo sistema operativo
sobre el que acte el procedimiento.
En este caso, se da esta circunstancia tanto en el procedimiento obten_segundos que invoca a la
llamada time y en el procedimiento obten_fecha que usa la llamada local_time.
Como el inters de nuestro programa es obtener una hora fiable de un servidor de tiempos, con
hacer remoto el procedimiento obten_segundos es suficiente, ya que la conversin a un formato
horario es mejor hacerlo localmente. La mquina destino cuenta con el mismo sistema operativo
que la mquina local, por lo que la llamada al sistema time de obten_segundos se puede ejecutar
correctamente en la mquina remota. As, la divisin de procedimientos entre las dos mquinas
quedara:
rhora.c
main
escribe_hora
obten_fecha
RPC
rhora_srp.c
obten segundos
Mquina Local
Mquina Remota
Una vez realizada la divisin de los procedimientos, el siguiente paso es dividir el programa inicial
hora.c en dos componentes. Se seleccionan las constantes y estructuras de datos que usar cada
parte situndolas en ficheros separados. En la mquina local, el fichero rhora.c contendr
exactamente lo mimo que el programa local hora.c excepto la declaracin y el cuerpo del
procedimiento remoto obten_segundos.
El fichero rhora_srp.c (source remote procedure) contiene la declaracin y el cuerpo del
procedimiento que obtiene los segundos del sistema.
Por convenio se usan letras maysculas para representar los nombres de procedimientos y del
programa.
Hay que destacar que el procedimiento OBTEN_SEGUNDOS se ha diseado para que solo tenga
un parmetro de salido. Y ese parmetro es un registro variable que, dependiendo del valor de la
etiqueta status, devolver un valor u otro:
status = HORA_OK indica que el servidor ha realizado el servicio con xito y, por tanto, el
campo segundos contendr los segundos pedidos.
status
rhora_xdr.c: procedimientos que convierten a/desde formato local desde/a formato externo
los tipos de datos declarados en rhora.x
Hay una solucin: escribir en la mquina local, el cuerpo del procedimiento obten_segundos para
sea ste el que llame al procedimiento del stub obten_segundos_1 con los parmetros adecuados
y recoja el resultado de obten_segundos_1 para devolverlo al programa principal, de acuerdo al
tipo de resultado que ste espera. Es decir, todo este proceso de adaptacin de los parmetros
entre el programa principal y el procedimiento del stub del cliente obten_segundos_1 se recoge
dentro del procedimiento obten_segundos.
Por convenio, este procedimiento se conoce como rutina de interfaz del cliente y le vamos a incluir
en el fichero rhora_cif.c (client interfaces).
Grficamente, el esquema de llamada es:
rhora.c
main()
{
obten_segundos();
rhora_cif.c
.
int obten_segundos(time_t *s)
{
prepara_parmetros
obten_segundos_1(parmetros)
recoge resultados
}
rhora_clnt.c
segactual *
obten_segundos_1(void
*argp, CLIENT *clnt)
{
..
Aqu se hace la RPC
}
Adems, para que esta rutina de interfaz sea capaz de realizar una llamada remota al servidor es
necesario crear un cliente del servicio de tiempo con la rutina clnt_create que ofrece la librera rpc.
Por eso es necesario hacer #include <rpc/rpc.h>.
Los parmetros que se necesitan para crear un cliente son: el nombre de la mquina donde reside
el servidor de hora, el nombre de programa del servicio HORA_PROGRAM y HORA_VERSION y
el protocolo de comunicacin. Nosotros utilizaremos udp.
Con todas estas consideraciones, el cdigo de la runita de la interfaz del cliente podra ser el
siguiente:
//rhora_cif.c
#include <time.h>
#include <rpc/rpc.h>
#include "rhora.h"
#define Rmaquina "localhost"
static CLIENT *clte_rhora;
int obten_segundos(time_t *s)
{
struct segactual *segundos;
//se crea un cliente del servicio de hora
clte_rhora = clnt_create(Rmaquina, HORA_PROGRAM, HORA_VERSION, "udp");
if(clte_rhora == NULL)
return -1;
segundos = (struct segactual*) malloc (sizeof(struct segactual));
//se realiza la rpc
segundos = obten_segundos_1(NULL, clte_rhora);
if(segundos == NULL) //error de comunicacin con el servidor
return -1;
else if (segundos->status == HORA_NOK) //error de ejecucin
return -1;
else // se recogen los segundo devueltos
*s = (time_t)segundos->segactual_u.segundos;
}
Con el procedimiento anterior hay que destacar que cuando hay un error en la conexin o bien en
el servidor devuelve un error, el procedimiento enmascara el error de comunicacin devolviendo
un -1, para que el programa principal siga viendo la llamada si se ejecutara localmente.
Rutinas de interfaz del lado del servidor: rhora_sif.c
En el lado del servidor ocurre algo similar a lo que ocurre en el lado del cliente. El servidor, que
ejecuta el programa rhora_svc.c, se encarga de recibir peticiones procedentes de los clientes,
analizar la peticin a realizar, e invocar el procedimiento que lleva a cabo dicha peticin.
En nuestro caso, cuando el servidor reciba la peticin de obtencin de la hora en segundos, ste
invoca el procedimiento del stub obten_segunods_1_svc. Como se puede observar, surge el
mismo problema que apareci en el apartado anterior: este procedimiento no se llama igual que el
procedimiento obten_segundos (que incluimos en el paso 2 en el fichero rhora_srp.c) ni cuenta
con los mismos parmetros.
//declaracin de obten_segundos en rhora_srp.c
int obten_segundos (time_t *s);
//declaracin de obten_segundos_1_svc en rhora_clnt.c
segactual * obten_segundos_1_svc(void *p1, struct svc_req *p2);
La solucin se basa en usar la misma idea aplicada en el apartado anterior: hay que escribir un
cuerpo del procedimiento obten_segundos_1_svc que invoque adecuadamente al procedimiento
obten_segundos, recoja el valor devuelto por este procedimiento, lo analice y, finalmente
construya una respuesta que est de acuerdo con lo que espera el programa rhora_svc.c
La declaracin y el cuerpo de este procedimiento debe guardarse en el fichero rhora_sif.c (Server
interface file). Grficamente:
rhora_svc.c
main()
{
obten_segundos_1_svc();
rhora_sif.c
segactual *
obten_segundos_1_svc()
{
prepara_parmetros
obten_segundos(..)
recoge resultados
rhora_srp.c
int obten_segundos_1_svc
(time_t *s)
{
Aqu se hace la llamada local
Time(&s);
}
rhora_clnt.c
rhora.x
rpcgen
rhora.h
rhora_xdr.c
rhora.c
rhora_cif.c
Compilador
C
rhora
10
rhora_svc.c
rhora.x
rhora_srp.c
rhora.h
rpcgen
rhora_sif.c
Compilador
C
rhora_xdr.c
rhorad
11
Trabajo asignado:
1. Ejecute en primer lugar el programa hora.c en un entorno local.
2. Siga cada uno de los pasos descritos en esta prctica, para convertir al programa hora en
una aplicacin distribuida.
3. Pruebe en primer lugar el cliente y el servidor en la misma mquina y luego en mquinas
diferentes.
4. Cree un fichero Makefile, para hacer menos pesada la organizacin de los ficheros que
intervienen en la aplicacin distribuida. Pruebe este fichero.
Plazo de realizacin:
Dos sesiones de Laboratorio.
12