Professional Documents
Culture Documents
peticin respuesta
cliente
servidor
cliente
(ack)
servidor
cliente
(34759037F3247A)
servidor
cliente
(ack)
servidor
Diapo. No. 2
E/S no es un concepto clave para los sistemas centralizados; pero si para la computacin o clculo distribuido Objetivo: hacer el clculo distribuido como si fuera clculo centralizado Clculo centralizado: llamadas de procedimientos y/o funciones
Dr. Roberto Gmez C. Diapo. No. 3
SP
SP
SP
Diapo. No. 4
Por referencia
en el stack se almacena la direccin de la variable es posible modificar el valor del parmetro
call-by-copy/restore
se copia el valor de la variable en el stack, (como en paso por valor) stack al final de la ejecucin local se copia el valor que tiene la variable dentro del procedimiento, en el stack el procedimiento que mand llamar al procedimiento copia el valor final en condiciones normales tiene el mismo efecto que el paso por referencia
Dr. Roberto Gmez C. Diapo. No. 5
El RPC
Creado por Birrel & Nelson en 1984 Permiten a los programas llamar procedimientos localizados en otras mquinas Un proceso x en una mquina A, puede llamar un procedimiento localizado en una mquina B Informacin puede llevarse del proceso invocador al invocado dentro de los parmetros Ningn mensaje u operacin de E/S es visible para el programador Problemas a resolver:
procedimientos invocador e invocado se ejecutan en diferentes mquinas, i.e. diferentes direcciones y posiblemente diferentes arquitecturas ambas mquinas pueden fallar
Dr. Roberto Gmez C. Diapo. No. 6
Mquina Servidor
stub del servidor
Unpack parmetros Pack resultado call servidor return
kernel
kernel
mensaje sum(i,j)
sum
4
7
kernel
kernel
Diapo. No. 9
Problemas a resolver
diferencias entre representacin de datos diferencias en formatos paso de apuntadores, (estructuras complejas)
Optimizacin
especificacin parmetros de entrada y salida registros para paso de apuntadores
Diapo. No. 10
#include <header.h> specification of file_server, version 3.1 file server, long read(in char name[MAX_PATH], out char buf[BUF_SIZE], in long bytes, in long position); long write(in char name[MAX_PATH], in char buf[BUF_SIZE], in long bytes, in long position); int create(in char[MAX_PATH], in int mode); int delete(in char[MAX_PATH]); end.
Diapo. No. 11
SERVIDOR
Binder
Sistema Distribuido
Diapo. No. 12
Peticin cliente 3
error
servicio NO disponible
Binder
proceso 1 solicitante
2
stub cliente
servicio disponible
Nombre, Num. versin, Id.nico, Manejador
Diapo. No. 13
Accin
Registrar Suprimir Buscar
Parmetros Entrada
Nombre, versin, manejador, id nico Nombre, versin, id nico Nombre, Nombre versin
Salida
Diapo. No. 14
Puerto 111
Servidor
Portmapper
Puerto 1061
Cliente
Diapo. No. 15
definido por y administrado por Sun definido d fi id por el usuario l i de trnsito, (aplicaciones con generacin de nmeros) reservado para un futuro uso
Ejemplo rpcinfo
armagnac:45>rpcinfo -s toto program version(s) netid(s) 100000 2,3,4 udp, tcp, tictls, ticosord, ticots 100029 2,1 ticots, ticotsord, ticlts 100078 4 ticots, ticotsord, ticlts 100087 10 udp 100011 1 ticlts, udp 100002 3,2 ticlts, udp 100099 1 ticots, ticotsord, ticlts 100012 1 ticlts, udp 100008 1 ticlts, udp 100001 4,3,2 432 ticlts, udp i l d 100024 1 ticots, ticotsord, ticlts, tcp, udp 100021 2,3,1 ticots, ticotsord, ticlts, tcp, udp 134177279 1,2 tcp armagnac:46> service rpcbin keyserv kerbd admind rquotad rusersd sprayd walld rstad d status nlockmgr owner superuser superuser superuser superuser superuser superuser superuser superuser superuser superuser superuser superuser 5001
Diapo. No. 18
callrpc () host, programa, versin, procedimiento, argumentos Mquina Cliente errores o resultados Programa Cliente
Diapo. No. 19
Aplicacin Usuario
4. TRANSPORTE
TCP
UDP
3. RED
IP
1-2.ENLACE / FSICO
NIVELES OSI
Interface Hardware
RED
Dr. Roberto Gmez C. Diapo. No. 20
10
1. El procedimiento del cliente llama al client-stub normalmente. 2. El client-stub construye un mensaje y lo pasa al kernel. 3. El kernel enva el mensaje al kernel remoto. 4. El kernel remoto pasa el mensaje al server-stub. 5. El server-stub desempaca los parmetros y llama al servidor. 6. El servidor realiza el trabajo y regresa el resultado al stub. 7. El server-stub lo empaqueta en un mensaje y lo pasa al kernel. 8. El kernel remoto enva un mensaje al cliente. 9. El kernel del cliente le da el mensaje al client-stub. 10. El stub desempaca el resultado y lo regresa al cliente.
Diapo. No. 21
Mquina Servidor
Realizar sevicio Servidor
Stub Cliente
Kernel
Mquina
Contexto switch al kernel Copiar mensaje en el kernel Determinar direcciones destino Poner direccin en encabezado mensaje Establecer la interfaz de la red Hechar a andar el timer
Switch contexto a server stub Copiar mensaje en server stub Ver si stub esta esperando Decidir a que stub darselo Checar el paquete para validacin Interrupcin de proceso
Kernel Mquina i
Diapo. No. 22
11
EL RPC DE SUN
El rpcgen y el lenguaje de especificacin RPCL Ejemplos: - Llamada procedimientos con un solo parmetro - Llamada remota con mltiples parmetros
Diapo. No. 23
user developed
Compilador RPC
compilar y ligar
compilar y ligar
funciones cliente
funciones servidor
cdigo cliente
Dr. Roberto Gmez C.
cdigo servidor
Diapo. No. 24
12
Equivalente en C
- Enumeraciones enum colores{ROJO = 0, VERDE=1, enum colores { ROJO=0, VERDE=1, AZUL=2}; AZUL=2}; typedef enum colores colores; -Booleanos Booleanos bool termino; bool_t termino; -Arreglos tamao fijo int alumnos[10];
int alumnos[10];
Diapo. No. 25
RPCL
Equivalente en C
-Arreglos tamao variable int a <12> /* a los mas 12 elementos*/ struct { u_int a_len; int *a_val; } a; int b<> /* cualquier numero de elementos */ struct { u_int b_len; int *b_val; } b; Tamao mximo = parmetro maxsize en xdr_array() No especificacin mximo => mximo valor puede tomar u_int; Solo es posible trabajar con arreglos unidimensionales -Estructuras struct punto { int x; int y; };
Dr. Roberto Gmez C.
13
-Strings No existen en C, RPCL convencin de terminacin en NULL Tamao especifica mximo nmero caracteres permitidos en string No especificado => tamao mximo = mximo valor u_int; string nombre <32> string nombresote<> -Uniones Ms cercanas al registro variante de Pascal union resultado switch (int errno){ case 0: opaque data[1024]; case 1 1: int valor; default: void }; char *nombre; char *nombresote;
struct resultado { int errno; union { char data[1024] h d t [1024] int valor; } resultado_u; }; typedef struct resultado resultado;
Diapo. No. 27
-Datos opacos Usados para describir datos que no tienen tipo Dato puede ser de tamao fijo o variable opaque diskblock[512]; opaque filedata<1024>
RPCL
Equivalente en C
-Typedef RPCL Misma sintaxis que en C Ejemplo define un fname_type usado para declarar strings de nombres de archivos que tienen una longitud mxima de 255 caracteres typedef string fname_type <255> - Identificadores Compuestos de letras, nmeros y el underscore Distincin entre mayusculas y minusculas typedef char *fname_type;
Diapo. No. 28
14
- Disear programa usando llamadas locales. p g - Restructurar cada funcin de tal forma que slo tenga un parmetro pasado por valor y asegurarse que trabaja bien localmente. - Crear un archivo de especificacin con extensin .x. - Ejecutar rpcgen con opciones -a y -C para generar archivos necesarios. - Usar el makefile generado para compilar los archivos. Es posible detectar errores en las definiciones de tipos en el archivo de especificacin. - Insertar programa que va a llamar a la funcin en el archivo _client.c generado por rpcgen. - Insertar cdigo funcin local en el archivo _server.c generado por rpcgen. - Intentar compilar los programas usando el makefile generado. - Jugar, (fiddle), con el _server.c y el _client.c hasta que trabajen. Este juego puede no ser necesario si solo se utilizan tipos simples de datos.
Diapo. No. 29
Diapo. No. 30
15
Diapo. No. 31
main(int argc, char *argv[]) { int a; int per; double sup; if (argc !=2 ) { fprintf(stderr,"Error,uso: %s a \n",argv[0]); exit(1); } a = atoi(argv[1]); per = perimetro(a); sup = area(a); printf("El perimetro del cuadrado es %d \n",per); printf("El area del cuadrado es %d \n",sup); }
Dr. Roberto Gmez C.
Diapo. No. 32
16
Cdigo del servidor local: servidor.c #include cuad.h int perimetro(int a) { int res; res = 4*a; return(res); } double area(int a) { double res; res = a*a; return(res); }
Diapo. No. 33
17
Diapo. No. 35
Compilando y ejecutando
rogomez@cuba:93>gcc cliente.c servidor.c -o cuadro rogomez@cuba:94>cuadro 5 El perimetro del cuadrado es 20 El area del cuadrado es 25 rogomez@cuba:95>cuadro 2 El perimetro del cuadrado es 8 El area del cuadrado es 4 rogomez@cuba:96>
Diapo. No. 36
18
Diapo. No. 37
/*Nombre archivo: cuadro.x */ program CUADRO_PROG { version CUADRO_VERS{ int PERIMETRO(int) = 1; double AREA(int) = 2; } = 1; } = 0x311445566;
Diapo. No. 38
19
Rango (hexadecimal) 00000000 - 1FFFFFFF 20000000 - 3FFFFFFF 40000000 - 5FFFFFFF 50000000 - 7FFFFFFF 80000000 - 9FFFFFFF A0000000 - BFFFFFFF C0000000 - DFFFFFFF E0000000 - FFFFFFFF
Diapo. No. 39
rpcgen infile rpcgen [ -a ] [ -A ] [ -b ] [ -C ] [-D name [ = value] ] [ -i size ] [ -I [ -K seconds ] ] [ -L ] [ -M ] [ -N ] [ -T ] [ -Y pathname ] infile rpcgen [ -c | -h | -m | -t | -Sc | - Ss | -Sm ] [ -o outfile ] [ infile ] rpcgen [ -s nettype ] [ -o outfile ] [ i fil ] tt tfil infile] rpcgen [ -n netid ] [ -o outfile ] [ infile ]
Diapo. No. 40
20
Opciones rpcgen
-Dnombre[=valor] -I -K segundos -L -T -s transporte -o archivo-salida -c -h -l -m -t -a -b b -C -i tamao -N -Sc -Ss -Y path
Dr. Roberto Gmez C.
Define un smbolo (igual que #define) Genera un cdigo para soporte de inted en el servidor (SunOS 4.1) Servidor existe despus de segundos de inactividad Los errores del servidor sern impresos en el syslog Genera cdigo para soportar tablas de atencin de RPC Genera el cdigo del servidor que soporta el transporte Nombre del archivo de salida Slo genera rutinas XDR Slo genera el archivo de encabezado Slo genera los stubs del cliente Slo genera los stubs del servidor Genera la tabla de atencin de RPC Genera todos los archivos Modo backward de compatibilidad (genera cdigo para SunOS4 1) SunOS4.1) Genera lenguaje C de ANSI Tamao a partir del cual se empieza a generar cdigo in-line Soporta varios argumentos y llamado por valor Genera esqueleto cliente que usa procedimientos remotos Genera esqueleto servidor que define los procedimientos remotos Nombre del directorio para encontrar pre-procesadores de C (cpp)
Diapo. No. 41
Comando a ejecutar:
$ rpcgen -C -a cuadro.x
Archivos generados: makefile.cuadro makefile para compilar el cdigo del cliente y del servidor. cuadro_clnt.c contiene el stub del cliente, el cual usualmente no es modificado. cliente modificado cuadro_svc.c contiene stub servidor cuadro.h contiene todos los tipos XDR generados a partir de la espcecificacin.
Diapo. No. 42
21
cuadro_client.c cuadro client c programa esqueleto del cliente con llamadas dummy al servicio remoto. Inserta cdigo para asignar los valores de los argumentos para el servicio remoto. cuadro_server.c contiene stubs para servicios remotos. Inserta cdigo para la versin local dentro de los stubs. cuadro_xdr.c contiene filtros XDR necesarios para los stubs del cliente y servidor.
Diapo. No. 43
cuadro_server.c archivos servidor cuadro_svc.c cuadro_xdr.c cuadro.x rpcgen cuadro.h makefile.cuadro fi cuadro_clnt.c cuadro_client.c archivos comunes
archivos cliente
Diapo. No. 44
22
Diapo. No. 45
Programa cuadro_client.c generado por rpcgen /* * This is sample code generated by rpcgen. * These are only templates and you can use them * as a guideline f id li for d developing your own f l i functions. ti */ #include "cuadro.h" void cuadro_prog_1(char *host) { CLIENT *clnt; int *result_1; int perimetro_1_arg; double *result_2; int area_1_arg;
Dr. Roberto Gmez C. Diapo. No. 46
23
#ifndef DEBUG clnt = clnt_create (host, CUADRO_PROG, CUADRO_VERS, "udp"); if (clnt == NULL) { clnt_pcreateerror (host); exit (1); } #endif # dif /* DEBUG */ result_1 = perimetro_1(&perimetro_1_arg, clnt); if (result_1 == (int *) NULL) { clnt_perror (clnt, "call failed"); } result_2 = area_1(&area_1_arg, clnt); if (result_2 == (double *) NULL) { clnt_perror (clnt, call failed ); clnt perror (clnt "call failed"); } #ifndef DEBUG clnt_destroy (clnt); #endif /* DEBUG */ }
Diapo. No. 47
int main (int argc, char *argv[]) { char *host; if (argc < 2) { printf ("usage: %s server_host\n", argv[0]); exit (1); } host = argv[1]; cuadro_prog_1 (host); exit (0); }
Diapo. No. 48
24
Versin final del programa cuadro_client.c #include "cuadro.h" int main (int argc, char *argv[]) { CLIENT *clnt; char *host; int a; int *per; double *sup; if (argc !=3 ) { fprintf(stderr,"Error, uso: %s a host \n",argv[0]); exit(1); } a = atoi(argv[1]); host = argv[2];
Dr. Roberto Gmez C. Diapo. No. 49
clnt = clnt_create (host, CUADRO_PROG, CUADRO_VERS, "udp"); if (clnt == NULL) { clnt_pcreateerror (host); exit (1); } p per = p perimetro_1(&a, clnt); ( , ); if (per == (int *) NULL) { clnt_perror (clnt, "call failed"); } sup = area_1(&a, clnt); if (sup == (double *) NULL) { clnt_perror (clnt, "call failed"); } printf("El perimetro del cuadrado es %d \n",*per); printf("El area del cuadrado es %d \n",*sup); clnt_destroy(clnt); }
Dr. Roberto Gmez C. Diapo. No. 50
25
Versin final del programa servidor #include "cuadro.h" int * perimetro_1_svc(int *argp, struct svc_req *rqstp) { static int result; result = 4* (*argp); return &result; } double * area_1_svc(int *argp, struct svc_req *rqstp) { static double result; result = (*argp) * (*argp); return &result; }
Diapo. No. 52
26
Diapo. No. 53
1. Usar makefile generado por rpcgen: rogomez@costarica:281>make -f makefile.cuadro cc g -c cuadro_clnt.c -o cuadro_clnt.o d l t d l t cc -g -c cuadro_client.c -o cuadro_client.o cc -g -o cuadro_client cuadro_clnt.o cuadro_client.o -lnsl cc -g -c cuadro_svc.c -o cuadro_svc.o cc -g -c cuadro_server.c -o cuadro_server.o cc -g -o cuadro_server cuadro_svc.o cuadro_server.o -lnsl rogomez@costarica:282> 2. Se producen dos archivos:ejecutables: cuadro_client y cuadro_server
Diapo. No. 54
27
Diapo. No. 55
Diapo. No. 56
28
/ /* * Please do not edit this file. * It was generated using rpcgen. */ #include <memory.h> /* for memset */ #include "cuadro.h" /* Default timeout can be changed using clnt_control() */ static struct timeval TIMEOUT = { 25, 0 };
Diapo. No. 57
int * perimetro_1(int *argp, CLIENT *clnt) { static int clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); if (clnt_call (clnt, PERIMETRO, (xdrproc_t) xdr_int, (caddr_t) argp, (xdrproc_t) xdr_int, (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { return (NULL); } return (&clnt_res); }
Diapo. No. 58
29
double * area_1(int *argp, CLIENT *clnt) { static double clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); if (clnt_call (clnt, AREA, (xdrproc_t) xdr_int, (caddr_t) argp, (xdrproc_t) xdr_double, (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { return (NULL); } return (&clnt_res); }
Diapo. No. 59
30
switch (rqstp->rq_proc) { case NULLPROC: (void) svc_sendreply (transp, (xdrproc_t) xdr_void, (char *)NULL); return; case PERIMETRO: _xdr_argument = (xdrproc_t) xdr_int; _xdr_result = (xdrproc_t) xdr_int; local = (char *(*)(char *, struct svc_req *)) perimetro_1_svc; break; case AREA: _xdr_argument = (xdrproc_t) xdr_int; _xdr_result = (xdrproc_t) xdr_double; local = (char *(*)(char *, struct svc_req *)) area_1_svc; break;
Dr. Roberto Gmez C. Diapo. No. 61
int main (int argc, char **argv) { register SVCXPRT *transp; : if (!svc register(transp CUADRO PROG CUADRO VERS (!svc_register(transp, CUADRO_PROG, CUADRO_VERS, cuadro_prog_1, IPPROTO_UDP)) { fprintf (stderr, "%s", "unable to register (CUADRO_PROG, CUADRO_VERS, udp)."); exit(1); } : svc_run (); fprintf (stderr, "%s", "svc_run returned"); exit (1); /* NOTREACHED */ }
Diapo. No. 62
31
Diapo. No. 63
32
Diapo. No. 65
a,b,c
b 2 4ac 2a b (b 2 4 a c ) c o m p le x = j 2a 2a res =
Diapo. No. 66
33
Diapo. No. 67
Servidor Local
#include "encabeza.h" struct raiz resuelve(a,b,c) float a,b,c; { int temp; struct raiz res; res.error=0; temp = (b*b) - (4*a*c); if (temp < 0) res.error=1; ; else { res.r1 = (-b + sqrt((double)temp)) / (2*a); res.r2 = (-b - sqrt((double)temp)) / (2*a); } return res; }
Dr. Roberto Gmez C. Diapo. No. 68
struct complex complejo(a,b,c) float a,b,c; a b c; { float temp; struct complex res; temp = (b*b) - (4*a*c); res.real = (-b)/(2*a); g ( p) ( ); res.imag = (temp)/(2*a); return(res); }
34
Cliente Local
#include "encabeza.h" main(argc, argv) int argc; char *argv[]; struct complex rescom; struct raiz result; float a,b,c; if (argc != 4) { fprintf(stderr,"Error, uso: %s a b c\n", argv[0]); [0]) exit(1); } a=(float)atoi(argv[1]); b=(float)atoi(argv[2]); c=(float)atoi(argv[3]);
Dr. Roberto Gmez C. Diapo. No. 69
result=resuelve(a,b,c); if ( ! result.error ) { printf("La solucion de (%.1f %.1f %.1f)\n",a,b,c); (% 1f % 1f % 1f)\n" a b c); printf("es %.5f y %.5f\n",result.r1, result.r2); } else { rescom=complejo(a,b,c); printf("La solucion de (%.1f %.1f %.1f)\n",a,b,c); printf("es (%.5f %.5fj) y (%.5f %.5fj)\n", rescom.real, rescom.imag, rescom.real, (-1)*rescom.imag); ( 1) rescom.imag); } }
#include <stdio.h> #include <math.h> struct raiz { float r1; float r2; int error; }; struct complex { float l fl t real; float imag; };
Diapo. No. 70
35
Compilando y ejecutando
rogomez@armagnac:156>cc cliente.c servicio.c -lm -o toto rogomez@armagnac:157>toto 1 -1 1 @ 157>t t 1 La solucion de (1.0 -1.0 1.0) es (0.50000 -1.50000j) y (0.50000 1.50000j) rogomez@armagnac:158>toto 1 9 14 La solucion de (1.0 9.0 14.0) es -2.00000 y -7.00000 rogomez@armagnac:159>toto 1 1 1 La solucion de (1.0 1.0 1.0) ( ) es (-0.50000 -1.50000j) y (-0.50000 1.50000j) rogomez@armagnac:160>toto 1 2 2 La solucion de (1.0 2.0 2.0) es (-1.00000 -2.00000j) y (-1.00000 2.00000j) rogomez@armagnac:161>
Dr. Roberto Gmez C. Diapo. No. 71
Diapo. No. 72
36
program RAIZ PROG { RAIZ_PROG version RAIZ_VERS{ struct raiz RESUELVE(datos) = 1; struct complex COMPLEJO(datos) = 2; } = 1; } = 0x31112345;
Diapo. No. 73
struct complex * l j 1 (d t * complejo_1_svc(datos *argp, struct svc_req *rqstp) { static struct complex result; /* * insert server code here */ return (&result); }
37
Servidor remoto
#include "raiz.h" struct raiz * resuelve_1_svc(datos *argp, struct svc_req *rqstp) { static struct raiz res; int temp; struct complex * complejo_1_svc(datos *argp, struct svc_req *rqstp) l j 1 (d t * t t * t ) { static struct complex res; float temp;
temp = (argp->b*argp->b) - (4*argp->a*argp->c); res.error=0; res.real = (-argp->b)/(2*argp->a); temp = (argp->b*argp->b) - (4*argp->a*argp->c); res.imag = (temp)/(2*argp->a); if (temp < 0) res.error=1; return (&res); else { } res.r1=(-argp->b + sqrt((double)temp))/ (2*argp->a); res.r2=(-argp->b - sqrt((double)temp))/(2*argp->a); } return (&res); }
Diapo. No. 75
38
#ifndef #endif }
result_1 = resuelve_1(&resuelve_1_arg, clnt); if (result_1 == (struct raiz *) NULL) { clnt_perror(clnt, "call failed"); } result_2 = complejo_1(&complejo_1_arg, clnt); if (result_2 == (struct complex *) NULL) { ( ( p ) ) clnt_perror(clnt, "call failed"); } DEBUG clnt_destroy(clnt); /* DEBUG */ main(int argc, char *argv[]) { char *host; if (argc < 2) { printf("usage: %s server_host\n", argv[0]); exit(1); } host = argv[1]; raiz_prog_1(host); }
Diapo. No. 77
Cliente remoto
if (argc !=5) { printf("uso: %s host a b c \n", argv[0]); exit(1); } host = argv[1]; data.a =(float)atoi(argv[2]); data.b =(float)atoi(argv[3]); data.c =(float)atoi(argv[4]); clnt = clnt_create(host, RAIZ_PROG, RAIZ_VERS, "netpath"); if (clnt == (CLIENT *) NULL) { clnt_pcreateerror(host); exit(1); } raices = resuelve_1(&data, clnt); if (raices == (struct raiz *) NULL) { clnt_perror(clnt, "call failed"); }
CLIENT *clnt; struct raiz *raices; datos data; struct complex *rescom; main(argc, argv) int argc; g ; char *argv[]; { char *host;
Diapo. No. 78
39
if ( ! raices->error ) { printf("La solucion de (%.1f %.1f %.1f)\n",data.a,data.b,data.c); printf("es %.5f y %.5f\n",raices->r1, raices->r2); } else { rescom = complejo_1(&data, clnt); if (rescom == (struct complex *) NULL) { clnt_perror(clnt, "call failed"); } printf("La solucion de (%.1f %.1f %.1f)\n",data.a,data.b,data.c); printf("es (%.5f %.5fj) y (%.5f %.5fj)\n",rescom->real, rescom->imag, rescom->real, (-1)*(rescom->imag)); } clnt_destroy(clnt); }
Diapo. No. 79
Compilacin
rogomez@costarica:81> make -f makefile.raiz cc -g -c raiz_clnt.c -o raiz_clnt.o cc -g -c raiz client c -o raiz client o raiz_client.c raiz_client.o cc -g -c raiz_xdr.c -o raiz_xdr.o cc -g -o raiz_client raiz_clnt.o raiz_client.o raiz_xdr.o -lnsl cc -g -c raiz_svc.c -o raiz_svc.o cc -g -c raiz_server.c -o raiz_server.o raiz_server.c: In function `resuelve_1_svc': raiz_server.c:20: warning: type mismatch in implicit declaration for built-in function `sqrt' cc -g -o raiz_server raiz_svc.o raiz_server.o raiz_xdr.o -lnsl Undefined first referenced symbol in file sqrt raiz_server.o ld: fatal: Symbol referencing errors. No output written to raiz_server make: *** [raiz_server] Error 1 [1] - Done /usr/4local/bin/xvile raiz.x rogomez@costarica:82>
Dr. Roberto Gmez C. Diapo. No. 80
40
by rpcgen
Compilando de nuevo
rogomez@costarica:82> !ma g @ make -f makefile.raiz cc -g -o raiz_server raiz_svc.o raiz_server.o raiz_xdr.o -lnsl -lm rogomez@costarica:83>
Diapo. No. 82
41
Diapo. No. 83
42