SlideShare una empresa de Scribd logo
1 de 32
Descargar para leer sin conexión
Tema            2
            La Comunicación en los
              Sistemas Distribuidos

La diferencia más importante entre un sistema distribuido y un sistema multiusuario convencio-
nal es la comunicación de procesos. En un sistema convencional, la mayoría de los mecanismos
desarrollados de alguna manera asumen la existencia de una memoria que comparten todos los
procesos. Un ejemplo típico es el del productor-consumidor, donde la comunicación se realiza
mediante un buffer almacenado en memoria común. El buffer más simple es el semáforo, que
requiere tan sólo una palabra de memoria, el semáforo mismo. En un sistema distribuido, sin
embargo, no existe en absoluto la memoria compartida, de modo que los mecanismos de
comunicación de procesos deben ser rediseñados desde el principio.

En este capitulo, discutiremos las reglas que deben observar dos computadores para comunicarse
entre sí. Estas reglas se denominan protocolos. Asumiremos que el alumno está ya familiarizado
con la pila de protocolos OSI, de modo que introduciremos ATM, un estándar de comunicación
de alta velocidad emergente que se está mostrando como el más eficaz en la construcción de
sistemas operativos distribuidos. Después examinaremos el modelo de comunicación cliente-
servidor en detalle. Examinaremos las opciones disponibles en que los procesos pueden
intercambiar mensajes. Una de estas formas es la llamada a procedimiento remoto. Este tópico
merece un apartado especial por su interés y por su amplia implantación en sistemas comerciales
actuales. El capítulo concluirá con la comunicación de más de dos procesos o grupos de
procesos.


2.1 Redes ATM
       El modelo de referencia OSI fue discutido y consensuado por empresas públicas y privadas
       de telecomunicaciones en los años setenta y fue implementado en parte en los ochenta. Los
       años noventa han alumbrado nuevos desarrollos tecnológicos en los niveles inferiores de la
       pila de protocolos OSI. Uno de ellos es ATM o modo de transferencia asícrono. Es previsible
       que esta tecnología sea adoptada en la comunicación de los sistemas distribuidos, de modo
       que es preciso un mínimo acercamiento a la misma por parte de un diseñador de sistemas dis-
       tribuidos.
UNIVERSIDAD NACIONAL DE TRUJILLO 2
                                                          ESCUELA DE INFORMATICA

      En los últimos veinticinco años, los computadores han experimentado avances en prestacio-
      nes de muchos órdenes de magnitud. Las redes no. Arpanet, la red precursora de Internet
      entró en funcionamiento en 1969 con líneas punto a punto de 56 Kbytes/s. Hoy todavía los
      usuarios finales de Internet se comunican a estas velocidades. Los nuevos desarrollos de los
      noventa proponen estándares que repentinamente saltan a velocidades de 155 Mbytes/s para
      el usuario final y a 1 Gbyte/s para el tronco principal de Internet. Este cambio de escala en
      las comunicaciones va a tener un impacto evidente en los sistemas distribuidos, donde van a
      aparecer nuevas aplicaciones que resultaban impensables hace tan sólo unos pocos años. Esta
      nueva tecnología, ATM, es la que ahora examinamos.


2.1.1 ¿Qué es el modo de transferencia asíncrono?
      A finales de los años ochenta las compañías de telecomunicaciones de todo el mundo
      comenzaron a darse cuenta de que las telecomunicaciones eran algo más que transmitir la
      voz humana en una banda de cuatro Khz. Entonces ya hacía tiempo que existían las redes
      de datos, como X.25, pero eran aún inmaduras y operaban a un máximo de 56 Kb/s o 64
      Kb/s. Sistemas como la red Internet no pasaban de ser curiosidades académicas.

      Cuando estas compañías decidieron construir redes para el siglo 21, se encontraron con
      un dilema. Por una parte, la voz requiere un ancho de banda muy bajo, pero constante.
      Por la otra, los datos de los computadores no aparecen en las líneas de comunicación de
      una forma predecible y con una tasa constante. Al contrario, son de naturaleza explosiva.
      Repentinamente surge una corriente a la que es preciso asignar un canal del mayor ancho
      de banda posible. Cuando la comunicación acaba, el ancho de banda que se precisa es
      nulo. En conclusión, ni la red telefónica de conmutación de circuitos es apropiada para
      transmitir datos ni las redes de datos de conmutación de paquetes son apropiadas para
      trasmitir la voz.

      El compromiso más razonable para atender ambos tipos de tráfico es el modelo híbrido
      ATM. ATM requiere que sea establecido un circuito virtual antes de establecer la comu-
      nicación entre el emisor y el receptor o los receptores de la comunicación. Durante el es-
      tablecimiento de la conexión, la información del encaminamiento se almacena en los no-
      dos de conmutación ATM que definen la misma. Los paquetes de los protocolos de ni-
      vel superior -TCP/IP, FILP, ...- son enviados a la tarjeta o adaptador ATM de la máquina
      donde corre el proceso de usuario, que los trocea en unidades pequeñas de tamaño fijo
      denominadas celdas. Las celdas de una conexión siguen la secuencia de nodos que se es-
      tableció al crearla. Cuando esta termina, la información relativa a la conexión es elimi-
      nada de los nodos de conmutación.

      Las ventajas de este método son evidentes. La principal es que ahora una única red es
      capaz de transportar voz, datos, radio, televisión por cable, vídeo, etc, reemplazando a la
      red de antenas y repetidores de radio y televisión, la maraña de cabes de la red telefónica,
      el nuevo cableado de la televisión por cable, el cableado de las redes de datos, etc.
      Además, permite la aparición de nuevos servicios como las videoconferencias, que serán
      accesibles desde todos los hogares con un único cable. En todos los casos, los nodos in-
      termedios de la conexión ven sólo celdas, el contenido poco importa excepto al extremo
      final.

      El hecho de que las celdas sean de tamaño fijo hace que la conmutación sea mucho más
      rápida, sin necesidad de que sean almacenadas en disco duro como los paquetes de la red
      Internet. El segundo factor que incrementa la velocidad es que los conmutadores ATM no
      realizan control de flujo ni comprobación de errores en las celdas. A este método se le
UNIVERSIDAD NACIONAL DE TRUJILLO 3
                                                            ESCUELA DE INFORMATICA

      denomina "cell relay". ATM opera estableciendo circuitos virtuales, pero un circuito sólo
      es establecido si están disponibles los recursos suficientes para garantizar la calidad del
      servicio solicitado.

      ATM tiene su propia pila de protocolo como indica la figura 2.1. A continuación vamos a
      describir brevemente los tres niveles ATM.




                                Fig. 2.1 El modelo de referencia ATM.


2.1.2 El nivel físico
         Una tarjeta adaptadora ATM se encarga de poner en el cable, sea de cobre o fibra óptica
      una corriente continua de celdas. Cuando no hay nada que transmitir, se envían celdas vacías.
      A este modo de transmisión se le llama modo nativo ATM y logra velocidades de transmisión
      superiores al Gigabit/s con fibra óptica.

      Alternativamente, las celdas ATM pueden ser enviadas como datos convencionales en los
      marcos de la red de servicios integrados de banda ancha, B-ISDN. Con este método, definido
      en el estandar CCITT I.150, se alcanza una velocidad de transmisión de 155 Mbits/s o 622
      Mbits/s.

2.1.3 El nivel ATM
          Este es el nivel que define el formato de las células y el protocolo orientado a conexión
      que las transmite. Cuando se discutían las propuestas, los comités europeo y norteamericano
      estaban enfrentados. Los americanos disponían de líneas de mayor calidad, con supresores de
      eco, lo que les permitía celdas más grandes, de 64 bits. Los europeos no disponemos de este
      tipo de líneas, de modo que celdas de 32 eran las más adecuadas. Se llegó a un compromiso
      de celdas de 48 bytes. Una celda de 48 bytes es demasiado grande para transmisión de voz y
      demasiado pequeña para transmisión de datos. Y peor aún, a la celda se le añadió un cabece-
      ro de 5 bytes. Resultaba una celda de 53 bytes que no enjaba bien en los marcos de la red B-
      ISDN. Una celda debe ser partida en dos marcos B-ISDN. A pesar de todo, el estándar ya es-
      ta elaborado y existen implementaciones hardware en funcionamiento.

      La figura 2.2 muestra el formato del cabecero de una celda ATM intercambiada entre un host
      de usuario y un conmutador ATM. Desgraciadamente, el cabecero entre dos conmutadores
      ATM es ligeramente distinto, lo que impone adaptadores distintos en hosts y conmutadores.
      La parte de datos, no obstante, es de 48 bytes en ambos tipos de celdas. Los campos VPI y
      VCI son los más importantes. VCI significa identificador de canal virtual. VPI es identifica-
      ción de ruta virtual (Virtual Path Identifier). En cada conmutador, tal y como indica la figura
      2.3, existe una tabla de encaminamiento que se establece cuando se crea la conexión. Cuando
      una celda llega a un conmutador, se examinan los campos VCI y VPI y la celda sale por el
      puerto correspondiente. Por lo tanto, los campos VCI y VPI de una celda se modifican cada
      vez que esta atraviesa un conmutador. El campo GFC significa control genérico de flujo. No
      se utiliza a falta de un acuerdo sobre cómo emplearlo. El campo CLP significa prioridad en la
UNIVERSIDAD NACIONAL DE TRUJILLO 4
                                                            ESCUELA DE INFORMATICA

     pérdida de celdas y puede utilizarse para distinguir entre unas celdas más importantes que
     otras en función de su contenido. En caso de congestión en un conmutador, este puede des-
     cartar las celdas menos importantes. El campo tipo de datos distingue entre celdas de datos y
     celdas de control y distingue entre varios tipos de celdas de control. El campo CRC -código
     de redundancia cíclica- es una comprobación sobre la cabecera completa (no los datos).




                        Fig. 2.3 Disposición de la cabecera de una celda ATM.

             La figura 2.3 muestra cómo se realiza el encaminamiento de las celdas en un conmu-
     tador en base a la tabla establecida en el establecimiento de la conexión. Los nodos de una
     red ATM son de tres tipos:


        1. Hosts, que envían y reciben mensajes.
        2. Conmutadores de rutas virtuales, que mantienen las tablas de comutación de rutas vir-
           tuales.
        3. Conmutadores de canales y rutas virtuales, que mantienen tablas de conmutación de
           canales y de rutas.




                         Fig. 2.3 Conmutando rutas virtuales en una red ATM.

     ATM proporciona un servicio de baja latencia. El retardo que introduce un conmutador es de
     alrededor de 25 microsegundos. Una ruta transcontinental de 10 conmutadores introduce un
     retraso de 250 microsegundos, un cuarto de milisegundo, en cada celda que atraviesa los diez
     conmutadores. Esto significa que la comunicación cliente servidor tendría las mismas presta-
     ciones que si se hiciese en un red de área local en un contexto de área ancha ATM.

2.1.4 El nivel de adaptación ATM
UNIVERSIDAD NACIONAL DE TRUJILLO 5
                                                            ESCUELA DE INFORMATICA

          Una celda ATM tiene 53 bytes o 53x8=424 bits. A una velocidad de transmisión de 155
       Mbps, 424 bits se transmiten en 424/(155x106)=2.74 microsegundos. Pocas UCP pueden so-
       portar interrupciones de sus adaptadores de red a una tasa de 2.74 µs, lo que impone en el
       adaptador un mecanismo para ensamblar las celdas entrantes en que se reparte el mensaje de
       usuario. Este mecanismo es el que trocea el mensaje en las celdas que salen al cable. Estos
       procedimientos de ensamblado y desensamblado constituyen el nivel de adaptación ATM.
       Están implementados en el adaptador de red y provocan una interrupción por paquete y no
       por celda.

       Una propuesta del nivel de adaptación es SEAL, que significa "Nivel de Adaptación Simple
       y Eficiente". Por su nombre, fácilmente puede adivinarse lo que pensaron sus creadores de
       las propuestas anteriores. SEAL utiliza un bit del campo de tipo de datos de la celda. Este bit
       es normalmente cero, pero es uno en la última celda de un paquete.

2.1.5 Implicaciones de ATM en los sistemas distribuidos
           La disponibilidad de líneas de comunicación con anchos de banda de 155 Mbps, 622
       Mbps y potencialmente hasta 2.5 Gbps tiene importantes implicaciones en el diseño de
       sistemas distribuidos, sobre todo en aquellos que abarcan áreas supranacionales, con
       componentes en distintos países o incluso continentes, los llamados sistemas distribuidos
       de área ancha.

2.1.5.1 Latencia
          El problema fundamental en estos sistemas es el inevitable retraso que sufre un im-
       pulso eléctrico aplicado en el extremo de un conductor en llegar al otro extremo. Este re-
       traso se denomina latencia. La electricidad se transmite en un cable de cobre a 2/3 de la
       velocidad de la luz. La luz en fibra óptica se transmite también a una velocidad que es
       2/3 de la que alcanza en el vacío. Si disponemos de una línea transcontinental de 3000
       Km, el retraso que experimenta una señal es de 3000/200000 = 15 ms. Supongamos que
       queremos enviar 1 Mb de datos por esa línea a 64 Kb/s y esperar la confirmación. Sóla-
       mente bombear a la línea el Mb lleva 1000/64 = 15.6 segundos. El retraso de propaga-
       ción del impulso eléctrico es de 0.015 * 2 = 0.03 segundos, que no es significativo frente
       a los 15.6, de modo que la distancia entre máquinas no es un factor que influya en el di-
       seño del sistema global.

       Consideremos ahora la instalación de adaptadores ATM en ambas máquinas a una velo-
       cidad de 622 Mbs. Ahora poner en la línea 1 Mb supone 1/622 = 0.0016 s. Un retardo de
       propagación de 0.03 segundos, no sólo sí es significativo frente a 0.0016 segundos que se
       emplea en sacar el fichero a la línea, sino que es 18 veces mayor. Se tarda muchísimo
       más en que el primer bit llegue al otro extremo que en poner en el cable el megabit ente-
       ro. Desde que comienza el envío hasta que vuelve la confirmación transcurren 0.0316
       segundos, de los cuales la línea está ocupada 0.0016 s y ociosa 0.03 segundos, es decir, el
       95% del tiempo. Un aumento de la velocidad de transmisión no provoca provoca más
       que un menor aprovechamiento de la línea, que se aproxima asintóticamente al 100%. La
       conclusión es que en la construcción de sistemas de distribuidos de área ancha, la laten-
       cia de las comunicaciones lleva a reconsiderar las arquitecturas y los protocolos emplea-
       dos.

2.1.5.2 Control de flujo
UNIVERSIDAD NACIONAL DE TRUJILLO 6
                                                         ESCUELA DE INFORMATICA

      Dispositivos que se comunican a 622 Mbps también plantean el problema del control de
      flujo de la comunicación. Supongamos que una máquina envía a otra, a 3000 Km, una
      cinta de video que ocupa 10 Gb. Seguramente la estación receptora no va a tener dispo-
      nible un buffer de 10 Gb, de modo que, cuando el espacio se agota, envía una celda a la
      estación emisora con el mandato STOP. La celda STOP va a tardar un mínimo de 0.015
      segundos. En ese intervalo de tiempo, han llegado a la máquina receptora 0.015 s * 622
      Mbps = 9.3 Mb, que deben ser descartados. Será necesario introducir un protocolo clási-
      co de ventana deslizante que imponga a la estación emisora el envío de 1 Mb y la espera
      de una celda de confirmación antes de enviar el segundo Mb. Ahora estamos en la situa-
      ción antes descrita, en que la ocupación de la línea no supera el 5% de tiempo. La solu-
      ción a este problema pasa por aumentar el número de Mbits de memoria RAM en los
      adaptadores de red, lo que supone un alto costo. Otra solución es la negociación de la ve-
      locidad de transmisión en bits/s en la fase del establecimiento del circuito virtual. De
      cualquier modo, el salto de 64Kbps a 622 Mbps no va suponer que las prestaciones de un
      sistema distribuido se multipliquen por 10.000 y será necesario investigar aún para sacar
      el mayor partido posible a la tecnología ATM.


2.2 El Modelo Cliente-Servidor
      El modelo de referencia OSI es aparentemente una buena herramienta para construir sis-
      temas operativos distribuidos, ya que sus protocolos garantizan que los bits que se envían
      por la red de comunicación llegan correctamente a su destino. Sin embargo, no es así.
      Por una parte, hay que considerar que la implantación de los protocolos OSI representa
      una sobrecarga muy importante en la tarea del transporte de los bits. En líneas de baja
      capacidad, como 64Kbps, la ejecución de los procesos que implementan los protocolos
      que tratan un paquete IP, por ejemplo, terminan antes de que llegue el siguiente, de modo
      de la comunicación no se ve retardada por la sobrecarga OSI. En modelos de comunica-
      ción más rápidos, como ATM, los protocolos OSI representan el cuello de botella de la
      comunicación. Es preciso tener en cuenta que la pila OSI no trata más que una pequeña
      parte del problema de la comunicación y es que los datos se transmitan entre los extre-
      mos finales correctamente, no necesariamente rápidamente. Para construir sistemas dis-
      tribuidos las prestaciones son fundamentales, de modo que al modelo OSI la hace falta
      algo más. Este algo más es la arquitectura cliente-servidor.


2.2.1 Clientes y servidores
      Un sistema operativo distribuido se puede estructurar mediante un grupo de procesos que
      cooperan. Unos prestan servicios y se denominan servidores y otros los solicitan y se
      denominan clientes. Generalmente, en el contexto de un sistema operativo distribuido,
      clientes y servidores son programas de usuario que corren en máquinas con el mismo
      microkernel. Así, una máquina puede albergar un sólo cliente o un sólo servidor o bien
      una mezcla de clientes y de servidores.

      El modelo cliente-servidor se basa en un protocolo no orientado a conexión de petición-
      réplica (Fig 2.4). Consiste en el envío de un mensaje por parte del proceso cliente al pro-
      ceso servidor. El servidor devuelve los datos requeridos o bien un indicador de error. Na-
      da más. No es necesario establecer ni liberar ninguna conexión. Supongamos que las
      máquinas son idénticas y se opera en un entorno de red local altamente fiable como et-
      hernet o token-ring. No es necesario el nivel cuatro de OSI porque los datos se transmi-
      ten sin error. No es necesaria ninguna función de encaminamiento por que el hardware se
UNIVERSIDAD NACIONAL DE TRUJILLO 7
                                                            ESCUELA DE INFORMATICA

     encarga directamente. Así, no es necesario el nivel tres de OSI. El protocolo petición-
     réplica reside en el nivel cinco de la pila OSI, que invoca directamente los servicios del
     nivel dos.




                              Fig. 2.4 El modelo de interacción cliente-servidor.


     Cuando los procesos que residen en máquinas distintas se comunican a través de una red
     local, es preciso añadir al microkernel servicios de comunicación, que presentan a los
     programas de usuario mediante llamadas al sistema. En un modelo de interacción cliente-
     servidor, estas llamadas al sistema pueden ser funciones de biblioteca como
     send(direccion, &mens) y receive(direccion, &mens). El nivel cinco
     puede ser implementado en funciones de este tipo que invocan las llamadas al sistema de
     comunicación de procesos. Estas funciones examinan los parámetros con que el usuario
     ha invocado send y receive y, finalmente, ejecutan una función de trap al sistema
     operativo. mens es una estructura de datos en espacio de direccionamiento del proceso
     de usuario. direccion es el identificador de un punto de acceso al servicio de peti-
     ción-réplica donde receive espera las peticiones o bien donde send las envía. Los
     procesos se comunican enviando datos y recibiendo datos en un punto de acceso previa-
     mente acordado. A estos puntos de acceso se les denomina comúnmente puertos.

2.2.2 Direccionamiento
     Cada punto de acceso al servicio de comunicación cliente-servidor debe tener una direc-
     ción que lo identifica en todo el sistema distribuido y lo distingue del resto. El criterio
     seguido para identificarlos de una forma global a todo el sistema distribuido, es decir,
     darles una dirección única, es el objeto de esta sección.

     En toda red de computadores cada máquina tiene una dirección que la identifica, de mo-
     do que la primera alternativa es dar al punto de acceso la dirección de la máquina en la
     red. Si sólo hay un proceso ejecutando en la máquina, cuando un mensaje llega, el kernel
     se lo envía al único proceso que existe. Ahora bien, si hay más procesos ejecutando, ¿a
     qué proceso se lo envía? Desde luego, esta no es la solución adecuada. A continuación
     vamos a examinar tres posibles aproximaciones al problema (Fig. 2.5).
UNIVERSIDAD NACIONAL DE TRUJILLO 8
                                                          ESCUELA DE INFORMATICA




           Fig 2.5 [1] direccionamiento máquina-puerto. [2] direccionamiento mediante difusión.
                         [3] direccionamiento vía un servidor de nombres.


La solución pasa por direcciones de puntos de acceso que consisten en dos partes. La primera
es la dirección de la máquina en la red y la segunda es una dirección particular en cada
máquina. Así, la máquina 245 tiene las direcciones 245@0, 245@1, etc. La pila de protoco-
los TCP/IP usa este método. La primera parte de la dirección se llama dirección IP, e identifi-
ca una máquina en la Internet. La segunda parte se llama puerto. Servicios TCP/IP bien co-
nocidos como finger o ftp utilizan siempre el mismo puerto en todas las máquinas. El
servidor de FTP, por ejemplo, recibe en el puerto 21, de modo que, conceptualmente, realiza
un equivalente a receive(@21, &mens). Un cliente FTP que accede a la máquina de
dirección IP 33.33.33.33 conceptualmente invoca send(33.33.33.33@20,
&mens). Este modo de direccionamiento, si bien es simple, está lejos de ser ideal por que
no es transparente. El cliente debe ser consciente de la máquina en que reside el servicio y la
transparencia es una de las metas en el diseño de un sistema operativo distribuido.

Una alternativa es numerar los puntos de acceso de forma global y no relativos a cada
máquina. Una posibilidad es elegirlos de forma aleatoria en un rango numérico muy grande,
por ejemplo el definido por los números enteros de 64 bits. Según este sistema, un proceso
cliente no necesita conocer direcciones de máquinas, sino sólo números de puerto de 64 bits.
Ahora bien, aunque un proceso cliente conozca la identificación del punto de acceso a un
servicio, sin importarle en qué máquina reside el servidor, los protocolos de red sí necesitan
conocer la máquina en la que se encuentra, a fin de enviar allí el mensaje. Del identificador
aleatorio de 64 bits no se deriva ninguna dirección de red, de modo que se plantea un pro-
blema que es necesario resolver.

Redes locales como ethernet soportan difusión o "broadcasting", es decir, la posiblidad de
que una máquina envíe un paquete al resto de los nodos de la red. Un cliente que conoce la
UNIVERSIDAD NACIONAL DE TRUJILLO 9
                                                           ESCUELA DE INFORMATICA

      dirección de un servicio en la red local pero no conoce la máquina en la que reside, puede
      hacer uso de la difusión para encontrarla. Este paquete, denominado paquete de localización,
      lleva el identificador de 64 bits del punto de acceso y ocasiona una réplica de la máquina que
      alberga dicho punto de acceso. Esta respuesta lleva su dirección de red. Dicha dirección es
      registrada por el kernel de la máquina solicitante en una caché a fin de evitar una nueva difu-
      sión en un segundo uso del servicio. Como es de apreciar, este esquema es transparente al
      cliente, que sólo sabe de la identificación del servicio y no de su ubicación.

      Existe una tercera solución al direccionamiento de los servicios. Consiste en que los clientes
      accedan a un servicio especificando su nombre, una cadena ascii. Es necesario incorporar a la
      red un servidor de nombres, que almacena pares (Nombre, XXX@YYY). Con este esquema,
      un cliente, antes de acceder a un servicio debe realizar una consulta al servidor de nombres.
      Cada una de las tres soluciones tiene sus inconvenientes. La primera no es transparente, la
      segunda añade sobrecarga en el sistema y la tercera requiere un componente centralizado,
      que no escala adecuadamente.

2.2.3 Primitivas con bloqueo y sin bloqueo
      Las primitivas send y receive pueden ser diseñadas como bloqueantes o síncronas y no
      bloqueantes o asíncronas. A veces, ambas opciones, con bloqueo y sin bloqueo, están dispo-
      nibles para el usuario.

      Si send es bloqueante, significa que, tras ser invocada por un proceso de usuario, este es
      suspendido hasta que el mensaje ha sido enviado. Enviado puede significar dos cosas sutil-
      mente distintas y que es preciso aclarar en cada contexto. Unos autores, sobre todo los impli-
      cados en construcción de sistemas operativos, entienden por "enviado" como aquel mensaje
      que ha sido copiado al kernel para su envío o que ha sido puesto directamente en la línea de
      comunicación. Lo importante, consideran ellos, es que el buffer del mensaje saliente quede
      libre de nuevo. Lo de menos es que el mensaje haya sido recibido. Otros autores, sobre todos
      los involucrados en la construcción de lenguajes, argumentan que un mensaje puede conside-
      rarse como enviado cuando ha llegado a su destino, es decir, cuando el kernel de la máquina
      destino ha replicado al kernel de la máquina remitente con un mensaje de reconocimiento. En
      lo que ambos están de acuerdo es que si la primitiva send retorna cuando se confirma la re-
      cepción del mensaje, esta semántica es síncrona. También todos están de acuerdo en que si
      send retorna antes de que el mensaje haya sido copiado al núcleo o enviado por la línea, es-
      tamos ante una primitiva asíncrona.

      Si receive es bloqueante, el proceso que la invoca es suspendido mientras el mensaje no
      haya sido recibido. Si receive es no bloqueante, el proceso que la invoca no se suspende
      en ella. Al cabo de algún tiempo que el proceso considere oportuno, acudirá al buffer a reco-
      ger el mensaje solicitado con la esperanza de que haya llegado o bien con la información de
      que efectivamente así ha ocurrido.

      La ventaja de las llamadas no bloqueantes reside que el proceso de usuario invocante puede
      seguir ejecutando concurrentemente con la transmisión del mensaje. La ventaja del aumento
      de prestaciones de las llamadas no bloqueantes se ve superada, no obstante por una desventa-
      ja muy seria: el emisor de send(direccion, &mens) no puede modificar el buffer
      mens hasta que este haya sido enviado y, lo que es peor, en principio no conoce cuándo el
      envío se produce, de modo que no puede volver a reutilizarlo para enviar o recibir un nuevo
      mensaje. A este problema se le pueden aplicar dos soluciones:

      1. La primera es que el kernel copie el contenido del mensaje a un buffer interno y desde allí
         lo envíe. Ahora el proceso de usuario puede reutilizar el buffer y send se comporta como
UNIVERSIDAD NACIONAL DE TRUJILLO 10
                                                          ESCUELA DE INFORMATICA

         en modo síncrono. La desventaja de esta solución es que el kernel debe copiar el mensaje
         al adaptador de comunicaciones cuando este esté libre para transmitir. Son necesarias dos
         copias, una de espacio de usuario al kernel y otra del kernel al dispositivo de E/S. Cuando
         el mensaje es grande y los envíos numerosos, esta solución puede degradar notablemente
         las prestaciones del sistema.

      2. La segunda solución es interrumpir al emisor cuando el mensaje ha sido enviado. Enton-
         ces el proceso entiende que ya puede modificar el buffer. Esta es una opción que, si bien
         ahorra tiempo, hace muy complicada la programación de aplicaciones de usuario y, debi-
         do a la aparición de las condiciones de carrera, hace muy difícil de depurar este tipo de
         programas. Por lo tanto, las desventajas superan ampliamente a las ventajas. El utilizar
         primitivas síncronas parece la opción más adecuada. No maximiza el paralelismo, pero es
         fácil de comprender y de programar. Las mismas consideraciones que hemos hecho sobre
         send se aplican a receive.

      En el diseño de las primitivas de comunicación puede considerarse la introducción de plazos.
      Tras invocar send, el kernel desbloquea el proceso cuando recibe el reconocimiento de que
      el mensaje ha llegado a su destino. Si este no llega, el proceso quedará bloqueado indefini-
      damente. Algunos sistemas proporcionan primitivas con un parámetro de temporización. Si
      el mensaje no ha sido enviado o recibido en el plazo especificado, la llamada vuelve con
      error.

2.2.4 Primitivas con buffer y sin buffer
      Una llamada receive(direccion, &mens) indica al kernel que el próximo mensaje
      entrante dirigido al punto de acceso direccion se copie en el buffer mens del espacio
      de direccionamiento del proceso que la invoca. Esta primitiva se conoce como sin buffer
      porque el kernel no almacena el mensaje entrante antes de entregarlo a la aplicación. Funcio-
      na correctamente cuando receive se invoca antes de que llegue el mensaje a la dirección
      especificada. En contraste, cuando el mensaje llega antes de que se produzca la llamada re-
      ceive, el kernel no sabe a quién entregar el mensaje y, como no dispone de espacio para
      almacenarlo, simplemente lo descarta, enviando al kernel del emisor un código de error. En
      la aplicación que envía, send retorna con error y siempre puede volver a hacer un reintento.
      Cuando la aplicación que envía considera que el número de reintentos execede un límite, re-
      nuncia a seguir, presumiendo que el servidor no está ejecutando, cuando tal vez esté sirvien-
      do un mensaje que simplemente exige más tiempo que el habitual.

      El problema se palía disponiendo un buffer en el kernel para cada punto de acceso. A este
      buffer se le suele llamar buzón. Las primitivas con buzones asociados se denominan "con
      buffer". La solución no es completa, sin embargo. El buzón tiene capacidad finita, de modo
      que cuando se llena volvemos a la situación de la primitiva sin buffer, donde los mensajes
      son descartados.

2.2.5 Primitivas fiables y no fiables
      Hasta aquí hemos asumido tácitamente que, cuando se envía un mensaje, el kernel del recep-
      tor lo recibe. Sin embargo, los mensajes en ocasiones se pierden en las líneas de comunica-
      ción. Vamos a considerar tres estrategias ante el problema. La primera es reconsiderar la
      semántica de send en el programa de usuario como no fiable. Implementar una comunica-
      ción fiable se deja en manos del usuario. Al fin y al cabo, el correo convencional funciona
      así. Una carta se deja en el buzón y el servicio de correos pone todo de su parte, pero no ga-
      rantiza que la carta va a llegar a su destino. Las primitivas fiables se implementan mediante
      mensajes de confirmación, que a continuación examinamos. Así, la segunda aproximación se
UNIVERSIDAD NACIONAL DE TRUJILLO 11
                                                           ESCUELA DE INFORMATICA

     basa en que el kernel de la máquina receptora envíe un mensaje de confirmación al kernel de
     la máquina emisora. El programa de usuario que invoca send queda suspendido hasta que
     este mensaje se recibe. La réplica del servidor al cliente también va acompañada de este tipo
     de confirmación (Fig 2.6, izq.), de modo que el servidor queda bloqueado en send hasta que
     la confirmación se produce. La tercera vía es sacar partido a que la interacción cliente-
     servidor está diseñada como una réplica del servidor al cliente que siempre sigue a la solici-
     tud de este último. En la figura 2.6, izq. vemos que el servidor envía los mensajes 2 y 3 al
     cliente, el 2 para confirmar la llegada de la petición y 3 lleva la réplica. Podemos prescindir
     de la confirmación 2 que modo que ésta venga dada implícitamente por la réplica 3 (Fig. 2.6,
     der.). El cliente queda ahora suspendido en send hasta que se llegue la réplica del servidor,
     que se confirma con el mensaje 4.




                       Fig. 2.6 Izq. Mensajes de usuario individualmente reconocidos.



2.3 Llamada a procedimiento remoto (RPC)
     En el anterior epígrafe hemos estudiado un modelo de interacción entre los procesos de un
     sistema distribuido que es el modelo cliente-servidor. Para implementarlo, el sistema dispone
     de dos llamadas al sistema, send y receive, que las aplicaciones utilizan de forma con-
     veniente. Estas primitivas, a pesar de constituir la base de la construcción de los sistemas dis-
     tribuidos, pertenecen a un nivel demasiado bajo como para programar de forma eficiente
     aplicaciones distribuidas.

2.3.1 La operación RPC básica
UNIVERSIDAD NACIONAL DE TRUJILLO 12
                                                      ESCUELA DE INFORMATICA

La llamada a procedimiento remoto constituye un mecanismo que integra el concepto clien-
te-servidor con la programación convencional basada en llamadas a procedimientos. La idea
surgió en 1984 y consiste en que el cliente se comunica con el servidor mediante una llama-
da ordinaria a un procedimiento. Esta llamada se denomina a procedimiento remoto porque
el procedimiento invocado se encuentra en otro espacio de direccionamiento, en la misma o
en distinta máquina que el cliente. La información se transporta en los parámetros de la lla-
mada y el resultado es devuelto en el retorno de la llamada. El cliente no tiene que utilizar las
primitivas send y receive como en el modelo cliente-servidor puro, de modo que la pro-
gramación de aplicaciones distribuidas se hace más sencilla.

La figura 2.7 muestra un ejemplo del uso de RPC. El cliente necesita de un servicio que es la
suma de dos enteros. El servicio se invoca mediante a una llamada a función tal y como se
hace en un programa convencional escrito en C. La única diferencia es que la función se eje-
cuta en una máquina diferente de una forma completamente transparente al usuario.




                           Fig. 2.7 Computando una suma de forma remota.

La función suma(2, 3); de la figura se implementa en el cliente como una rutina de bi-
blioteca que se denomina el cabo o "stub" cliente. Recordemos cómo se implementan las
llamadas al sistema en un lenguaje como C en un sistema operativo centralizado. Estas aca-
ban almacenando los parámetros de la llamada en los registros de la UCP y ejecutando una
instrucción de trap al sistema operativo. En un sistema distribuido las cosas son básicamente
iguales. La función suma contiene una llamada al sistema send seguida de una llamada
receive, donde el programa cliente que invoca suma(2, 3); es suspendido hasta que
llega la respuesta del servidor, según el modelo de interacción cliente-servidor. Como pode-
mos ver, el mecanismo RPC no es sino el modelo cliente-servidor, pero con una interfaz más
sencilla que hace que el cliente invoque al servicio por su nombre y sin necesidad de gestio-
nar números de puerto.

En cuanto al servidor, el cabo no es una función como era suma en el cliente, sino que es el
programa principal. El programador del servicio sólo se ocupa del procedimiento que invoca
el cliente. Las llamadas de receive y send en el servidor son ejecutadas por el cabo,
que recibe el mensaje, determina el procedimiento solicitado -suma en este caso- y, finalmen-
te, lo invoca. Todos los pasos implicados son los siguientes:

     1. El cliente llama al cabo cliente en la manera convencional.
     2. El cabo cliente construye un mensaje empaquetando los parámetros del procedi-
        miento y salta al kernel mediante un trap.
     3. El kernel local envía el mensaje al kernel remoto.
     4. El kernel remoto entrega el mensaje al cabo servidor.
     5. El cabo servidor desempaqueta los parámetros y llama al procedimiento de servicio.
UNIVERSIDAD NACIONAL DE TRUJILLO 13
                                                           ESCUELA DE INFORMATICA

          6.   El procedimiento de servicio hace el trabajo y devuelve el resultado.
          7.   El cabo servidor empaqueta el resultado y salta al kernel mediante un trap.
          8.   El kernel remoto envía el mensaje al kernel local.
          9.   El kernel local envía el mensaje al cabo del cliente, ahora suspendido esperándolo.
         10.   El cabo local desempaqueta el resultado y lo devuelve al cliente.


2.3.2 El paso de parámetros
         La función del cabo cliente es empaquetar los parámetros en un mensaje y enviarlo al ca-
     bo servidor. Este examina el código del procedimiento en una sentencia tipo switch e invoca
     el procedimiento de forma local. El resultado es de nuevo empaquetado en un mensaje y en-
     viado al cabo cliente. Esta interacción, que parece directa, no es tan simple como aparenta
     ser. Mientras las arquitecturas del cliente y del servidor sean iguales no se presenta ningún
     problema especial. En un entorno distribuido, sin embargo, cada arquitectura tiene su propia
     representación de números, caracteres, etc. Por ejemplo, los mainframe IBM utilizan el códi-
     go EBCDIC para los caracteres en lugar del código ASCII, como el IBM PC. Problemas si-
     milares ocurren con la representación de coma flotante o los enteros negativos (complemento
     a 1 o complemento a 2).

     Otro problema surge con la forma de almacenar un entero. La arquitectura PC mantiene una
     representación "little endian", a saber, el byte menos significativo en el byte más bajo de
     memoria. La arquitectura SPARC utiliza un almacenamiento "big endian", es decir, el byte
     más significativo en el byte más bajo de la memoria. Un 486 operando en modo protegido
     representa un entero con cuatro bytes, de modo que el 5 lo representa como 0005. Suponga-
     mos que es el primer parámetro de la llamada a procedimiento suma de la Fig. 2.7 y que el
     servidor ejecuta en una estación SPARC. Los bytes se envían a la red siguiendo su posición
     en la memoria, de modo que circulará por ella la secuencia de bits del cinco, luego la del cero
     tres veces. Según llegan los bytes se van almacenando en el buffer del mensaje comenzando
     por el byte más bajo, de modo que en la memoria de la máquina servidora tenemos llos cua-
     tro bytes almacenados de la misma forma que en la memoria del 486, es decir, 0005, el 5 en
     el byte más bajo. Sin embargo, para la UCP SPARC, este número no es el cinco, sino 5*2563,
     casi 84 millones. Por lo tanto, es preciso realizar una convesión en la máquina SPARC antes
     de entregar los parámetros al procecimiento de servicio. Nótese, no obstante, que si es otra
     máquina SPARC la que envía el entero 5, no es necesario realizar la conversión.

     Una forma de solucionar todos estos problemas de representación es convertir los datos a una
     forma canónica antes de ser enviados a la red. Cuando los parámetros llegan a su destino, por
     ejemplo, es preciso reconvertir el formato canónico al de la arquitectura del servidor. El pro-
     blema de este método es que es ineficiente en interacciones entre máquinas de igual arquitec-
     tura, de modo que otra aproximación al problema es incorporar en el mensaje un primer byte
     que identifique la arquitectura del emisor. Si es la misma que la del receptor, no es necesaria
     conversión alguna.

     El problema más difícil de tratar en las llamadas a procedimiento remoto es el paso de punte-
     ros, ya que estos sólo tienen sentido en un espacio de direccionamiento dado. Un entero pa-
     sado a una rutina de servicio tiene un significado pleno, pero un puntero es simplemente una
     referencia inútil. No obstante, el paso de punteros en las aplicaciones de usuario es tan
     común que el prescindir de ellos en las llamadas a rutinas remotas haría perder al concepto
     de RPC gran parte de su atractivo. Afortunadamente, el problema puede abordarse. En el
     lenguaje C, por ejemplo, están disponibles dos formas de pasar parámetros. Los enteros y ca-
     racteres se pasan por valor. Esto significa que, al invocar un procedimiento con un parámetro
     que es un entero, se hace una copia del entero en la pila. La rutina invocada trabaja con esta
     copia. La variable original no se toca. Los vectores, sin embargo, se pasan por referencia.
UNIVERSIDAD NACIONAL DE TRUJILLO 14
                                                           ESCUELA DE INFORMATICA

      Ello significa que no se copia en la pila el vector completo en la llamada, sino sólo su direc-
      ción. El programador de la rutina que recibe la referencia es consciente de que trabaja con un
      puntero al vector original, que es realmente modificado en la rutina. En Pascal, por defecto,
      todas las variables se pasan por valor. El paso por referencia es controlado por el programa-
      dor añadiendo el modificador var a la definición del parámetro que se pasa por referencia en
      la declaración de la rutina.

      Un mecanismo adicional de paso de parámetros es denominado de copia-restauración. Con-
      siste en realizar una copia del parámetro en la pila. Si esta copia parámetro es modificada en
      el procedimiento, se restaura su nuevo valor a la variable original. Algunos compiladores de
      Ada utilizan este mecanismo en parámetros in out, si bien ello no está especificado en la de-
      finición del lenguaje. La estrategia de copia con restauración puede ser utilizada para pasar
      punteros a procedimientos remotos. Supongamos la invocación del procedimiento remoto

              cuenta = read(df, buf, nbytes);

      La implementación más directa consiste en copiar al buffer del mensaje local un vector de
      "nbytes" caracteres en lugar de buf, que es la referencia al vector. El mensaje es entonces en-
      viado al cabo servidor. Ahora el buffer del mensaje se encuentra en el espacio de direcciona-
      miento de este último, invocará la rutina de servicio read con la referencia al vector recibi-
      do en el mensaje, es decir de forma convencional por referencia. Ahora el mensaje es devuel-
      to con su contenido actualizado a la rutina cabo del cliente, que restaura el vector del mensa-
      je a su vector original. Para optimizar este mecanismo eludimos en el cabo cliente la copia
      del vector al mensaje en caso de lectura. En el caso de la escritura, prescindiremos de restau-
      rarlo. Como vemos, es posible pasar punteros a procedimientos remotos siempre que sean re-
      ferencias a estructuras sencillas como vectores. No obstante, no podemos enviar a procedi-
      mientos remotos referencias a estructuras de datos complejas como listas o árboles.

2.3.3 Especificación de interface
      El servidor RPC puede ser considerado como un módulo u objeto que implementa unas
      operaciones sobre datos ocultos. El servidor de a conocer estas operaciones a los clientes
      mediante lo que se denomina su interface, constituida por las declaraciones de los méto-
      dos que soporta.

      Como sabemos, el objetivo del mecanismo RPC es lograr que un programa tenga acceso
      a los servicios de uno de estos módulos, aunque residan en otro espacio de direcciona-
      miento, posiblemente remoto. La figura 2.8 muestra los componentes de una implemen-
      tación RPC. La mitad rayada constituye el software adicional de empaquetamiento y
      desempaquetamiento de parámetros y primitivas de comunicación que debe ser ocultado
      al programador. Por brillante que sea la idea de la interacción cliente-servidor a través de
      RPC, si el programador debe encarar la construcción de los cabos, el progreso de los sis-
      temas distribuidos se verá comprometido por la falta de uso en la práctica. Es preciso que
      la generación de cabos en el cliente y el servidor se realize de forma automática. Pues
      bien, la interfaz del servidor se utiliza como la base de esta generación automática de ca-
      bos.

      El primer paso es definir el interfaz, es decir, el conjunto de los prototipos de los proce-
      dimientos de servicio, mediante un lenguaje determinado, denominado lenguaje de inter-
      face. La figura 2.8, a) muestra un ejemplo de servidor. La figura 2.8, b) su definición de
      interfaz. Un compilador especial toma como entrada el fichero escrito en el lenguaje de
      interface y como salida genera el código objeto de los procedimientos que constituyen el
      cabo cliente, por una parte, y el cabo servidor, por la otra. El programa cliente se enlaza
UNIVERSIDAD NACIONAL DE TRUJILLO 15
                                                         ESCUELA DE INFORMATICA

con estos procedimientos objeto para generar el ejecutable. En cuanto al servidor, los
procedimientos de servicio, escritos por el programador, se compilan previamente a len-
guaje objeto y, a continuación, se enlazan con los procedimientos cabo, entre los que fi-
gura el procedimiento principal del servidor RPC.
      #include <header.h>
      void main(void)
      {
        struct mensaje m1, m2; /* Mensajes entrante y saliente */
        int r;

        while(1)
        {
           receive(FILE_SERVER, &m1); /* El servidor se bloquea esperando un mensaje
      */
           switch(m1.opcode)
           {
              case CREATE:     r = do_create(&m1, &m2); break;
              case READ:       r = do_read(&m1, &m2); break;
              case WRITE:      r = do_write(&m1, &m2); break;
              case DELETE:     r = do_delete(&m1, &m2); break;
              case DELETE:     r = E_BAD_OP; break;
           }
           m2.result = r;
           send(m1.source, &m2);
        }
      }
                 a)

      #include <header.h>
      specification of file_server, version 3.1
       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;
               b)
                      Fig. 2.8 Ejemplo de un servidor y su definición de interface.


Una de las implementaciones RPC más populares es Sun RPC, desarrollada por Sun Micro-
systems. Supongamos que deseamos un servidor de tiempo que proporcione dos servicios.
Uno, invocado por la función bin_date_1 que devuelve el número de segundos transcu-
rridos desde las cero horas del 1 de enero de 1970. Otro, invocado por la función
str_date_2. Esta función toma un parámetro, que es un número de segundos transcurri-
dos desde el instante antes citado, y devuelve la hora y la fecha en una cadena de caracteres.
La figura 2.9 describe los pasos implicados en la creación de los procesos servidor y cliente a
partir de la especificación de interfaz en el sistema Sun RPC.
UNIVERSIDAD NACIONAL DE TRUJILLO 16
                                                         ESCUELA DE INFORMATICA




                                           Fig. 2.9 Sun RPC


2.3.4 Enlace dinámico
        No es conveniente que un servicio esté ligado a una máquina. A veces las máquinas
     no están operativas, de modo que los servicios se mueven a otra máquina. El cliente está
     interesado en el servicio, no en qué máquina ejecuta el servidor. Para solicitar un servi-
     cio, un cliente podría enviar un mensaje en una sentencia como la siguiente
             send(33.33.33.33@20, &mens);
     en el código fuente que implementa la llamada RPC. Esta solución es inflexible, puesto
     que, si dentro de la máquina 33.33.33.33 el servidor pasa a escuchar en otro puerto
     distinto del 20, el cliente debe ser recompilado. Lo mismo ocurre si el servidor cambia de
     máquina.

     En contraste, el cliente debería invocar el servicio por su nombre, sin hacer referencia a
     dirección alguna. La figura 2.8 b) muestra la especificación formal del servidor de fiche-
     ros 2.8 a). En la especificación formal del servidor intervienen el nombre del servidor y
     su número de versión. Ambos datos identifican un servidor. Un servidor con el mismo
     nombre y la misma versión, no obstante, pueden estar replicados en dos o más máquinas
     a fin de mejorar el servicio o proporcionar tolerancia a fallos. El cliente debe solicitar un
     servicio invocando su nombre y versión, sin citar dirección alguna. El número de versión
     es conveniente a fin de que un servidor que evoluciona conserve su nombre. Un servidor
     puede evolucionar ofertando nuevos servicios, cancelando otros y modificando otros. A
     pesar de esta evolución, es preciso que clientes antiguos, desconocedores de los cambios,
     sigan obteniendo el mismo tipo de servicio. Es preciso comprender, no obstante, que un
     servidor con el mismo nombre pero con número de versión distinto es un servidor dife-
     rente.

     Las ventajas de identificar al servidor por su nombre son evidentes, pero, ¿cómo el clien-
     te localiza al servidor? ¿Quién le proporciona su dirección? Este es un problema al que
     algunos sistemas RPC, entre ellos Sun RPC, dan respuesta mediante lo que se llama el
     enlace dinámico, que no es sino averiguar la dirección del servidor en tiempo de ejecu-
     ción. El enlace dinámico está basado en un tercer proceso denomindado el enlazador.
     Cuando el servidor arranca, en su código de inicialización previo al bucle principal, en-
     vía un mensaje al enlazador a fin de registrarse como un proceso que presta un servicio.
     El enlazador es, al fin y al cabo, un registrador de servicios, un servidor de nombres. El
UNIVERSIDAD NACIONAL DE TRUJILLO 17
                                                            ESCUELA DE INFORMATICA

       servidor entrega su nombre, su número de versión y su dirección. Se dice que el servidor
       exporta su interfaz. No sería extraño que dos programadores diesen el mismo nombre a
       dos servidores distintos, de modo que, a pesar de que no aparezca en la figura 2.9 b), ca-
       da servidor RPC tiene asociado, además del nombre y la versión, un identificador numé-
       rico, generalmente de 32 bits, que también entrega en la operación de registro. Dos ser-
       vidores distintos deben tener identificadores distintos (se entiende aquí servidor como
       programa, no como proceso). Si bien sería raro, es posible que dos programadores que
       terminan dos servidores RPC, coincidan en darles el mismo identificador. Lo que ocurra
       cuando ambos traten de registrarse depende de cada implementación particular del soft-
       ware RPC, pero es lógico pensar que el enlazador rechazaría la segunda petición de re-
       gistro.

       Supongamos que un cliente invoca el procedimiento remoto read de la figura 2.8 b). El
       cabo del cliente percibe que aún no dispone de la dirección del servidor, de manera que
       envía un mensaje al enlazador solicitando la dirección de un servidor cuyo nombre y ver-
       sión el cliente proporciona en los campos del mensaje. El enlazador busca en sus tablas
       tal servidor y, si está registrado, proporciona su dirección al cliente en el mensaje de
       réplica. La principal ventaja del enlace dinámico es que el servidor puede estar en cual-
       quier máquina. Incluso puede haber varios servidores. En enlazador proporciona al clien-
       te la dirección del servidor menos sobrecargado, más cercano, etc. Una desventaja es el
       tiempo que lleva el registro del servidor y la solicitud del cliente. Muchos procesos clien-
       te sólo hacen una llamada a procecimiento remoto. Por otra parte el enlazador puede lle-
       gar a ser una máquina muy solicitada, hasta el punto de necesitar varios enlazadores re-
       plicados. Mantener la consistencia de los mismos conlleva más tráfico en el sistema.

2.3.5 Semántica RPC en presencia de fallos
      El objetivo de la llamada a procedimiento remoto es conseguir la ejecución de procedi-
  mientos en otras máquinas sin cambiar la forma en que se invoca el procedimiento en el
  código fuente. Salvo algunas excepciones como que un procedimiento remoto no puede usar
  variables globales, el objetivo ha sido alcanzado plenamente. Mientras no se produzcan
  errores la transparencia de la llamada remota está conseguida, ya que el programador no
  necesita saber que la llamada que realiza es a un procedimiento remoto. Los problemas llegan
  cuando bien cliente o bien servidor dejan de operar correcatamente, ya que las diferencias
  entre llamadas locales y remotas no son fáciles de enmascarar. Vamos a considerar cinco
  situaciones de fallo:
      1.   El cliente no es capaz de localizar al servidor.
      2.   El mensaje del cliente al servidor se pierde.
      3.   El mensaje de réplica de servidor a cliente se pierde.
      4.   El servidor se cae tras recibir el mensaje del cliente.
      5.   El cliente se cae tras recibir la réplica.

  El cliente no puede localizar al servidor
  Puede haber varias causas. Una es que el servidor se cae. Otra es que el servidor se actualiza y
  un cliente antiguo invoca una versión del servidor que ya no ejecuta. Una solución es que la
  llamada devuelva -1 como código de error. Sin embargo, -1 puede ser un resultado válido
  como en la llamada RPC de suma de la figura 2.7. Otro intento de solución es escirbir un
  manejador de excepción (señales en C) para los errores producidos en las llamadas RPC. Sin
  embargo, esta solución acaba con la transparencia respecto a las llamadas locales. Lo mejor es
  recibir el resultado en parámetros de salida de la llamada RPC y que esta devuelva 0 en caso
  de ejecución con éxito y un código de error en otro caso.
UNIVERSIDAD NACIONAL DE TRUJILLO 18
                                                         ESCUELA DE INFORMATICA


La petición del cliente se pierde
Este caso tiene un tratamiento sencillo. El núcleo del cliente arranca un temporizador cuando
envía el mensaje al servidor. Si al cabo de un plazo no ha llegado réplica o reconocimiento del
servidor, el cliente da el mensaje por perdido y lo reenvía. Si todos los reenvíos se pierden, el
kernel del cliente considera que el servidor no está activo y devuelve un error al cabo cliente,
que lo pasa a la aplicación. Estamos en el caso anterior.

La réplica del servidor se pierde
Este problema es más complejo. Cuando en el caso anterior venció el plazo sin que llegase la
respuesta del servidor, asumimos que se había perdido el mensaje enviado por el cliente. Pero
existe la posibilidad de que el mensaje perdido fuese la réplica. De cualquier forma, estable-
cimos que lo que había que hacer era el reenvío del mensaje. En el primer caso, el servidor
recibe el mensaje reenviado por primera vez. Todo vuelve a funcionar correctamente. En el
segundo caso el servidor recibe el mensaje por segunda vez. Sirve la petición dos veces, como
si en el programa cliente hubiésemos invocado la llamada una segunda vez. En algunos casos,
la repetición de una operación en el servidor no causa ningún daño. Por ejemplo, el leer los 20
primeros bytes de un fichero. Las peticiones que tienen esta propiedad se dicen que son
idempotentes. Otras veces, la re-petición sí ocasiona perjuicios, como puede ser el añadir 20
bytes a ese fichero o retirar de una cuenta bancaria 500 millones de pesetas. La solución a este
problema pasa por numerar las peticiones. Las retransmisiones llevan el mismo número de
secuencia que la transmisión original. Entonces el kernel del servidor detecta que la réplica se
ha perdido y la reenvía, sin operar sobre el servidor. Una versión distinta de esta solución es
introducir en la cabecera de la petición un bit de retransmisión.

El servidor se cae
La figura 2.10 a) muestra la secuencia de eventos producidos en un servidor en el servicio de
una petición. El sistema operativo del servidor recibe el paquete entrante con el mensaje, que
entrega al cabo para que invoque la ejecución del procedimiento que sirve la petición. A
continuación, el cabo pasa la réplica al sistema operativo que lo envía en un paquete al cliente.
Ahora bien, tras haberse ejecutado el procedimiento de servicio, el servidor puede sufrir una
caída que impide la emisión de la réplica al cliente. Es el caso b) de la figura. Por el contrario,
la caída puede producirse tras la recepción del paquete, pero previamente a la ejecución del
procedimiento de servicio. Es el caso c).

Las consecuencias de los casos b) y c) es diferente. Supongamos que la operación remota es
escribir un texto en la impresora. El servidor primero carga el texto en la memoria interna de
la impresora y después escribe en un registro de la misma para iniciar la impresión. El servi-
dor puede caerse antes de establecer el bit o después de establecer el bit. En el primer caso, la
operación no será realizada. En el segundo caso, sí, ya que la impresora continúa su trabajo
con independencia de que el servidor esté activo o no lo esté.

Podemos pensar que este caso tiene la misma complejidad que la pérdida de la réplica, exami-
nada en el caso anterior. No es así. La pérdida de la réplica supone un reenvío de la solicitud
de impresión. El núcleo del servidor se dará cuenta de que el mensaje tiene un número de
secuencia repetido y enviará de nuevo la réplica si repetir la impresión. En contraste, la caída
del servidor supone la pérdida del registro de los números de secuencia de mensajes del
cliente. Por esta razón, tras un rearranque, el servidor no puede saber si la re-petición de
impresión ha sido servida con anterioridad, de modo que volverá a ser servida. Si la caída se
produjo en el caso c) la impresión no se hizo, de modo que reiniciar la operación es lo correc-
to. Sin embargo, si la caída se produjo en el caso b) reiniciar la operación supone repetirla. Lo
UNIVERSIDAD NACIONAL DE TRUJILLO 19
                                                                     ESCUELA DE INFORMATICA

peor del caso b) es que ni cliente ni servidor sabrán nunca si la operación se realizó con
anterioridad o no.




Fig. 2.10 Caída del servidor. a) Operación correcta. b) Caída tras servir el mensaje c) Caída antes de servir el mensaje.

La discusión anterior viene a decir, en esencia, que la ejecución de un procedimiento remoto
está envuelta en un factor de incertidumbre que hay que asumir a la hora de programar una
aplicación distribuida. Para reducir este factor aleatorio, los implementadores de un sistema
RPC toman una de estas tres aproximaciones en cuanto a la semántica de la llamada RPC. La
primera se denomina semántica de "al menos una vez". Esta filosofía de implementación de
un software RPC garantiza a la aplicación cliente que el procedimiento remoto va a ejecutarse
al menos una vez, pero posiblemente más. Mientras el servidor de figura 2.10 está caído, el
cliente no cesa de enviarle nuevas solicitudes de impresión. Llega un momento en que el
servidor rearranca y su decisión es ejecutar la petición. Ante el caso b) de la figura 2.10, el
servidor está repitiendo la operación. En el caso c) no la repite. De cualquier forma, este
mecanismo garantiza la impresión al menos una vez.

La segunda aproximación se denomina semántica de "como máximo una vez". A la aplicación
cliente no se le garantiza que la llamada se ejecute. Tras el rearranque, el servidor RPC puede
tomar la decisión de ignorar las peticiones entrantes y de enviar un mensaje de aviso al cliente
informándole de la caída, para que este tome las medidas oportunas. La llamada devolverá un
código de error parecido a "rearranque de servidor". El cliente tendrá garantizado que el
procedimiento no se ha ejecutado más de una vez. Lo que nunca sabrá es si se ejecutó alguna
vez. Otra aproximación que puede tomar el cliente, si la caída se prolonga, es renunciar tras
un número de reintentos determinado. También en este caso, desconoce si el procedimiento se
ejecutó.

La tercera filosofía que puede adoptar el software RPC es no garantizar nada a la aplicación
de usuario. Si el servidor se cae, tras el rearranque, informa de la caída y sigue ejecutando
peticiones como si nada hubiese ocurrido. El procedimiento puede no haberse ejecutado o
puede haberse ejecutado una o más veces. La ventaja de esta semántica es que es fácil de
implementar.

El cliente se cae
Puede ocurrir que un cliente haya invocado una llamada RPC y, antes de que la respuesta
llegue, el cliente se cae. La operación que se realiza en el servidor no se hace ahora en benefi-
cio de nadie y se dice que ha quedado huérfana. Las operaciones huérfanas son un problema.
Cuando el cliente rearranca, puede eliminar las operaciones iniciadas mediante un mensaje
especial. Esta solución se denomina exterminación de huérfanos. Esta solución, sin embargo,
es problematica porque puede tener consecuencias impredecibles. Por ejemplo, un huérfano
puede haber bloqueado uno o más ficheros o registros en una base de datos. Si la operación se
aborta, quedarán bloqueados para siempre. Por otra, parte, una operación RPC puede haber
solicitado servicios remotos en otras máquinas que habría que abortar igualmente. Desde
UNIVERSIDAD NACIONAL DE TRUJILLO 20
                                                            ESCUELA DE INFORMATICA

 luego, una de las soluciones, tal vez la mejor, es esperar a que terminen los huérfanos aunque
 ellos represente una carga inútil de ciclos de UCP.

2.3.6 Implementación de software RPC
      El éxito o el fracaso de un sistema operativo distribuido radica en sus prestaciones. Si un sis-
      tema es lento, no tiene éxito. Las prestaciones de un sistema operativo distribuido radican en
      gran parte en la velocidad de las comunicaciones, y esta velocidad depende fundamentalmen-
      te de la implementación del protocolo de comunicación más que en sus principios abstratos.
      En esta sección vamos a discutir la implementación de software RPC.

      Protocolos RPC
      En los sistemas comerciales actuales, el software RPC está implementado como una bibliote-
      ca de funciones que el programa de usuario invoca. Tanto el cabo cliente como el cabo servi-
      dor no son sino un conjunto de llamadas a funciones de la biblioteca RPC. Veamos el ejem-
      plo de Sun RPC. El siguiente mandato UNIX es el que se utiliza para compilar el programa
      cliente rdate de la figura 2.9.

              # cc -o rdate rdate.c date_clnt.c -lrpclib

      donde se aprecia el enlace de la biblioteca de Sun RPC, rpclib. El mandato para generar el
      servidor RPC es similar. La aplicación de usuario rdate invoca funciones RPC del cabo
      que, a su vez, invocan las llamadas al sistema de comunicaciones del sistema operativo para
      enviar los mensajes al servidor RPC. Así, el software RPC puede entenderse como un nivel
      de servicio entre cliente o servidor y el sistema operativo, tal como ilustra la figura 2.11. Ge-
      neralmente, las llamadas al sistema de comunicaciones de los sistemas UNIX están imple-
      mentadas mediante la pila de protocolos TCP/IP, que forman parte del núcleo de UNIX. IP es
      el protocolo de nivel de red (nivel tres en la pila OSI).

      TCP es uno de los protocolos de transporte de la pila TCP/IPTCP es un protocolo del nivel de
      transporte (nivel cuatro en la pila OSI), orientado a conexión. La comunicación entre dos
      procesos mediante conexión se basa en establecer un circuito virtual entre ambas máquinas
      antes del hacer envío alguno. El establecimiento de una conexión es costoso en tiempo y re-
      cursos, pero garantiza la fiabilidad total de la comunicación.

      El otro protocolo de transporte de la pila TCP/IP es UDP, no orientado a conexión. UDP no
      es fiable. No usa reconocimientos para hacer saber al proceso emisor la llegada de un paque-
      te. No garantiza la estricta secuencia de los paquetes en el receptor, ya que cada uno de ellos
      circula por una ruta que no tiene por qué ser la misma. Los paquetes entrantes no son orde-
      nados, sino entregados a la aplicación según llegan. Tampoco dispone de control de flujo, de
      modo que una máquina rápida puede desbordar a una más lenta o más cargada, con la conse-
      cuente pérdida de paquetes. En resumen, si se usa UDP como protocolo de transporte, los
      paquetes pueden ser perdidos y, si llegan, hacerlo desordenadamente. Una aplicación de
      usuario que use UDP asume toda la responsabilidad de implementar la fiabilidad de la comu-
      nicación. UDP es, sin embargo, mucho más rápido que TCP. Se usa en redes altamente fia-
      bles como las redes locales. En ellas prácticamente no existen errores de comunicación que
      corrompan paquetes, de modo que la sobrecarga que TCP representa no está justificada y el
      programador de una aplicación de red puede entender perfectamente UDP como un protocolo
      fiable. En entornos de área ancha, sin embargo, el uso de TCP es imperativo.
UNIVERSIDAD NACIONAL DE TRUJILLO 21
                                                    ESCUELA DE INFORMATICA




                         Fig. 2.11 Contexto del software de Sun RPC.

A la hora de construir un software RPC, hay que considerar varias cuestiones. Una de ellas es
el un protocolo orientado a conexión es que la comunicación es mucho más fácil de imple-
mentar. Se envía un mensaje y tenemos la seguridad plena de que ha llegado a su destino. No
hay que preocuparse por reconocimientos ni paquetes desordenados. En suma, el nivel de
transporte ya está soportado por el protocolo de comunicación utilizado. Como alternativa,
puede pensarse en utilizar protocolo de comunicación que utilizan las funciones de la biblio-
teca RPC. La primera decisión que tomar es la elección de un protocolo orientado a conexión
o no orientado a conexión. La ventaja de un protocolo menos sofisticado como UDP en un
entorno fiable como una red local.

Una segunda cuestión a ponderar es el uso de un protocolo de comunicación de propósito
general o bien diseñar un protocolo específico que se adapte mejor al paradigma RPC. Sun
RPC utiliza la primera opción, construido sobre la pila TCP/IP. Las ventajas de usar un pro-
tocolo estándar como TCP/IP son evidentes, ya que

   1.   El protocolo no hay que diseñarlo ni implementarlo.
   2.   Está disponible en casi todos los sistemas UNIX.

El inconveniente de implementar RPC sobre un protocolo de comunicación estándar como
TCP o UDP es la pérdida de prestaciones. Por ejemplo, uno de los campos de la cabecera de
un paquete IP es el "checksum" de los campos de la cabecera, que es costoso de computar.

La alternativa al protocolo estándar es un protocolo específicamente diseñado para soportar
RPC. La desventaja es el tiempo de concepción y desarrollo de este protocolo y la integra-
ción en el sistema operativo. La ventaja es un aumento considerable en la velocidad de las
comunicaciones, un factor clave en sistemas operativos distribuidos.

Una tercera cuestión a considerar en el diseño del software RPC es la longitud permitida de
los mensajes RPC. Supongamos una llamada RPC read para leer un fichero de 64 Kbytes.
Una llamada RPC conlleva una fuerte carga de comunicación por sí misma, con independen-
cia de la cantidad de datos implicados, de modo que conviene realizar la lectura en una sóla
llamada. Para ello necesitamos mensajes suficientemente grandes. Sun RPC tiene un límite
de mensaje limitado a 8 Kbytes. También hay que considerar la longitud de los paquetes de
los protocolos subyacentes. Por ejemplo, los paquetes Ethernet están limitados a 1536 bytes,
de manera que una llamada RPC a menudo debe ser partida en muchos marcos ethernet, au-
mentando así la sobrecarga de comunicación.

Reconocimientos
En la sección anterior discutimos la posibilidad de implementar RPC sobre un protocolo no
fiable como UDP o incluso IP. La fiabilidad es entonces responsabilidad del protocolo RPC y
debe ser implementada mediante reconocimientos. Una llamada RPC puede ser la escritura
de un bloque de 4 Kbytes. Seguramente, la llamada RPC debe ser partida por el protocolo de
UNIVERSIDAD NACIONAL DE TRUJILLO 22
                                                       ESCUELA DE INFORMATICA

transporte RPC en varios paquetes de nivel inferior, supongamos cuatro paquetes como indi-
ca la figura 2.12. La estrategia de la figura 2.12b es que el servidor envíe un paquete de nivel
inferior con un código de reconocimiento para cada paquete de nivel inferior recibido. Ya que
la llamada RPC necesita cuatro paquetes, son precisos cuatro paquetes de reconocimiento.
Esta estrategia se denomina protocolo de parada y espera. La alternativa es esperar a que
llegue el último paquete de la llamada RPC y entonces el servidor envía un paquete de reco-
nocimiento al cliente. Esta estrategia se denomina protocolo de ráfaga. Con parada y espera,
si un paquete se pierde, el temporizador establecido para el paquete por el cliente agota su
plazo y el cliente retransmite el paquete. Con el protocolo de ráfaga, supongamos que se
pierde el mensaje 1 y el dos y el tres llegan correctamente. El servidor tiene dos alternativas.
Una es no enviar el reconocimiento de la llamada RPC. El temporizador del cliente para la
llamada agota el plazo y el cliente retransmite los cuatro paquetes de la llamada. La otra es lo
que se llama la repetición selectiva. El servidor envía un paquete de reconocimiento de los
paquetes 0, 2 y 3 y solicitud de reenvío del paquete 1. La repetición selectiva requiere más
gestión, pero usa mejor el ancho de banda de la red. Ya que la pérdida de paquetes en redes
locales raramente ocurre, conviene evitar el uso de la repetición selectiva. En redes de área
ancha la repetición selectiva es una opción conveniente.




      Fig. 2.12 a) Un mensaje de 4 Kbytes. b) Protocolo de parada y espera. c) Protocolo blast.

Un problema incluso más importante en el diseño de protocolos de red y transporte es el de
control de flujo. Cuando llega un paquete a un adaptador de Ethernet, por ejemplo, este eleva
una interrupción a la UCP para que el manejador copie el paquete del adaptador a la memoria
principal. Algunos de estos adaptadores son desabilitados mientras el paquete se lee, de mo-
do que si un segundo paquete llega en medio de la lectura, parte del mismo se pierde. En ge-
neral, cuando los paquetes llegan más aprisa de lo que pueden ser atendidos, parte de los
mismos se pierden, produciéndose un error denominado de "overrun" o sobreflujo. El sobre-
flujo es un problema más serio que los paquetes corrompidos por el ruido en las líneas.

Volvamos a la figura 2.12. Con un protocolo de parada y espera el error de sobreflujo no
puede producirse, porque el segundo paquete no se envía hasta de que no se ha reconocido el
primero. Sí puede producirse sobreflujo en un servidor con un número alto de clientes, no
obstante. Con el protocolo de ráfaga, mucho más eficiente que el de parada y espera, tenemos
el problema del sobreflujo. La solución es que el cliente no envíe el segundo paquete hasta
después de un tiempo suficiente como para que termine el trabajo de la rutina de interrupción
y el adaptador vuelva a aceptar paquetes. Si el retraso necesario para enviar el segundo pa-
quete es corto, el cliente puede realizar espera activa. Si es largo puede establecer una alar-
ma.
UNIVERSIDAD NACIONAL DE TRUJILLO 23
                                                          ESCUELA DE INFORMATICA

     Un protocolo de transporte de propósito general no tiene por qué tener conocimiento del tipo
     de adaptador de red existente en la máquina. Al fin y al cabo, este es un problema del nivel
     de enlace. Si el protocolo de nivel de enlace es Ethernet, no fiable, la fiabilidad se deja en
     manos del protocolo de red. Si este protocolo, como IP, tampoco es fiable, la fiabilidad des-
     cansa en el nivel de transporte. Si el protocolo de transporte es UDP, no fiable, es la aplica-
     ción de usuario -por ejemplo, el cabo RPC- el garante de la fiablilidad de la llamada RPC, a
     través de reconocimientos.

     Otra posibilidad es que el software RPC implemente el nivel de transporte, descansando di-
     rectamente sobre el nivel de red. Esta segunda posibilidad permite la optimización del proto-
     colo de transporte por dos razones. La primera es el conocimiento de que está sirviendo úni-
     camente a llamadas RPC, lo que puede ahorrar reconocimientos debido al modelo de interac-
     ción cliente servidor. La segunda razón es que el transporte RPC puede ser codificado con
     conocimiento del tipo de adaptador hardware de la red a la que pertenecen clientes y servido-
     res, evitando desde un principio el problema del sobreflujo, por ejemplo.

     Copias
     La copia de datos entre espacios de direccionamiento es el cuello de botella en las prestacio-
     nes de un software RPC. En el mejor de los casos, cuando un mensaje llega al adaptador de
     red, este puede copiarlo a un buffer del driver del adaptador en el kernel. El kernel lo copia a
     continuación al espacio del proceso de usuario en una estructura de datos del cabo.

2.3.7 Problemas abiertos
     La llamada a procedimiento remoto es una primitiva de comunicación más abstracta y por
     tanto más potente que el paso de un mensaje. Ello hace de RPC una herramienta más valiosa
     que el paso de mensaje en los complejos problemas que plantea la escritura de un sistema
     operativo distribuido. No obstante, algunos problemas no han sido aún resueltos por las ac-
     tuales implementaciones de RPC.

     Una de las metas de una llamada RPC es que sea completamente transparente al programa-
     dor. Supongamos una aplicación que corre en una única UCP que queremos distribuir
     haciendo uso de llamadas a procedimientos remotos. La total transparencia de RPC supone:

          1. La distribución de la aplicación o el sistema operativo no puede conllevar la prohibi-
             ción de ciertas construcciones en las llamadas a procedimiento remoto que son lega-
             les en las llamadas a procedimieto local.
          2. Tampoco debe requerir de construcciones que antes eran opcionales.

     Uno de los problemas es el de las variables globales. Una de ellas es errno, para el lenguaje
     C. El servidor RPC es un proceso en la máquina remota. El cliente es un proceso en la
     máquina local. Esto significa que la variable errno es diferente en ambos procesos. Por de-
     finición, esta variable contiene un código de error correspondiente a la última llamada al sis-
     tema fallida. Si un procedimiento local realiza una llamada al sistema vuelve con error, la va-
     riable errno tiene el código del error y está disponible a todos los procedimientos del pro-
     ceso. Falso. A todos los procedimientos del proceso, pero siempre que sean los locales. Los
     procedimientos remotos ven otra variable errno, la del servidor, que nada tiene que ver con
     el errno local. La solución de una aplicación distribuida es prohibir el acceso a la variable
     errno, lo cual viola el segundo principio.

     Otro problema es el paso de punteros. Es fácil pasar un arbol a un procedimiento local, pero
     cómo se pasa un árbol a un procedimiento remoto? No se puede pasar el puntero a la estruc-
     tura padre del arbol, ya que no tiene ningún sentido en la máquina remota.
UNIVERSIDAD NACIONAL DE TRUJILLO 24
                                                      ESCUELA DE INFORMATICA


También la función C printf plantea problemas porque tiene un número de parámetros va-
riable. La especificación del lenguaje C no pone límites al número de parámetros de
printf. Si nuestra intención es implementar printf como uno de los procedimientos de
un servidor RPC, es preciso empaquetar sus parámetros en el cabo antes de enviarlos. El
problema es que este es de longitud variable, lo que viola la definición de interfaz del servi-
dor, con declaraciones de rutinas de número fijo de parámetros. La solución es no hacer uso
de printf remota. Pero esto viola la deseada transparencia de RPC.

Hasta aquí hemos tratado algunos de los problemas que hay que superar para dotar de trans-
parencia a RPC. Sin embargo, existen problemas mucho más serios, ya que cuestionan la uti-
lidad misma del paradigma RPC. Considerar un sistema microkernel en el que el servidor de
ficheros, escrito como servidor según el paradigma de la figura 2.9, ha sido dispuesto en otra
máquina como un servidor RPC. De esta forma, todos los procesos locales actúan como
clientes del servidor de ficheros. Consideremos el mandato UNIX:

        # sort <f1 >f2

sort ordena su entrada estándar y el resultado se envía a la salida estándar, de modo que
puede ser programado como un cliente RPC. Para leer la entrada estándar realiza una llama-
da RPC read y para escribir en la salida estándar realiza una llamada RPC write. El mo-
delo cliente-servidor encaja perfertamente en la implementación distribuida del sistema de
ficheros. Lo mismo ocurre con el mandato

        # grep qsd <f3 >f4

que busca el patrón qsd en el fichero f3 y escribe en f4 las líneas que lo contienen. Consi-
deremos un sistema operativo distribuido en que los procesos se ejecutan en máquinas dife-
rentes. Supongamos que grep y sort han sido asignadas a máquinas distinas y el usuario
del sistema emite el mandato

        # grep qsd <f5 | sort >f6

De alguna manera, el sistema operativo debe implementarlo. Consideremos el paradigma
cliente- servidor. El cliente se considera el elemento activo, por que de él parten las iniciati-
vas de solicitud de servicio. El servidor se comporta como elemento pasivo, ya que no actúa
a menos que reciba un estímulo de solicitud de servicio. Según lo hasta ahora establecido, te-
nemos un proceso actuando como servidor que es el servidor de ficheros (pasivo) y dos pro-
cesos actuando como clientes que son grep y sort (activos) por que así han sido progra-
mados. Veamos si esta implementación sirve en esta ocasión. Si grep actúa como cliente,
puede solicitar una petición de escritura a sort para enviarle la salida de grep. Sin embar-
go, sort debería estar configurado como servidor (pasivo) a fin de recoger la salida de
grep cuando grep lo solicite. Sin embargo, hemos decidido escribir sort como un cliente
(activo) del sistema de ficheros. Bien sort, bien grep deberían haberse codificado como
servidor en lugar de como cliente. El problema es que esta opción, que sirve para un mandato
dado, es catastrófica para otro mandato. En general, el modelo cliente servidor no es apro-
piado en estado puro en el problema de la tubería

        # p1 <f3 | p2 | p3 >f2

Son necesarias soluciones más elaboradas. Por ejemplo, la tubería misma puede ser imple-
mentada como un proceso servidor que atiende peticiones de lectura y de escritura. Ahora
p1, p2 y p3 pueden ser escritos como clientes de las tuberías y del servidor de ficheros. Ni
UNIVERSIDAD NACIONAL DE TRUJILLO 25
                                                            ESCUELA DE INFORMATICA

        que decir tiene que esta solución representa una complejidad añadida al sistema operativo.
        Una solución más sencilla es implementar las pipelines como ficheros temporales en el ser-
        vidor de ficheros./**/


2.4 Comunicación de grupos
        La comunicación RPC tiene dos partes, una, el cliente, dos, el servidor. Hay situaciones en
        que este modelo no es el idóneo en un sistema con un conjunto de servidores de ficheros re-
        plicados a fin de proporcionar tolerancia a fallos. Un programa cliente que hace una escritura
        a disco debe hacer llegar la petición simultánemante a todos los servidores y no a uno de
        ellos únicamente. El problema puede solucionarse invocando tantas llamadas RPC como ser-
        vidores existentes. Existe, sin embargo, otro paradigma de comunicación disponible para los
        sistemas distribuidos que es la comunicación de grupos, más apropiado en casos como este.

2.4.1 Introducción a la comunicación de grupos
La característica principal de un grupo de procesos es que cuando se envía un mensaje al grupo,
todos sus componentes lo reciben. Por otra parte, los grupos son dinámicos. Los grupos nacen y
mueren y en cada grupo terminan algunos procesos y se incorporan otros. Por lo tanto es necesario un
mecanismo de gestión de grupos. Un proceso puede pertenecer a más de un grupo y abandonar un
grupo para unirse a otro. Un grupo es una abstracción cuyo propósito es evitar, en las llamadas de
comunicación con grupos de procesos, parámetros molestos como el número de elementos en el
grupo o la localización de cada proceso del grupo y proporcionar primitivas más potentes y
transparentes, como el ejemplo anterior de envío de un mensaje a un conjunto de servidores de
ficheros. El cliente no debería saber cuantos servidores están disponibles en cada momento ni en qué
máquinas concretas han sido arrancados.

La implementación de grupos depende mucho del hardware de comunicación disponible. En algunas
redes, como ethernet, existen unas direcciones especiales en las que pueden escuchar más de una
máquina. Para ello es necesario configurar el adaptador de red ethernet en cada máquina. Un único
marco o enviado a esta dirección es leído por todas las máquinas que escuchan en ella. Estas
direcciones se denominan multicasting. Si el nivel de enlace de la red soporta multicasting, como es
el caso de ethernet, la implementación de grupos es sencilla. Basta asignar a cada grupo una
dirección multicasting diferente. Existen redes que si bien no admiten multicasting, sí admiten
difusión. Marcos ethernet con la dirección de destino 111...111 son recibidos por todas las máquinas
de la red. La difusión puede ser utilizada para implementar grupos, pero es menos eficiente, porque el
marco se envía a todas las máquinas, tanto las que pertenecen al grupo como las que no. De todas
formas, el envío al grupo de procesos requiere de un solo paquete. Si el nivel de enlace no proporcio-
na multicasting ni difusión, aún es posible la implementación de grupos. Para ello, el emisor debe
enviar un paquete particular a cada miembro del grupo. Por supuesto, esta es la implementación
menos eficiente.

2.4.2 Aspectos de diseño
   La comunicación de grupos comparte muchos aspectos de la comunicación estándar de paso de
mensajes, tales como primitivas con buffer o sin buffer, bloqueantes o no bloqueantes, etc. No
obstante, existen más posibilidades adicionales a elegir en la comunicación de grupos. En esta
sección examinamos algunos de estos aspectos particulares en la comunicación de grupos.

2.4.2.1 Grupos cerrados frente a grupos abiertos

   Los protocolos que soportan comunicación de grupos pueden dividirse en dos categorías. Una es
la de los grupos cerrados. En ellos sólo los miembros del grupo pueden enviarse mensajes entre sí.
UNIVERSIDAD NACIONAL DE TRUJILLO 26
                                                             ESCUELA DE INFORMATICA

Procesos que no pertenencen al grupo no pueden enviar mensajes al grupo como tal, si bien, por
supuesto, sí pueden enviar mensajes particulares a cada miembro del grupo a título particular. Otros
protocolos soportan grupos abiertos. Un proceso que no pertenece a un grupo puede enviar mensajes
a este grupo. Los grupos cerrados son utilizados típicamente en procesamiento en paralelo, donde los
procesos tienen su propio cometido y no interactúan con el mundo exterior. Los grupos abiertos son
apropiados para poblemas como el de los servidores replicados, donde un cliente envía una petición
al grupo. Los miembros del grupo también necesitan hacer uso de la comunicación en grupo y no
sólo un proceso externo, por ejemplo para decidir quién debe ejecutar una petición dada.

2.4.2.2 Grupos de iguales frente a grupos jerárquicos
    En algunos grupos un proceso es el jefe o coordinador y el resto trabajan para él. En otros, todos
los procesos tienen la misma categoría y las decisiones se toman de forma colectiva. En el primer
caso, cuando uno de los trabajadores o un cliente externo solicita una petición, esta es enviada al
coordinador, que decide cuál de los trabajadores es el más apropiado para servirla. Cada una de estas
organizaciones tiene sus ventajas y sus inconvenietes. Los grupos pares no tienen un único punto de
fallo. Si un trabajador deja de existir, la carga se reparte en el resto. Sin embargo, incurren en el
retraso que supone el ponerse de acuerdo para dedidir quién sirve una petición. Los grupos
jerárquicos tienen las propiedades opuestas.

2.4.2.3 Pertenencia a grupos
   Se necesita un método para crear, destruir y modificar los grupos. Una solución es introducir un
proceso denominado el servidor de grupos. El servidor de grupos mantiene tablas con los grupos
existentes y sus integrantes. Esta solución es eficiente y fácil de implementar. El problema es que el
servidor de grupos es una técnica centralizadora y, como tal, constituye un único punto de fallo. La
opción opuesta es la gestión distribuida. Un nuevo proceso que se incorpora al grupo puede enviar un
mensaje al grupo y todos los procesos toman nota de su existencia. Cuando un proceso del grupo
termina, envía un mensaje de adiós.

Surge un problema cuando un proceso del grupo termina inesperadamente. El resto del grupo tiene
que descubrirlo experimentalmente, ya que el proceso nunca responde a nada. Cuando todos los
miembros lo han constatado, se le da de baja.

2.4.2.4 Direccionamiento de grupos
   Para dirigir un mensaje a un grupo, el grupo debe tener una dirección. Si el nivel de enlace de la
red -en adelante, la red- soporta multicasting, se puede implementar una dirección de grupo como
una dirección multicasting. Si la red soporta difusión, pero no multicasting, el mensaje debe ser
recibido por todos los núcleos y extraer de él la dirección del grupo. Si ninguno de los procesos de la
máquina es miembro del grupo, el mensaje es descartado. En otro caso, es pasado a todos los
procesos que pertenecen al grupo. Si la red no soporta ni difusión ni multicasting, el núcleo de la
máquina emisora tendrá que tener una lista de los procesos que pertenecen al grupo y enviar un
mensaje a cada uno de los componentes del grupo.

2.4.2.5 Primitivas send y receive
    No es conveniente que los procesos de usuario puedan utilizar las primitivas send y receive
por separarado. Según Tanenbaum, send y receive se corresponden en programación distribuida
con la construcción "go to" en programación convencional. Su utilización provoca más trastornos que
utilidad. Si RPC es la primitiva de comunicación usada por los procesos de usuario, la comunicación
de grupo debiera poder constuirse mediante RPC. El problema es tratar con una llamada a procedi-
miento que devuelve tantos valores como procesos tiene un grupo. No parece posible, de modo que
una aproximación común es volver a las primitivas send y receive en los procesos de usuario.
UNIVERSIDAD NACIONAL DE TRUJILLO 27
                                                             ESCUELA DE INFORMATICA

Si se permite send y receive a los procesos de usuario, se pueden aprovechar estas primitivas
para realizar la comunicación de grupo. En el caso de la comunicación convencional cliente servidor,
el primer parámetro de send es un número de puerto en la red y el segundo parámetro es el mensaje.
Se puede utilizar send para la comunicación de grupos empleando como primer parámetro la
dirección de un grupo de procesos en lugar de un puerto determinado. Así unificamos la comunica-
ción punto a punto y la comunicación de grupos en una primitiva única. La implementación de send
que haga el núcleo o la rutina de biblioteca puede ser una de las tres citadas en el apartado de
direccionamiento de grupos. send puede ser con buffer o sin buffer, bloqueante o no bloqueante,
fiable o no fiable, etc, igual que en la comunicación punto a punto. La comunicación de grupo no
cambia las cosas.

Enviar a un grupo obliga al núcleo del sistema que envía a hacer una comunicación multicasting a
todos los miembros del grupo, pero ¿qué es recibir de un grupo? Puede entenderse que todos los
miembros del grupo van a enviar una réplica diferente y por lo tanto un envío a un grupo debería
continuar en el programa de usuario con tantas operaciones receive como miembros tuviese el
grupo. Ello, no obstante, significa una pérdida de transparencia, ya que un proceso externo no debe
conocer la estructura interna de un grupo.

2.4.2.6 Atomicidad de la difusión
Una de las características de la comunicación de grupos es que un mensaje enviado a un grupo debe
ser recibido por todos los miembros del grupo o por ninguno de ellos. A esta propiedad se la
denomina la atomicidad de la difusión o simplemente la atomicidad. La atomicidad facilita en gran
medida la programación de sistemas distribuidos. Supongamos, por ejemplo, una base de datos
distribuida. Una base de datos distribuida puede tener una relación cuyos atributos estén repartidos en
máquinas dispersas geográficamente. El acceso a una tupla significa enviar un mensaje a todas las
máquinas. Supongamos la creación de una tupla de estas características. Si uno de los mensajes se
pierde, la base de datos queda en un estado inconsistente. La tupla debe crearse en su totalidad o no
crearse y la aplicación ser informada del éxito o del fracaso de la operación entera, no sólo un éxito
parcial. Implementar la atomicidad de la difusión no es tan simple como parece. Por ejemplo, uno de
los adaptadores de red tal vez acaba de recibir un paquete y antes de que esté preparado para recibir
uno nuevo, llega el paquete de difusión, que no puede ser aceptado y simplemente se pierde. Todas
las máquinas del grupo han recibido el paquete excepto una, lo que arruina la difusión completa. Para
cerciorarse de que todo ha ido bien, el emisor de la difusión debe esperar las confirmaciones de los
miembros del grupo. Si una falta, deberá repetir la difusión o reenviar el mensaje en particular.

Puede ocurrir que antes de repetir la difusión o hacer el reenvío, el emisor de la difusión se caiga. En
esta situación, el cliente debe rearrancar, pero nunca sabrá cuántos son los mensajes que realmente
han sido enviados y cuántos los que han fallado. Algunos miembros del grupo han recibido el
mensaje y otros no. Una situación inaceptable e ¿incorregible? No, queda alguna esperanza. Existe
un algoritmo que demuestra que la atomicidad es posible. El emisor realiza la difusión, inicializa
temporizadores y realiza los reenvíos necesarios. Cuando un miembro del grupo recibe un mensaje
nuevo, envía el mensaje a todos los miembros del grupo -de nuevo utilizando temporizadores y
retransmisiones si son necesarias-. Si el mensaje no es nuevo, simplemente es descartado. No importa
cuantas máquinas caigan en el proceso de envíos y reenvíos, lo importante es que de los procesos
supervivientes en el grupo todos han recibido el mensaje.

2.4.2.7 Ordenación de mensajes
           Para que la comunicación en grupo sea fácil de usar y comprender requiere de dos pro-
        piedades. La primera es la atomicidad, examinada más arriba y la segunda es el orden de los
        mensajes. Supongamos cinco máquinas, cada una con un proceso. Los procesos 0, 1, 3 y 4
        pertenecen a un grupo de procesos. Supongamos que los procesos 0 y 4 deciden enviar un
        mensaje al resto de los procesos del grupo. Supongamos que el proceso 0 lo ha decidido un
UNIVERSIDAD NACIONAL DE TRUJILLO 28
                                                            ESCUELA DE INFORMATICA

      instante de tiempo antes. La propiedad de orden temporal global exige que cada miembro
      del grupo reciba primero el mensaje del proceso 0 y después el mensaje del proceso 4.

      Una red local que soporte difusión garantiza el orden temporal global. Todos los mensajes
      del proceso 0 llegan al resto del grupo ya que el paquete con dirección difusión es recibido
      por todos los adaptadores de red de forma simultánea. Sólo después, cuando el mensaje ha
      sido enviado y deja libre el canal el proceso 4 puede emitir su paquete de difusión. Una red
      sin difusión no garantiza el orden temporal global, que debe implementar la difusión envian-
      do cuatro mensajes consecutivos que pueden entrelazarse con los del proceso 4. Así, el pro-
      ceso 1 puede recibir primero el mensaje del proceso 0 y después el del 4 y el proceso 3 puede
      recibir primero el mensaje del proceso 4 y después el del proceso 0 como indica la figura
      2.13.




                      Fig. 2.13 Violación del principio de ordenación tempo-
                      ral global en una red sin difusión. Los mensajes envia-
                                         dos se entrelazan.

      Existen algunas versiones más relajadas del orden temporal global. Una de ellas es el orden
      temporal consistente. Si los procesos 0 y 4 toman la decisión de enviar los mensajes al gru-
      po de forma independiente de forma casi instantánea, tal vez no haya forma de saber quien
      fue el primero en enviar. Tampoco importa, de manera que el sistema elige uno como el pri-
      mero. A partir de aquí se exige el cumplimiento del principio de orden temporal global.

2.4.2.8 Grupos solapados
         En el apartado anterior vimos el problema de la ordenación temporal global aplicada a
      un grupo dado. Dos procesos del mismo grupo enviaban simultáneamente un mensaje al
      grupo. Hemos mencionado previamente que un proceso puede pertenecer a más de un
      grupo, de manera que los grupos pueden solaparse. Este solapamiento produce un nuevo
      tipo de inconsistencia temporal. La figura 2.14 muestra el problema planteado. Los pro-
      cesos A y D, en distinto grupo, envían simultáneamente un mensaje a su propio grupo.
      Como en el caso anterior supongamos que la red no proporciona difusión y esta se im-
      plementa mediante unicasting. El envío simultáneo es consitente si B y C reciben prime-
      ro el mensaje del grupo 1 y después el mensaje del grupo 2 (o viceversa). Unicasting no
      puede garantizar esto, de modo que es posible el escenario de la figura 2.14. B recibe el
      mensaje dirigido al grupo 1 y después el mensaje al grupo 2. C, por el contrario, primero
      recibe el mensaje dirigido al grupo 2 y después el mensaje al grupo 1.
Sistemas distribuidos-la-comunicacion
Sistemas distribuidos-la-comunicacion
Sistemas distribuidos-la-comunicacion
Sistemas distribuidos-la-comunicacion

Más contenido relacionado

La actualidad más candente

Frame relay
Frame relayFrame relay
Frame relay1 2d
 
Frame relay-2
Frame relay-2Frame relay-2
Frame relay-2PIZARO
 
Acceso a la WAN: 8.1 Resolución de problemas de red
Acceso a la WAN: 8.1 Resolución de problemas de redAcceso a la WAN: 8.1 Resolución de problemas de red
Acceso a la WAN: 8.1 Resolución de problemas de redFrancesc Perez
 
1.5.2 redes de ejemplo tipicas orientadas a conexion
1.5.2  redes de ejemplo tipicas orientadas a conexion 1.5.2  redes de ejemplo tipicas orientadas a conexion
1.5.2 redes de ejemplo tipicas orientadas a conexion luishdiaz
 
Resumen del capitulo 10
Resumen del capitulo 10Resumen del capitulo 10
Resumen del capitulo 10Roshio Vaxquez
 
Capitulo 2 comunicacion a traves de la red
Capitulo 2 comunicacion a traves de la redCapitulo 2 comunicacion a traves de la red
Capitulo 2 comunicacion a traves de la redRoshio Vaxquez
 
Protocolos y Servicios Informaticos
Protocolos y Servicios InformaticosProtocolos y Servicios Informaticos
Protocolos y Servicios InformaticosJuan Antonio Mtz
 
Capitulo 1 la vida en un mundo centrado en las redes
Capitulo 1 la vida en un mundo centrado en las redesCapitulo 1 la vida en un mundo centrado en las redes
Capitulo 1 la vida en un mundo centrado en las redesRoshio Vaxquez
 
Presentación Protocolo x25 ppt
Presentación Protocolo x25 pptPresentación Protocolo x25 ppt
Presentación Protocolo x25 pptCarlos Durán
 
X25 y frame relay
X25 y frame relayX25 y frame relay
X25 y frame relayJuan Anaya
 

La actualidad más candente (20)

Frame relay
Frame relayFrame relay
Frame relay
 
Frame Relay
Frame RelayFrame Relay
Frame Relay
 
Frame relay
Frame relayFrame relay
Frame relay
 
Frame relay-2
Frame relay-2Frame relay-2
Frame relay-2
 
Acceso a la WAN: 8.1 Resolución de problemas de red
Acceso a la WAN: 8.1 Resolución de problemas de redAcceso a la WAN: 8.1 Resolución de problemas de red
Acceso a la WAN: 8.1 Resolución de problemas de red
 
1.5.2 redes de ejemplo tipicas orientadas a conexion
1.5.2  redes de ejemplo tipicas orientadas a conexion 1.5.2  redes de ejemplo tipicas orientadas a conexion
1.5.2 redes de ejemplo tipicas orientadas a conexion
 
Servicios de red 2
Servicios de red 2Servicios de red 2
Servicios de red 2
 
Reporte de capitulo 6
Reporte de capitulo 6Reporte de capitulo 6
Reporte de capitulo 6
 
Frame relay
Frame relayFrame relay
Frame relay
 
Resumen del capitulo 10
Resumen del capitulo 10Resumen del capitulo 10
Resumen del capitulo 10
 
Modelo osi
Modelo osiModelo osi
Modelo osi
 
frame Relay
frame Relayframe Relay
frame Relay
 
PPP
PPPPPP
PPP
 
Frame relay
Frame relayFrame relay
Frame relay
 
Capitulo 2 comunicacion a traves de la red
Capitulo 2 comunicacion a traves de la redCapitulo 2 comunicacion a traves de la red
Capitulo 2 comunicacion a traves de la red
 
Protocolos y Servicios Informaticos
Protocolos y Servicios InformaticosProtocolos y Servicios Informaticos
Protocolos y Servicios Informaticos
 
Frame Relay
Frame RelayFrame Relay
Frame Relay
 
Capitulo 1 la vida en un mundo centrado en las redes
Capitulo 1 la vida en un mundo centrado en las redesCapitulo 1 la vida en un mundo centrado en las redes
Capitulo 1 la vida en un mundo centrado en las redes
 
Presentación Protocolo x25 ppt
Presentación Protocolo x25 pptPresentación Protocolo x25 ppt
Presentación Protocolo x25 ppt
 
X25 y frame relay
X25 y frame relayX25 y frame relay
X25 y frame relay
 

Similar a Sistemas distribuidos-la-comunicacion

Similar a Sistemas distribuidos-la-comunicacion (20)

Atm Frame Relay
Atm Frame RelayAtm Frame Relay
Atm Frame Relay
 
Atm
AtmAtm
Atm
 
Asynchronous transfer mode-_conceptos
Asynchronous transfer mode-_conceptosAsynchronous transfer mode-_conceptos
Asynchronous transfer mode-_conceptos
 
Preguntas generadora nucleo 1
Preguntas generadora nucleo 1Preguntas generadora nucleo 1
Preguntas generadora nucleo 1
 
Grupo2 redesatm-101001115643-phpapp02
Grupo2 redesatm-101001115643-phpapp02Grupo2 redesatm-101001115643-phpapp02
Grupo2 redesatm-101001115643-phpapp02
 
ATM
ATMATM
ATM
 
Redes de área metropolitana y sus tecnologías
Redes de área metropolitana y sus tecnologías Redes de área metropolitana y sus tecnologías
Redes de área metropolitana y sus tecnologías
 
Grupo 2 redes atm
Grupo 2   redes atmGrupo 2   redes atm
Grupo 2 redes atm
 
ATM (Asynchronous Transfer Mode)
ATM (Asynchronous Transfer Mode)ATM (Asynchronous Transfer Mode)
ATM (Asynchronous Transfer Mode)
 
Atm
AtmAtm
Atm
 
Introducción a las Redes de Computadores
Introducción a las Redes de ComputadoresIntroducción a las Redes de Computadores
Introducción a las Redes de Computadores
 
Atm pesenyacion
Atm pesenyacionAtm pesenyacion
Atm pesenyacion
 
Atm
AtmAtm
Atm
 
Diaposi
DiaposiDiaposi
Diaposi
 
Tecnicas de Conmutacion
Tecnicas de ConmutacionTecnicas de Conmutacion
Tecnicas de Conmutacion
 
ATM
ATMATM
ATM
 
F Atm
F AtmF Atm
F Atm
 
Bus can
Bus canBus can
Bus can
 
Redes wan-4
Redes wan-4Redes wan-4
Redes wan-4
 
Teleproceso convertido
Teleproceso convertidoTeleproceso convertido
Teleproceso convertido
 

Sistemas distribuidos-la-comunicacion

  • 1. Tema 2 La Comunicación en los Sistemas Distribuidos La diferencia más importante entre un sistema distribuido y un sistema multiusuario convencio- nal es la comunicación de procesos. En un sistema convencional, la mayoría de los mecanismos desarrollados de alguna manera asumen la existencia de una memoria que comparten todos los procesos. Un ejemplo típico es el del productor-consumidor, donde la comunicación se realiza mediante un buffer almacenado en memoria común. El buffer más simple es el semáforo, que requiere tan sólo una palabra de memoria, el semáforo mismo. En un sistema distribuido, sin embargo, no existe en absoluto la memoria compartida, de modo que los mecanismos de comunicación de procesos deben ser rediseñados desde el principio. En este capitulo, discutiremos las reglas que deben observar dos computadores para comunicarse entre sí. Estas reglas se denominan protocolos. Asumiremos que el alumno está ya familiarizado con la pila de protocolos OSI, de modo que introduciremos ATM, un estándar de comunicación de alta velocidad emergente que se está mostrando como el más eficaz en la construcción de sistemas operativos distribuidos. Después examinaremos el modelo de comunicación cliente- servidor en detalle. Examinaremos las opciones disponibles en que los procesos pueden intercambiar mensajes. Una de estas formas es la llamada a procedimiento remoto. Este tópico merece un apartado especial por su interés y por su amplia implantación en sistemas comerciales actuales. El capítulo concluirá con la comunicación de más de dos procesos o grupos de procesos. 2.1 Redes ATM El modelo de referencia OSI fue discutido y consensuado por empresas públicas y privadas de telecomunicaciones en los años setenta y fue implementado en parte en los ochenta. Los años noventa han alumbrado nuevos desarrollos tecnológicos en los niveles inferiores de la pila de protocolos OSI. Uno de ellos es ATM o modo de transferencia asícrono. Es previsible que esta tecnología sea adoptada en la comunicación de los sistemas distribuidos, de modo que es preciso un mínimo acercamiento a la misma por parte de un diseñador de sistemas dis- tribuidos.
  • 2. UNIVERSIDAD NACIONAL DE TRUJILLO 2 ESCUELA DE INFORMATICA En los últimos veinticinco años, los computadores han experimentado avances en prestacio- nes de muchos órdenes de magnitud. Las redes no. Arpanet, la red precursora de Internet entró en funcionamiento en 1969 con líneas punto a punto de 56 Kbytes/s. Hoy todavía los usuarios finales de Internet se comunican a estas velocidades. Los nuevos desarrollos de los noventa proponen estándares que repentinamente saltan a velocidades de 155 Mbytes/s para el usuario final y a 1 Gbyte/s para el tronco principal de Internet. Este cambio de escala en las comunicaciones va a tener un impacto evidente en los sistemas distribuidos, donde van a aparecer nuevas aplicaciones que resultaban impensables hace tan sólo unos pocos años. Esta nueva tecnología, ATM, es la que ahora examinamos. 2.1.1 ¿Qué es el modo de transferencia asíncrono? A finales de los años ochenta las compañías de telecomunicaciones de todo el mundo comenzaron a darse cuenta de que las telecomunicaciones eran algo más que transmitir la voz humana en una banda de cuatro Khz. Entonces ya hacía tiempo que existían las redes de datos, como X.25, pero eran aún inmaduras y operaban a un máximo de 56 Kb/s o 64 Kb/s. Sistemas como la red Internet no pasaban de ser curiosidades académicas. Cuando estas compañías decidieron construir redes para el siglo 21, se encontraron con un dilema. Por una parte, la voz requiere un ancho de banda muy bajo, pero constante. Por la otra, los datos de los computadores no aparecen en las líneas de comunicación de una forma predecible y con una tasa constante. Al contrario, son de naturaleza explosiva. Repentinamente surge una corriente a la que es preciso asignar un canal del mayor ancho de banda posible. Cuando la comunicación acaba, el ancho de banda que se precisa es nulo. En conclusión, ni la red telefónica de conmutación de circuitos es apropiada para transmitir datos ni las redes de datos de conmutación de paquetes son apropiadas para trasmitir la voz. El compromiso más razonable para atender ambos tipos de tráfico es el modelo híbrido ATM. ATM requiere que sea establecido un circuito virtual antes de establecer la comu- nicación entre el emisor y el receptor o los receptores de la comunicación. Durante el es- tablecimiento de la conexión, la información del encaminamiento se almacena en los no- dos de conmutación ATM que definen la misma. Los paquetes de los protocolos de ni- vel superior -TCP/IP, FILP, ...- son enviados a la tarjeta o adaptador ATM de la máquina donde corre el proceso de usuario, que los trocea en unidades pequeñas de tamaño fijo denominadas celdas. Las celdas de una conexión siguen la secuencia de nodos que se es- tableció al crearla. Cuando esta termina, la información relativa a la conexión es elimi- nada de los nodos de conmutación. Las ventajas de este método son evidentes. La principal es que ahora una única red es capaz de transportar voz, datos, radio, televisión por cable, vídeo, etc, reemplazando a la red de antenas y repetidores de radio y televisión, la maraña de cabes de la red telefónica, el nuevo cableado de la televisión por cable, el cableado de las redes de datos, etc. Además, permite la aparición de nuevos servicios como las videoconferencias, que serán accesibles desde todos los hogares con un único cable. En todos los casos, los nodos in- termedios de la conexión ven sólo celdas, el contenido poco importa excepto al extremo final. El hecho de que las celdas sean de tamaño fijo hace que la conmutación sea mucho más rápida, sin necesidad de que sean almacenadas en disco duro como los paquetes de la red Internet. El segundo factor que incrementa la velocidad es que los conmutadores ATM no realizan control de flujo ni comprobación de errores en las celdas. A este método se le
  • 3. UNIVERSIDAD NACIONAL DE TRUJILLO 3 ESCUELA DE INFORMATICA denomina "cell relay". ATM opera estableciendo circuitos virtuales, pero un circuito sólo es establecido si están disponibles los recursos suficientes para garantizar la calidad del servicio solicitado. ATM tiene su propia pila de protocolo como indica la figura 2.1. A continuación vamos a describir brevemente los tres niveles ATM. Fig. 2.1 El modelo de referencia ATM. 2.1.2 El nivel físico Una tarjeta adaptadora ATM se encarga de poner en el cable, sea de cobre o fibra óptica una corriente continua de celdas. Cuando no hay nada que transmitir, se envían celdas vacías. A este modo de transmisión se le llama modo nativo ATM y logra velocidades de transmisión superiores al Gigabit/s con fibra óptica. Alternativamente, las celdas ATM pueden ser enviadas como datos convencionales en los marcos de la red de servicios integrados de banda ancha, B-ISDN. Con este método, definido en el estandar CCITT I.150, se alcanza una velocidad de transmisión de 155 Mbits/s o 622 Mbits/s. 2.1.3 El nivel ATM Este es el nivel que define el formato de las células y el protocolo orientado a conexión que las transmite. Cuando se discutían las propuestas, los comités europeo y norteamericano estaban enfrentados. Los americanos disponían de líneas de mayor calidad, con supresores de eco, lo que les permitía celdas más grandes, de 64 bits. Los europeos no disponemos de este tipo de líneas, de modo que celdas de 32 eran las más adecuadas. Se llegó a un compromiso de celdas de 48 bytes. Una celda de 48 bytes es demasiado grande para transmisión de voz y demasiado pequeña para transmisión de datos. Y peor aún, a la celda se le añadió un cabece- ro de 5 bytes. Resultaba una celda de 53 bytes que no enjaba bien en los marcos de la red B- ISDN. Una celda debe ser partida en dos marcos B-ISDN. A pesar de todo, el estándar ya es- ta elaborado y existen implementaciones hardware en funcionamiento. La figura 2.2 muestra el formato del cabecero de una celda ATM intercambiada entre un host de usuario y un conmutador ATM. Desgraciadamente, el cabecero entre dos conmutadores ATM es ligeramente distinto, lo que impone adaptadores distintos en hosts y conmutadores. La parte de datos, no obstante, es de 48 bytes en ambos tipos de celdas. Los campos VPI y VCI son los más importantes. VCI significa identificador de canal virtual. VPI es identifica- ción de ruta virtual (Virtual Path Identifier). En cada conmutador, tal y como indica la figura 2.3, existe una tabla de encaminamiento que se establece cuando se crea la conexión. Cuando una celda llega a un conmutador, se examinan los campos VCI y VPI y la celda sale por el puerto correspondiente. Por lo tanto, los campos VCI y VPI de una celda se modifican cada vez que esta atraviesa un conmutador. El campo GFC significa control genérico de flujo. No se utiliza a falta de un acuerdo sobre cómo emplearlo. El campo CLP significa prioridad en la
  • 4. UNIVERSIDAD NACIONAL DE TRUJILLO 4 ESCUELA DE INFORMATICA pérdida de celdas y puede utilizarse para distinguir entre unas celdas más importantes que otras en función de su contenido. En caso de congestión en un conmutador, este puede des- cartar las celdas menos importantes. El campo tipo de datos distingue entre celdas de datos y celdas de control y distingue entre varios tipos de celdas de control. El campo CRC -código de redundancia cíclica- es una comprobación sobre la cabecera completa (no los datos). Fig. 2.3 Disposición de la cabecera de una celda ATM. La figura 2.3 muestra cómo se realiza el encaminamiento de las celdas en un conmu- tador en base a la tabla establecida en el establecimiento de la conexión. Los nodos de una red ATM son de tres tipos: 1. Hosts, que envían y reciben mensajes. 2. Conmutadores de rutas virtuales, que mantienen las tablas de comutación de rutas vir- tuales. 3. Conmutadores de canales y rutas virtuales, que mantienen tablas de conmutación de canales y de rutas. Fig. 2.3 Conmutando rutas virtuales en una red ATM. ATM proporciona un servicio de baja latencia. El retardo que introduce un conmutador es de alrededor de 25 microsegundos. Una ruta transcontinental de 10 conmutadores introduce un retraso de 250 microsegundos, un cuarto de milisegundo, en cada celda que atraviesa los diez conmutadores. Esto significa que la comunicación cliente servidor tendría las mismas presta- ciones que si se hiciese en un red de área local en un contexto de área ancha ATM. 2.1.4 El nivel de adaptación ATM
  • 5. UNIVERSIDAD NACIONAL DE TRUJILLO 5 ESCUELA DE INFORMATICA Una celda ATM tiene 53 bytes o 53x8=424 bits. A una velocidad de transmisión de 155 Mbps, 424 bits se transmiten en 424/(155x106)=2.74 microsegundos. Pocas UCP pueden so- portar interrupciones de sus adaptadores de red a una tasa de 2.74 µs, lo que impone en el adaptador un mecanismo para ensamblar las celdas entrantes en que se reparte el mensaje de usuario. Este mecanismo es el que trocea el mensaje en las celdas que salen al cable. Estos procedimientos de ensamblado y desensamblado constituyen el nivel de adaptación ATM. Están implementados en el adaptador de red y provocan una interrupción por paquete y no por celda. Una propuesta del nivel de adaptación es SEAL, que significa "Nivel de Adaptación Simple y Eficiente". Por su nombre, fácilmente puede adivinarse lo que pensaron sus creadores de las propuestas anteriores. SEAL utiliza un bit del campo de tipo de datos de la celda. Este bit es normalmente cero, pero es uno en la última celda de un paquete. 2.1.5 Implicaciones de ATM en los sistemas distribuidos La disponibilidad de líneas de comunicación con anchos de banda de 155 Mbps, 622 Mbps y potencialmente hasta 2.5 Gbps tiene importantes implicaciones en el diseño de sistemas distribuidos, sobre todo en aquellos que abarcan áreas supranacionales, con componentes en distintos países o incluso continentes, los llamados sistemas distribuidos de área ancha. 2.1.5.1 Latencia El problema fundamental en estos sistemas es el inevitable retraso que sufre un im- pulso eléctrico aplicado en el extremo de un conductor en llegar al otro extremo. Este re- traso se denomina latencia. La electricidad se transmite en un cable de cobre a 2/3 de la velocidad de la luz. La luz en fibra óptica se transmite también a una velocidad que es 2/3 de la que alcanza en el vacío. Si disponemos de una línea transcontinental de 3000 Km, el retraso que experimenta una señal es de 3000/200000 = 15 ms. Supongamos que queremos enviar 1 Mb de datos por esa línea a 64 Kb/s y esperar la confirmación. Sóla- mente bombear a la línea el Mb lleva 1000/64 = 15.6 segundos. El retraso de propaga- ción del impulso eléctrico es de 0.015 * 2 = 0.03 segundos, que no es significativo frente a los 15.6, de modo que la distancia entre máquinas no es un factor que influya en el di- seño del sistema global. Consideremos ahora la instalación de adaptadores ATM en ambas máquinas a una velo- cidad de 622 Mbs. Ahora poner en la línea 1 Mb supone 1/622 = 0.0016 s. Un retardo de propagación de 0.03 segundos, no sólo sí es significativo frente a 0.0016 segundos que se emplea en sacar el fichero a la línea, sino que es 18 veces mayor. Se tarda muchísimo más en que el primer bit llegue al otro extremo que en poner en el cable el megabit ente- ro. Desde que comienza el envío hasta que vuelve la confirmación transcurren 0.0316 segundos, de los cuales la línea está ocupada 0.0016 s y ociosa 0.03 segundos, es decir, el 95% del tiempo. Un aumento de la velocidad de transmisión no provoca provoca más que un menor aprovechamiento de la línea, que se aproxima asintóticamente al 100%. La conclusión es que en la construcción de sistemas de distribuidos de área ancha, la laten- cia de las comunicaciones lleva a reconsiderar las arquitecturas y los protocolos emplea- dos. 2.1.5.2 Control de flujo
  • 6. UNIVERSIDAD NACIONAL DE TRUJILLO 6 ESCUELA DE INFORMATICA Dispositivos que se comunican a 622 Mbps también plantean el problema del control de flujo de la comunicación. Supongamos que una máquina envía a otra, a 3000 Km, una cinta de video que ocupa 10 Gb. Seguramente la estación receptora no va a tener dispo- nible un buffer de 10 Gb, de modo que, cuando el espacio se agota, envía una celda a la estación emisora con el mandato STOP. La celda STOP va a tardar un mínimo de 0.015 segundos. En ese intervalo de tiempo, han llegado a la máquina receptora 0.015 s * 622 Mbps = 9.3 Mb, que deben ser descartados. Será necesario introducir un protocolo clási- co de ventana deslizante que imponga a la estación emisora el envío de 1 Mb y la espera de una celda de confirmación antes de enviar el segundo Mb. Ahora estamos en la situa- ción antes descrita, en que la ocupación de la línea no supera el 5% de tiempo. La solu- ción a este problema pasa por aumentar el número de Mbits de memoria RAM en los adaptadores de red, lo que supone un alto costo. Otra solución es la negociación de la ve- locidad de transmisión en bits/s en la fase del establecimiento del circuito virtual. De cualquier modo, el salto de 64Kbps a 622 Mbps no va suponer que las prestaciones de un sistema distribuido se multipliquen por 10.000 y será necesario investigar aún para sacar el mayor partido posible a la tecnología ATM. 2.2 El Modelo Cliente-Servidor El modelo de referencia OSI es aparentemente una buena herramienta para construir sis- temas operativos distribuidos, ya que sus protocolos garantizan que los bits que se envían por la red de comunicación llegan correctamente a su destino. Sin embargo, no es así. Por una parte, hay que considerar que la implantación de los protocolos OSI representa una sobrecarga muy importante en la tarea del transporte de los bits. En líneas de baja capacidad, como 64Kbps, la ejecución de los procesos que implementan los protocolos que tratan un paquete IP, por ejemplo, terminan antes de que llegue el siguiente, de modo de la comunicación no se ve retardada por la sobrecarga OSI. En modelos de comunica- ción más rápidos, como ATM, los protocolos OSI representan el cuello de botella de la comunicación. Es preciso tener en cuenta que la pila OSI no trata más que una pequeña parte del problema de la comunicación y es que los datos se transmitan entre los extre- mos finales correctamente, no necesariamente rápidamente. Para construir sistemas dis- tribuidos las prestaciones son fundamentales, de modo que al modelo OSI la hace falta algo más. Este algo más es la arquitectura cliente-servidor. 2.2.1 Clientes y servidores Un sistema operativo distribuido se puede estructurar mediante un grupo de procesos que cooperan. Unos prestan servicios y se denominan servidores y otros los solicitan y se denominan clientes. Generalmente, en el contexto de un sistema operativo distribuido, clientes y servidores son programas de usuario que corren en máquinas con el mismo microkernel. Así, una máquina puede albergar un sólo cliente o un sólo servidor o bien una mezcla de clientes y de servidores. El modelo cliente-servidor se basa en un protocolo no orientado a conexión de petición- réplica (Fig 2.4). Consiste en el envío de un mensaje por parte del proceso cliente al pro- ceso servidor. El servidor devuelve los datos requeridos o bien un indicador de error. Na- da más. No es necesario establecer ni liberar ninguna conexión. Supongamos que las máquinas son idénticas y se opera en un entorno de red local altamente fiable como et- hernet o token-ring. No es necesario el nivel cuatro de OSI porque los datos se transmi- ten sin error. No es necesaria ninguna función de encaminamiento por que el hardware se
  • 7. UNIVERSIDAD NACIONAL DE TRUJILLO 7 ESCUELA DE INFORMATICA encarga directamente. Así, no es necesario el nivel tres de OSI. El protocolo petición- réplica reside en el nivel cinco de la pila OSI, que invoca directamente los servicios del nivel dos. Fig. 2.4 El modelo de interacción cliente-servidor. Cuando los procesos que residen en máquinas distintas se comunican a través de una red local, es preciso añadir al microkernel servicios de comunicación, que presentan a los programas de usuario mediante llamadas al sistema. En un modelo de interacción cliente- servidor, estas llamadas al sistema pueden ser funciones de biblioteca como send(direccion, &mens) y receive(direccion, &mens). El nivel cinco puede ser implementado en funciones de este tipo que invocan las llamadas al sistema de comunicación de procesos. Estas funciones examinan los parámetros con que el usuario ha invocado send y receive y, finalmente, ejecutan una función de trap al sistema operativo. mens es una estructura de datos en espacio de direccionamiento del proceso de usuario. direccion es el identificador de un punto de acceso al servicio de peti- ción-réplica donde receive espera las peticiones o bien donde send las envía. Los procesos se comunican enviando datos y recibiendo datos en un punto de acceso previa- mente acordado. A estos puntos de acceso se les denomina comúnmente puertos. 2.2.2 Direccionamiento Cada punto de acceso al servicio de comunicación cliente-servidor debe tener una direc- ción que lo identifica en todo el sistema distribuido y lo distingue del resto. El criterio seguido para identificarlos de una forma global a todo el sistema distribuido, es decir, darles una dirección única, es el objeto de esta sección. En toda red de computadores cada máquina tiene una dirección que la identifica, de mo- do que la primera alternativa es dar al punto de acceso la dirección de la máquina en la red. Si sólo hay un proceso ejecutando en la máquina, cuando un mensaje llega, el kernel se lo envía al único proceso que existe. Ahora bien, si hay más procesos ejecutando, ¿a qué proceso se lo envía? Desde luego, esta no es la solución adecuada. A continuación vamos a examinar tres posibles aproximaciones al problema (Fig. 2.5).
  • 8. UNIVERSIDAD NACIONAL DE TRUJILLO 8 ESCUELA DE INFORMATICA Fig 2.5 [1] direccionamiento máquina-puerto. [2] direccionamiento mediante difusión. [3] direccionamiento vía un servidor de nombres. La solución pasa por direcciones de puntos de acceso que consisten en dos partes. La primera es la dirección de la máquina en la red y la segunda es una dirección particular en cada máquina. Así, la máquina 245 tiene las direcciones 245@0, 245@1, etc. La pila de protoco- los TCP/IP usa este método. La primera parte de la dirección se llama dirección IP, e identifi- ca una máquina en la Internet. La segunda parte se llama puerto. Servicios TCP/IP bien co- nocidos como finger o ftp utilizan siempre el mismo puerto en todas las máquinas. El servidor de FTP, por ejemplo, recibe en el puerto 21, de modo que, conceptualmente, realiza un equivalente a receive(@21, &mens). Un cliente FTP que accede a la máquina de dirección IP 33.33.33.33 conceptualmente invoca send(33.33.33.33@20, &mens). Este modo de direccionamiento, si bien es simple, está lejos de ser ideal por que no es transparente. El cliente debe ser consciente de la máquina en que reside el servicio y la transparencia es una de las metas en el diseño de un sistema operativo distribuido. Una alternativa es numerar los puntos de acceso de forma global y no relativos a cada máquina. Una posibilidad es elegirlos de forma aleatoria en un rango numérico muy grande, por ejemplo el definido por los números enteros de 64 bits. Según este sistema, un proceso cliente no necesita conocer direcciones de máquinas, sino sólo números de puerto de 64 bits. Ahora bien, aunque un proceso cliente conozca la identificación del punto de acceso a un servicio, sin importarle en qué máquina reside el servidor, los protocolos de red sí necesitan conocer la máquina en la que se encuentra, a fin de enviar allí el mensaje. Del identificador aleatorio de 64 bits no se deriva ninguna dirección de red, de modo que se plantea un pro- blema que es necesario resolver. Redes locales como ethernet soportan difusión o "broadcasting", es decir, la posiblidad de que una máquina envíe un paquete al resto de los nodos de la red. Un cliente que conoce la
  • 9. UNIVERSIDAD NACIONAL DE TRUJILLO 9 ESCUELA DE INFORMATICA dirección de un servicio en la red local pero no conoce la máquina en la que reside, puede hacer uso de la difusión para encontrarla. Este paquete, denominado paquete de localización, lleva el identificador de 64 bits del punto de acceso y ocasiona una réplica de la máquina que alberga dicho punto de acceso. Esta respuesta lleva su dirección de red. Dicha dirección es registrada por el kernel de la máquina solicitante en una caché a fin de evitar una nueva difu- sión en un segundo uso del servicio. Como es de apreciar, este esquema es transparente al cliente, que sólo sabe de la identificación del servicio y no de su ubicación. Existe una tercera solución al direccionamiento de los servicios. Consiste en que los clientes accedan a un servicio especificando su nombre, una cadena ascii. Es necesario incorporar a la red un servidor de nombres, que almacena pares (Nombre, XXX@YYY). Con este esquema, un cliente, antes de acceder a un servicio debe realizar una consulta al servidor de nombres. Cada una de las tres soluciones tiene sus inconvenientes. La primera no es transparente, la segunda añade sobrecarga en el sistema y la tercera requiere un componente centralizado, que no escala adecuadamente. 2.2.3 Primitivas con bloqueo y sin bloqueo Las primitivas send y receive pueden ser diseñadas como bloqueantes o síncronas y no bloqueantes o asíncronas. A veces, ambas opciones, con bloqueo y sin bloqueo, están dispo- nibles para el usuario. Si send es bloqueante, significa que, tras ser invocada por un proceso de usuario, este es suspendido hasta que el mensaje ha sido enviado. Enviado puede significar dos cosas sutil- mente distintas y que es preciso aclarar en cada contexto. Unos autores, sobre todo los impli- cados en construcción de sistemas operativos, entienden por "enviado" como aquel mensaje que ha sido copiado al kernel para su envío o que ha sido puesto directamente en la línea de comunicación. Lo importante, consideran ellos, es que el buffer del mensaje saliente quede libre de nuevo. Lo de menos es que el mensaje haya sido recibido. Otros autores, sobre todos los involucrados en la construcción de lenguajes, argumentan que un mensaje puede conside- rarse como enviado cuando ha llegado a su destino, es decir, cuando el kernel de la máquina destino ha replicado al kernel de la máquina remitente con un mensaje de reconocimiento. En lo que ambos están de acuerdo es que si la primitiva send retorna cuando se confirma la re- cepción del mensaje, esta semántica es síncrona. También todos están de acuerdo en que si send retorna antes de que el mensaje haya sido copiado al núcleo o enviado por la línea, es- tamos ante una primitiva asíncrona. Si receive es bloqueante, el proceso que la invoca es suspendido mientras el mensaje no haya sido recibido. Si receive es no bloqueante, el proceso que la invoca no se suspende en ella. Al cabo de algún tiempo que el proceso considere oportuno, acudirá al buffer a reco- ger el mensaje solicitado con la esperanza de que haya llegado o bien con la información de que efectivamente así ha ocurrido. La ventaja de las llamadas no bloqueantes reside que el proceso de usuario invocante puede seguir ejecutando concurrentemente con la transmisión del mensaje. La ventaja del aumento de prestaciones de las llamadas no bloqueantes se ve superada, no obstante por una desventa- ja muy seria: el emisor de send(direccion, &mens) no puede modificar el buffer mens hasta que este haya sido enviado y, lo que es peor, en principio no conoce cuándo el envío se produce, de modo que no puede volver a reutilizarlo para enviar o recibir un nuevo mensaje. A este problema se le pueden aplicar dos soluciones: 1. La primera es que el kernel copie el contenido del mensaje a un buffer interno y desde allí lo envíe. Ahora el proceso de usuario puede reutilizar el buffer y send se comporta como
  • 10. UNIVERSIDAD NACIONAL DE TRUJILLO 10 ESCUELA DE INFORMATICA en modo síncrono. La desventaja de esta solución es que el kernel debe copiar el mensaje al adaptador de comunicaciones cuando este esté libre para transmitir. Son necesarias dos copias, una de espacio de usuario al kernel y otra del kernel al dispositivo de E/S. Cuando el mensaje es grande y los envíos numerosos, esta solución puede degradar notablemente las prestaciones del sistema. 2. La segunda solución es interrumpir al emisor cuando el mensaje ha sido enviado. Enton- ces el proceso entiende que ya puede modificar el buffer. Esta es una opción que, si bien ahorra tiempo, hace muy complicada la programación de aplicaciones de usuario y, debi- do a la aparición de las condiciones de carrera, hace muy difícil de depurar este tipo de programas. Por lo tanto, las desventajas superan ampliamente a las ventajas. El utilizar primitivas síncronas parece la opción más adecuada. No maximiza el paralelismo, pero es fácil de comprender y de programar. Las mismas consideraciones que hemos hecho sobre send se aplican a receive. En el diseño de las primitivas de comunicación puede considerarse la introducción de plazos. Tras invocar send, el kernel desbloquea el proceso cuando recibe el reconocimiento de que el mensaje ha llegado a su destino. Si este no llega, el proceso quedará bloqueado indefini- damente. Algunos sistemas proporcionan primitivas con un parámetro de temporización. Si el mensaje no ha sido enviado o recibido en el plazo especificado, la llamada vuelve con error. 2.2.4 Primitivas con buffer y sin buffer Una llamada receive(direccion, &mens) indica al kernel que el próximo mensaje entrante dirigido al punto de acceso direccion se copie en el buffer mens del espacio de direccionamiento del proceso que la invoca. Esta primitiva se conoce como sin buffer porque el kernel no almacena el mensaje entrante antes de entregarlo a la aplicación. Funcio- na correctamente cuando receive se invoca antes de que llegue el mensaje a la dirección especificada. En contraste, cuando el mensaje llega antes de que se produzca la llamada re- ceive, el kernel no sabe a quién entregar el mensaje y, como no dispone de espacio para almacenarlo, simplemente lo descarta, enviando al kernel del emisor un código de error. En la aplicación que envía, send retorna con error y siempre puede volver a hacer un reintento. Cuando la aplicación que envía considera que el número de reintentos execede un límite, re- nuncia a seguir, presumiendo que el servidor no está ejecutando, cuando tal vez esté sirvien- do un mensaje que simplemente exige más tiempo que el habitual. El problema se palía disponiendo un buffer en el kernel para cada punto de acceso. A este buffer se le suele llamar buzón. Las primitivas con buzones asociados se denominan "con buffer". La solución no es completa, sin embargo. El buzón tiene capacidad finita, de modo que cuando se llena volvemos a la situación de la primitiva sin buffer, donde los mensajes son descartados. 2.2.5 Primitivas fiables y no fiables Hasta aquí hemos asumido tácitamente que, cuando se envía un mensaje, el kernel del recep- tor lo recibe. Sin embargo, los mensajes en ocasiones se pierden en las líneas de comunica- ción. Vamos a considerar tres estrategias ante el problema. La primera es reconsiderar la semántica de send en el programa de usuario como no fiable. Implementar una comunica- ción fiable se deja en manos del usuario. Al fin y al cabo, el correo convencional funciona así. Una carta se deja en el buzón y el servicio de correos pone todo de su parte, pero no ga- rantiza que la carta va a llegar a su destino. Las primitivas fiables se implementan mediante mensajes de confirmación, que a continuación examinamos. Así, la segunda aproximación se
  • 11. UNIVERSIDAD NACIONAL DE TRUJILLO 11 ESCUELA DE INFORMATICA basa en que el kernel de la máquina receptora envíe un mensaje de confirmación al kernel de la máquina emisora. El programa de usuario que invoca send queda suspendido hasta que este mensaje se recibe. La réplica del servidor al cliente también va acompañada de este tipo de confirmación (Fig 2.6, izq.), de modo que el servidor queda bloqueado en send hasta que la confirmación se produce. La tercera vía es sacar partido a que la interacción cliente- servidor está diseñada como una réplica del servidor al cliente que siempre sigue a la solici- tud de este último. En la figura 2.6, izq. vemos que el servidor envía los mensajes 2 y 3 al cliente, el 2 para confirmar la llegada de la petición y 3 lleva la réplica. Podemos prescindir de la confirmación 2 que modo que ésta venga dada implícitamente por la réplica 3 (Fig. 2.6, der.). El cliente queda ahora suspendido en send hasta que se llegue la réplica del servidor, que se confirma con el mensaje 4. Fig. 2.6 Izq. Mensajes de usuario individualmente reconocidos. 2.3 Llamada a procedimiento remoto (RPC) En el anterior epígrafe hemos estudiado un modelo de interacción entre los procesos de un sistema distribuido que es el modelo cliente-servidor. Para implementarlo, el sistema dispone de dos llamadas al sistema, send y receive, que las aplicaciones utilizan de forma con- veniente. Estas primitivas, a pesar de constituir la base de la construcción de los sistemas dis- tribuidos, pertenecen a un nivel demasiado bajo como para programar de forma eficiente aplicaciones distribuidas. 2.3.1 La operación RPC básica
  • 12. UNIVERSIDAD NACIONAL DE TRUJILLO 12 ESCUELA DE INFORMATICA La llamada a procedimiento remoto constituye un mecanismo que integra el concepto clien- te-servidor con la programación convencional basada en llamadas a procedimientos. La idea surgió en 1984 y consiste en que el cliente se comunica con el servidor mediante una llama- da ordinaria a un procedimiento. Esta llamada se denomina a procedimiento remoto porque el procedimiento invocado se encuentra en otro espacio de direccionamiento, en la misma o en distinta máquina que el cliente. La información se transporta en los parámetros de la lla- mada y el resultado es devuelto en el retorno de la llamada. El cliente no tiene que utilizar las primitivas send y receive como en el modelo cliente-servidor puro, de modo que la pro- gramación de aplicaciones distribuidas se hace más sencilla. La figura 2.7 muestra un ejemplo del uso de RPC. El cliente necesita de un servicio que es la suma de dos enteros. El servicio se invoca mediante a una llamada a función tal y como se hace en un programa convencional escrito en C. La única diferencia es que la función se eje- cuta en una máquina diferente de una forma completamente transparente al usuario. Fig. 2.7 Computando una suma de forma remota. La función suma(2, 3); de la figura se implementa en el cliente como una rutina de bi- blioteca que se denomina el cabo o "stub" cliente. Recordemos cómo se implementan las llamadas al sistema en un lenguaje como C en un sistema operativo centralizado. Estas aca- ban almacenando los parámetros de la llamada en los registros de la UCP y ejecutando una instrucción de trap al sistema operativo. En un sistema distribuido las cosas son básicamente iguales. La función suma contiene una llamada al sistema send seguida de una llamada receive, donde el programa cliente que invoca suma(2, 3); es suspendido hasta que llega la respuesta del servidor, según el modelo de interacción cliente-servidor. Como pode- mos ver, el mecanismo RPC no es sino el modelo cliente-servidor, pero con una interfaz más sencilla que hace que el cliente invoque al servicio por su nombre y sin necesidad de gestio- nar números de puerto. En cuanto al servidor, el cabo no es una función como era suma en el cliente, sino que es el programa principal. El programador del servicio sólo se ocupa del procedimiento que invoca el cliente. Las llamadas de receive y send en el servidor son ejecutadas por el cabo, que recibe el mensaje, determina el procedimiento solicitado -suma en este caso- y, finalmen- te, lo invoca. Todos los pasos implicados son los siguientes: 1. El cliente llama al cabo cliente en la manera convencional. 2. El cabo cliente construye un mensaje empaquetando los parámetros del procedi- miento y salta al kernel mediante un trap. 3. El kernel local envía el mensaje al kernel remoto. 4. El kernel remoto entrega el mensaje al cabo servidor. 5. El cabo servidor desempaqueta los parámetros y llama al procedimiento de servicio.
  • 13. UNIVERSIDAD NACIONAL DE TRUJILLO 13 ESCUELA DE INFORMATICA 6. El procedimiento de servicio hace el trabajo y devuelve el resultado. 7. El cabo servidor empaqueta el resultado y salta al kernel mediante un trap. 8. El kernel remoto envía el mensaje al kernel local. 9. El kernel local envía el mensaje al cabo del cliente, ahora suspendido esperándolo. 10. El cabo local desempaqueta el resultado y lo devuelve al cliente. 2.3.2 El paso de parámetros La función del cabo cliente es empaquetar los parámetros en un mensaje y enviarlo al ca- bo servidor. Este examina el código del procedimiento en una sentencia tipo switch e invoca el procedimiento de forma local. El resultado es de nuevo empaquetado en un mensaje y en- viado al cabo cliente. Esta interacción, que parece directa, no es tan simple como aparenta ser. Mientras las arquitecturas del cliente y del servidor sean iguales no se presenta ningún problema especial. En un entorno distribuido, sin embargo, cada arquitectura tiene su propia representación de números, caracteres, etc. Por ejemplo, los mainframe IBM utilizan el códi- go EBCDIC para los caracteres en lugar del código ASCII, como el IBM PC. Problemas si- milares ocurren con la representación de coma flotante o los enteros negativos (complemento a 1 o complemento a 2). Otro problema surge con la forma de almacenar un entero. La arquitectura PC mantiene una representación "little endian", a saber, el byte menos significativo en el byte más bajo de memoria. La arquitectura SPARC utiliza un almacenamiento "big endian", es decir, el byte más significativo en el byte más bajo de la memoria. Un 486 operando en modo protegido representa un entero con cuatro bytes, de modo que el 5 lo representa como 0005. Suponga- mos que es el primer parámetro de la llamada a procedimiento suma de la Fig. 2.7 y que el servidor ejecuta en una estación SPARC. Los bytes se envían a la red siguiendo su posición en la memoria, de modo que circulará por ella la secuencia de bits del cinco, luego la del cero tres veces. Según llegan los bytes se van almacenando en el buffer del mensaje comenzando por el byte más bajo, de modo que en la memoria de la máquina servidora tenemos llos cua- tro bytes almacenados de la misma forma que en la memoria del 486, es decir, 0005, el 5 en el byte más bajo. Sin embargo, para la UCP SPARC, este número no es el cinco, sino 5*2563, casi 84 millones. Por lo tanto, es preciso realizar una convesión en la máquina SPARC antes de entregar los parámetros al procecimiento de servicio. Nótese, no obstante, que si es otra máquina SPARC la que envía el entero 5, no es necesario realizar la conversión. Una forma de solucionar todos estos problemas de representación es convertir los datos a una forma canónica antes de ser enviados a la red. Cuando los parámetros llegan a su destino, por ejemplo, es preciso reconvertir el formato canónico al de la arquitectura del servidor. El pro- blema de este método es que es ineficiente en interacciones entre máquinas de igual arquitec- tura, de modo que otra aproximación al problema es incorporar en el mensaje un primer byte que identifique la arquitectura del emisor. Si es la misma que la del receptor, no es necesaria conversión alguna. El problema más difícil de tratar en las llamadas a procedimiento remoto es el paso de punte- ros, ya que estos sólo tienen sentido en un espacio de direccionamiento dado. Un entero pa- sado a una rutina de servicio tiene un significado pleno, pero un puntero es simplemente una referencia inútil. No obstante, el paso de punteros en las aplicaciones de usuario es tan común que el prescindir de ellos en las llamadas a rutinas remotas haría perder al concepto de RPC gran parte de su atractivo. Afortunadamente, el problema puede abordarse. En el lenguaje C, por ejemplo, están disponibles dos formas de pasar parámetros. Los enteros y ca- racteres se pasan por valor. Esto significa que, al invocar un procedimiento con un parámetro que es un entero, se hace una copia del entero en la pila. La rutina invocada trabaja con esta copia. La variable original no se toca. Los vectores, sin embargo, se pasan por referencia.
  • 14. UNIVERSIDAD NACIONAL DE TRUJILLO 14 ESCUELA DE INFORMATICA Ello significa que no se copia en la pila el vector completo en la llamada, sino sólo su direc- ción. El programador de la rutina que recibe la referencia es consciente de que trabaja con un puntero al vector original, que es realmente modificado en la rutina. En Pascal, por defecto, todas las variables se pasan por valor. El paso por referencia es controlado por el programa- dor añadiendo el modificador var a la definición del parámetro que se pasa por referencia en la declaración de la rutina. Un mecanismo adicional de paso de parámetros es denominado de copia-restauración. Con- siste en realizar una copia del parámetro en la pila. Si esta copia parámetro es modificada en el procedimiento, se restaura su nuevo valor a la variable original. Algunos compiladores de Ada utilizan este mecanismo en parámetros in out, si bien ello no está especificado en la de- finición del lenguaje. La estrategia de copia con restauración puede ser utilizada para pasar punteros a procedimientos remotos. Supongamos la invocación del procedimiento remoto cuenta = read(df, buf, nbytes); La implementación más directa consiste en copiar al buffer del mensaje local un vector de "nbytes" caracteres en lugar de buf, que es la referencia al vector. El mensaje es entonces en- viado al cabo servidor. Ahora el buffer del mensaje se encuentra en el espacio de direcciona- miento de este último, invocará la rutina de servicio read con la referencia al vector recibi- do en el mensaje, es decir de forma convencional por referencia. Ahora el mensaje es devuel- to con su contenido actualizado a la rutina cabo del cliente, que restaura el vector del mensa- je a su vector original. Para optimizar este mecanismo eludimos en el cabo cliente la copia del vector al mensaje en caso de lectura. En el caso de la escritura, prescindiremos de restau- rarlo. Como vemos, es posible pasar punteros a procedimientos remotos siempre que sean re- ferencias a estructuras sencillas como vectores. No obstante, no podemos enviar a procedi- mientos remotos referencias a estructuras de datos complejas como listas o árboles. 2.3.3 Especificación de interface El servidor RPC puede ser considerado como un módulo u objeto que implementa unas operaciones sobre datos ocultos. El servidor de a conocer estas operaciones a los clientes mediante lo que se denomina su interface, constituida por las declaraciones de los méto- dos que soporta. Como sabemos, el objetivo del mecanismo RPC es lograr que un programa tenga acceso a los servicios de uno de estos módulos, aunque residan en otro espacio de direcciona- miento, posiblemente remoto. La figura 2.8 muestra los componentes de una implemen- tación RPC. La mitad rayada constituye el software adicional de empaquetamiento y desempaquetamiento de parámetros y primitivas de comunicación que debe ser ocultado al programador. Por brillante que sea la idea de la interacción cliente-servidor a través de RPC, si el programador debe encarar la construcción de los cabos, el progreso de los sis- temas distribuidos se verá comprometido por la falta de uso en la práctica. Es preciso que la generación de cabos en el cliente y el servidor se realize de forma automática. Pues bien, la interfaz del servidor se utiliza como la base de esta generación automática de ca- bos. El primer paso es definir el interfaz, es decir, el conjunto de los prototipos de los proce- dimientos de servicio, mediante un lenguaje determinado, denominado lenguaje de inter- face. La figura 2.8, a) muestra un ejemplo de servidor. La figura 2.8, b) su definición de interfaz. Un compilador especial toma como entrada el fichero escrito en el lenguaje de interface y como salida genera el código objeto de los procedimientos que constituyen el cabo cliente, por una parte, y el cabo servidor, por la otra. El programa cliente se enlaza
  • 15. UNIVERSIDAD NACIONAL DE TRUJILLO 15 ESCUELA DE INFORMATICA con estos procedimientos objeto para generar el ejecutable. En cuanto al servidor, los procedimientos de servicio, escritos por el programador, se compilan previamente a len- guaje objeto y, a continuación, se enlazan con los procedimientos cabo, entre los que fi- gura el procedimiento principal del servidor RPC. #include <header.h> void main(void) { struct mensaje m1, m2; /* Mensajes entrante y saliente */ int r; while(1) { receive(FILE_SERVER, &m1); /* El servidor se bloquea esperando un mensaje */ switch(m1.opcode) { case CREATE: r = do_create(&m1, &m2); break; case READ: r = do_read(&m1, &m2); break; case WRITE: r = do_write(&m1, &m2); break; case DELETE: r = do_delete(&m1, &m2); break; case DELETE: r = E_BAD_OP; break; } m2.result = r; send(m1.source, &m2); } } a) #include <header.h> specification of file_server, version 3.1 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; b) Fig. 2.8 Ejemplo de un servidor y su definición de interface. Una de las implementaciones RPC más populares es Sun RPC, desarrollada por Sun Micro- systems. Supongamos que deseamos un servidor de tiempo que proporcione dos servicios. Uno, invocado por la función bin_date_1 que devuelve el número de segundos transcu- rridos desde las cero horas del 1 de enero de 1970. Otro, invocado por la función str_date_2. Esta función toma un parámetro, que es un número de segundos transcurri- dos desde el instante antes citado, y devuelve la hora y la fecha en una cadena de caracteres. La figura 2.9 describe los pasos implicados en la creación de los procesos servidor y cliente a partir de la especificación de interfaz en el sistema Sun RPC.
  • 16. UNIVERSIDAD NACIONAL DE TRUJILLO 16 ESCUELA DE INFORMATICA Fig. 2.9 Sun RPC 2.3.4 Enlace dinámico No es conveniente que un servicio esté ligado a una máquina. A veces las máquinas no están operativas, de modo que los servicios se mueven a otra máquina. El cliente está interesado en el servicio, no en qué máquina ejecuta el servidor. Para solicitar un servi- cio, un cliente podría enviar un mensaje en una sentencia como la siguiente send(33.33.33.33@20, &mens); en el código fuente que implementa la llamada RPC. Esta solución es inflexible, puesto que, si dentro de la máquina 33.33.33.33 el servidor pasa a escuchar en otro puerto distinto del 20, el cliente debe ser recompilado. Lo mismo ocurre si el servidor cambia de máquina. En contraste, el cliente debería invocar el servicio por su nombre, sin hacer referencia a dirección alguna. La figura 2.8 b) muestra la especificación formal del servidor de fiche- ros 2.8 a). En la especificación formal del servidor intervienen el nombre del servidor y su número de versión. Ambos datos identifican un servidor. Un servidor con el mismo nombre y la misma versión, no obstante, pueden estar replicados en dos o más máquinas a fin de mejorar el servicio o proporcionar tolerancia a fallos. El cliente debe solicitar un servicio invocando su nombre y versión, sin citar dirección alguna. El número de versión es conveniente a fin de que un servidor que evoluciona conserve su nombre. Un servidor puede evolucionar ofertando nuevos servicios, cancelando otros y modificando otros. A pesar de esta evolución, es preciso que clientes antiguos, desconocedores de los cambios, sigan obteniendo el mismo tipo de servicio. Es preciso comprender, no obstante, que un servidor con el mismo nombre pero con número de versión distinto es un servidor dife- rente. Las ventajas de identificar al servidor por su nombre son evidentes, pero, ¿cómo el clien- te localiza al servidor? ¿Quién le proporciona su dirección? Este es un problema al que algunos sistemas RPC, entre ellos Sun RPC, dan respuesta mediante lo que se llama el enlace dinámico, que no es sino averiguar la dirección del servidor en tiempo de ejecu- ción. El enlace dinámico está basado en un tercer proceso denomindado el enlazador. Cuando el servidor arranca, en su código de inicialización previo al bucle principal, en- vía un mensaje al enlazador a fin de registrarse como un proceso que presta un servicio. El enlazador es, al fin y al cabo, un registrador de servicios, un servidor de nombres. El
  • 17. UNIVERSIDAD NACIONAL DE TRUJILLO 17 ESCUELA DE INFORMATICA servidor entrega su nombre, su número de versión y su dirección. Se dice que el servidor exporta su interfaz. No sería extraño que dos programadores diesen el mismo nombre a dos servidores distintos, de modo que, a pesar de que no aparezca en la figura 2.9 b), ca- da servidor RPC tiene asociado, además del nombre y la versión, un identificador numé- rico, generalmente de 32 bits, que también entrega en la operación de registro. Dos ser- vidores distintos deben tener identificadores distintos (se entiende aquí servidor como programa, no como proceso). Si bien sería raro, es posible que dos programadores que terminan dos servidores RPC, coincidan en darles el mismo identificador. Lo que ocurra cuando ambos traten de registrarse depende de cada implementación particular del soft- ware RPC, pero es lógico pensar que el enlazador rechazaría la segunda petición de re- gistro. Supongamos que un cliente invoca el procedimiento remoto read de la figura 2.8 b). El cabo del cliente percibe que aún no dispone de la dirección del servidor, de manera que envía un mensaje al enlazador solicitando la dirección de un servidor cuyo nombre y ver- sión el cliente proporciona en los campos del mensaje. El enlazador busca en sus tablas tal servidor y, si está registrado, proporciona su dirección al cliente en el mensaje de réplica. La principal ventaja del enlace dinámico es que el servidor puede estar en cual- quier máquina. Incluso puede haber varios servidores. En enlazador proporciona al clien- te la dirección del servidor menos sobrecargado, más cercano, etc. Una desventaja es el tiempo que lleva el registro del servidor y la solicitud del cliente. Muchos procesos clien- te sólo hacen una llamada a procecimiento remoto. Por otra parte el enlazador puede lle- gar a ser una máquina muy solicitada, hasta el punto de necesitar varios enlazadores re- plicados. Mantener la consistencia de los mismos conlleva más tráfico en el sistema. 2.3.5 Semántica RPC en presencia de fallos El objetivo de la llamada a procedimiento remoto es conseguir la ejecución de procedi- mientos en otras máquinas sin cambiar la forma en que se invoca el procedimiento en el código fuente. Salvo algunas excepciones como que un procedimiento remoto no puede usar variables globales, el objetivo ha sido alcanzado plenamente. Mientras no se produzcan errores la transparencia de la llamada remota está conseguida, ya que el programador no necesita saber que la llamada que realiza es a un procedimiento remoto. Los problemas llegan cuando bien cliente o bien servidor dejan de operar correcatamente, ya que las diferencias entre llamadas locales y remotas no son fáciles de enmascarar. Vamos a considerar cinco situaciones de fallo: 1. El cliente no es capaz de localizar al servidor. 2. El mensaje del cliente al servidor se pierde. 3. El mensaje de réplica de servidor a cliente se pierde. 4. El servidor se cae tras recibir el mensaje del cliente. 5. El cliente se cae tras recibir la réplica. El cliente no puede localizar al servidor Puede haber varias causas. Una es que el servidor se cae. Otra es que el servidor se actualiza y un cliente antiguo invoca una versión del servidor que ya no ejecuta. Una solución es que la llamada devuelva -1 como código de error. Sin embargo, -1 puede ser un resultado válido como en la llamada RPC de suma de la figura 2.7. Otro intento de solución es escirbir un manejador de excepción (señales en C) para los errores producidos en las llamadas RPC. Sin embargo, esta solución acaba con la transparencia respecto a las llamadas locales. Lo mejor es recibir el resultado en parámetros de salida de la llamada RPC y que esta devuelva 0 en caso de ejecución con éxito y un código de error en otro caso.
  • 18. UNIVERSIDAD NACIONAL DE TRUJILLO 18 ESCUELA DE INFORMATICA La petición del cliente se pierde Este caso tiene un tratamiento sencillo. El núcleo del cliente arranca un temporizador cuando envía el mensaje al servidor. Si al cabo de un plazo no ha llegado réplica o reconocimiento del servidor, el cliente da el mensaje por perdido y lo reenvía. Si todos los reenvíos se pierden, el kernel del cliente considera que el servidor no está activo y devuelve un error al cabo cliente, que lo pasa a la aplicación. Estamos en el caso anterior. La réplica del servidor se pierde Este problema es más complejo. Cuando en el caso anterior venció el plazo sin que llegase la respuesta del servidor, asumimos que se había perdido el mensaje enviado por el cliente. Pero existe la posibilidad de que el mensaje perdido fuese la réplica. De cualquier forma, estable- cimos que lo que había que hacer era el reenvío del mensaje. En el primer caso, el servidor recibe el mensaje reenviado por primera vez. Todo vuelve a funcionar correctamente. En el segundo caso el servidor recibe el mensaje por segunda vez. Sirve la petición dos veces, como si en el programa cliente hubiésemos invocado la llamada una segunda vez. En algunos casos, la repetición de una operación en el servidor no causa ningún daño. Por ejemplo, el leer los 20 primeros bytes de un fichero. Las peticiones que tienen esta propiedad se dicen que son idempotentes. Otras veces, la re-petición sí ocasiona perjuicios, como puede ser el añadir 20 bytes a ese fichero o retirar de una cuenta bancaria 500 millones de pesetas. La solución a este problema pasa por numerar las peticiones. Las retransmisiones llevan el mismo número de secuencia que la transmisión original. Entonces el kernel del servidor detecta que la réplica se ha perdido y la reenvía, sin operar sobre el servidor. Una versión distinta de esta solución es introducir en la cabecera de la petición un bit de retransmisión. El servidor se cae La figura 2.10 a) muestra la secuencia de eventos producidos en un servidor en el servicio de una petición. El sistema operativo del servidor recibe el paquete entrante con el mensaje, que entrega al cabo para que invoque la ejecución del procedimiento que sirve la petición. A continuación, el cabo pasa la réplica al sistema operativo que lo envía en un paquete al cliente. Ahora bien, tras haberse ejecutado el procedimiento de servicio, el servidor puede sufrir una caída que impide la emisión de la réplica al cliente. Es el caso b) de la figura. Por el contrario, la caída puede producirse tras la recepción del paquete, pero previamente a la ejecución del procedimiento de servicio. Es el caso c). Las consecuencias de los casos b) y c) es diferente. Supongamos que la operación remota es escribir un texto en la impresora. El servidor primero carga el texto en la memoria interna de la impresora y después escribe en un registro de la misma para iniciar la impresión. El servi- dor puede caerse antes de establecer el bit o después de establecer el bit. En el primer caso, la operación no será realizada. En el segundo caso, sí, ya que la impresora continúa su trabajo con independencia de que el servidor esté activo o no lo esté. Podemos pensar que este caso tiene la misma complejidad que la pérdida de la réplica, exami- nada en el caso anterior. No es así. La pérdida de la réplica supone un reenvío de la solicitud de impresión. El núcleo del servidor se dará cuenta de que el mensaje tiene un número de secuencia repetido y enviará de nuevo la réplica si repetir la impresión. En contraste, la caída del servidor supone la pérdida del registro de los números de secuencia de mensajes del cliente. Por esta razón, tras un rearranque, el servidor no puede saber si la re-petición de impresión ha sido servida con anterioridad, de modo que volverá a ser servida. Si la caída se produjo en el caso c) la impresión no se hizo, de modo que reiniciar la operación es lo correc- to. Sin embargo, si la caída se produjo en el caso b) reiniciar la operación supone repetirla. Lo
  • 19. UNIVERSIDAD NACIONAL DE TRUJILLO 19 ESCUELA DE INFORMATICA peor del caso b) es que ni cliente ni servidor sabrán nunca si la operación se realizó con anterioridad o no. Fig. 2.10 Caída del servidor. a) Operación correcta. b) Caída tras servir el mensaje c) Caída antes de servir el mensaje. La discusión anterior viene a decir, en esencia, que la ejecución de un procedimiento remoto está envuelta en un factor de incertidumbre que hay que asumir a la hora de programar una aplicación distribuida. Para reducir este factor aleatorio, los implementadores de un sistema RPC toman una de estas tres aproximaciones en cuanto a la semántica de la llamada RPC. La primera se denomina semántica de "al menos una vez". Esta filosofía de implementación de un software RPC garantiza a la aplicación cliente que el procedimiento remoto va a ejecutarse al menos una vez, pero posiblemente más. Mientras el servidor de figura 2.10 está caído, el cliente no cesa de enviarle nuevas solicitudes de impresión. Llega un momento en que el servidor rearranca y su decisión es ejecutar la petición. Ante el caso b) de la figura 2.10, el servidor está repitiendo la operación. En el caso c) no la repite. De cualquier forma, este mecanismo garantiza la impresión al menos una vez. La segunda aproximación se denomina semántica de "como máximo una vez". A la aplicación cliente no se le garantiza que la llamada se ejecute. Tras el rearranque, el servidor RPC puede tomar la decisión de ignorar las peticiones entrantes y de enviar un mensaje de aviso al cliente informándole de la caída, para que este tome las medidas oportunas. La llamada devolverá un código de error parecido a "rearranque de servidor". El cliente tendrá garantizado que el procedimiento no se ha ejecutado más de una vez. Lo que nunca sabrá es si se ejecutó alguna vez. Otra aproximación que puede tomar el cliente, si la caída se prolonga, es renunciar tras un número de reintentos determinado. También en este caso, desconoce si el procedimiento se ejecutó. La tercera filosofía que puede adoptar el software RPC es no garantizar nada a la aplicación de usuario. Si el servidor se cae, tras el rearranque, informa de la caída y sigue ejecutando peticiones como si nada hubiese ocurrido. El procedimiento puede no haberse ejecutado o puede haberse ejecutado una o más veces. La ventaja de esta semántica es que es fácil de implementar. El cliente se cae Puede ocurrir que un cliente haya invocado una llamada RPC y, antes de que la respuesta llegue, el cliente se cae. La operación que se realiza en el servidor no se hace ahora en benefi- cio de nadie y se dice que ha quedado huérfana. Las operaciones huérfanas son un problema. Cuando el cliente rearranca, puede eliminar las operaciones iniciadas mediante un mensaje especial. Esta solución se denomina exterminación de huérfanos. Esta solución, sin embargo, es problematica porque puede tener consecuencias impredecibles. Por ejemplo, un huérfano puede haber bloqueado uno o más ficheros o registros en una base de datos. Si la operación se aborta, quedarán bloqueados para siempre. Por otra, parte, una operación RPC puede haber solicitado servicios remotos en otras máquinas que habría que abortar igualmente. Desde
  • 20. UNIVERSIDAD NACIONAL DE TRUJILLO 20 ESCUELA DE INFORMATICA luego, una de las soluciones, tal vez la mejor, es esperar a que terminen los huérfanos aunque ellos represente una carga inútil de ciclos de UCP. 2.3.6 Implementación de software RPC El éxito o el fracaso de un sistema operativo distribuido radica en sus prestaciones. Si un sis- tema es lento, no tiene éxito. Las prestaciones de un sistema operativo distribuido radican en gran parte en la velocidad de las comunicaciones, y esta velocidad depende fundamentalmen- te de la implementación del protocolo de comunicación más que en sus principios abstratos. En esta sección vamos a discutir la implementación de software RPC. Protocolos RPC En los sistemas comerciales actuales, el software RPC está implementado como una bibliote- ca de funciones que el programa de usuario invoca. Tanto el cabo cliente como el cabo servi- dor no son sino un conjunto de llamadas a funciones de la biblioteca RPC. Veamos el ejem- plo de Sun RPC. El siguiente mandato UNIX es el que se utiliza para compilar el programa cliente rdate de la figura 2.9. # cc -o rdate rdate.c date_clnt.c -lrpclib donde se aprecia el enlace de la biblioteca de Sun RPC, rpclib. El mandato para generar el servidor RPC es similar. La aplicación de usuario rdate invoca funciones RPC del cabo que, a su vez, invocan las llamadas al sistema de comunicaciones del sistema operativo para enviar los mensajes al servidor RPC. Así, el software RPC puede entenderse como un nivel de servicio entre cliente o servidor y el sistema operativo, tal como ilustra la figura 2.11. Ge- neralmente, las llamadas al sistema de comunicaciones de los sistemas UNIX están imple- mentadas mediante la pila de protocolos TCP/IP, que forman parte del núcleo de UNIX. IP es el protocolo de nivel de red (nivel tres en la pila OSI). TCP es uno de los protocolos de transporte de la pila TCP/IPTCP es un protocolo del nivel de transporte (nivel cuatro en la pila OSI), orientado a conexión. La comunicación entre dos procesos mediante conexión se basa en establecer un circuito virtual entre ambas máquinas antes del hacer envío alguno. El establecimiento de una conexión es costoso en tiempo y re- cursos, pero garantiza la fiabilidad total de la comunicación. El otro protocolo de transporte de la pila TCP/IP es UDP, no orientado a conexión. UDP no es fiable. No usa reconocimientos para hacer saber al proceso emisor la llegada de un paque- te. No garantiza la estricta secuencia de los paquetes en el receptor, ya que cada uno de ellos circula por una ruta que no tiene por qué ser la misma. Los paquetes entrantes no son orde- nados, sino entregados a la aplicación según llegan. Tampoco dispone de control de flujo, de modo que una máquina rápida puede desbordar a una más lenta o más cargada, con la conse- cuente pérdida de paquetes. En resumen, si se usa UDP como protocolo de transporte, los paquetes pueden ser perdidos y, si llegan, hacerlo desordenadamente. Una aplicación de usuario que use UDP asume toda la responsabilidad de implementar la fiabilidad de la comu- nicación. UDP es, sin embargo, mucho más rápido que TCP. Se usa en redes altamente fia- bles como las redes locales. En ellas prácticamente no existen errores de comunicación que corrompan paquetes, de modo que la sobrecarga que TCP representa no está justificada y el programador de una aplicación de red puede entender perfectamente UDP como un protocolo fiable. En entornos de área ancha, sin embargo, el uso de TCP es imperativo.
  • 21. UNIVERSIDAD NACIONAL DE TRUJILLO 21 ESCUELA DE INFORMATICA Fig. 2.11 Contexto del software de Sun RPC. A la hora de construir un software RPC, hay que considerar varias cuestiones. Una de ellas es el un protocolo orientado a conexión es que la comunicación es mucho más fácil de imple- mentar. Se envía un mensaje y tenemos la seguridad plena de que ha llegado a su destino. No hay que preocuparse por reconocimientos ni paquetes desordenados. En suma, el nivel de transporte ya está soportado por el protocolo de comunicación utilizado. Como alternativa, puede pensarse en utilizar protocolo de comunicación que utilizan las funciones de la biblio- teca RPC. La primera decisión que tomar es la elección de un protocolo orientado a conexión o no orientado a conexión. La ventaja de un protocolo menos sofisticado como UDP en un entorno fiable como una red local. Una segunda cuestión a ponderar es el uso de un protocolo de comunicación de propósito general o bien diseñar un protocolo específico que se adapte mejor al paradigma RPC. Sun RPC utiliza la primera opción, construido sobre la pila TCP/IP. Las ventajas de usar un pro- tocolo estándar como TCP/IP son evidentes, ya que 1. El protocolo no hay que diseñarlo ni implementarlo. 2. Está disponible en casi todos los sistemas UNIX. El inconveniente de implementar RPC sobre un protocolo de comunicación estándar como TCP o UDP es la pérdida de prestaciones. Por ejemplo, uno de los campos de la cabecera de un paquete IP es el "checksum" de los campos de la cabecera, que es costoso de computar. La alternativa al protocolo estándar es un protocolo específicamente diseñado para soportar RPC. La desventaja es el tiempo de concepción y desarrollo de este protocolo y la integra- ción en el sistema operativo. La ventaja es un aumento considerable en la velocidad de las comunicaciones, un factor clave en sistemas operativos distribuidos. Una tercera cuestión a considerar en el diseño del software RPC es la longitud permitida de los mensajes RPC. Supongamos una llamada RPC read para leer un fichero de 64 Kbytes. Una llamada RPC conlleva una fuerte carga de comunicación por sí misma, con independen- cia de la cantidad de datos implicados, de modo que conviene realizar la lectura en una sóla llamada. Para ello necesitamos mensajes suficientemente grandes. Sun RPC tiene un límite de mensaje limitado a 8 Kbytes. También hay que considerar la longitud de los paquetes de los protocolos subyacentes. Por ejemplo, los paquetes Ethernet están limitados a 1536 bytes, de manera que una llamada RPC a menudo debe ser partida en muchos marcos ethernet, au- mentando así la sobrecarga de comunicación. Reconocimientos En la sección anterior discutimos la posibilidad de implementar RPC sobre un protocolo no fiable como UDP o incluso IP. La fiabilidad es entonces responsabilidad del protocolo RPC y debe ser implementada mediante reconocimientos. Una llamada RPC puede ser la escritura de un bloque de 4 Kbytes. Seguramente, la llamada RPC debe ser partida por el protocolo de
  • 22. UNIVERSIDAD NACIONAL DE TRUJILLO 22 ESCUELA DE INFORMATICA transporte RPC en varios paquetes de nivel inferior, supongamos cuatro paquetes como indi- ca la figura 2.12. La estrategia de la figura 2.12b es que el servidor envíe un paquete de nivel inferior con un código de reconocimiento para cada paquete de nivel inferior recibido. Ya que la llamada RPC necesita cuatro paquetes, son precisos cuatro paquetes de reconocimiento. Esta estrategia se denomina protocolo de parada y espera. La alternativa es esperar a que llegue el último paquete de la llamada RPC y entonces el servidor envía un paquete de reco- nocimiento al cliente. Esta estrategia se denomina protocolo de ráfaga. Con parada y espera, si un paquete se pierde, el temporizador establecido para el paquete por el cliente agota su plazo y el cliente retransmite el paquete. Con el protocolo de ráfaga, supongamos que se pierde el mensaje 1 y el dos y el tres llegan correctamente. El servidor tiene dos alternativas. Una es no enviar el reconocimiento de la llamada RPC. El temporizador del cliente para la llamada agota el plazo y el cliente retransmite los cuatro paquetes de la llamada. La otra es lo que se llama la repetición selectiva. El servidor envía un paquete de reconocimiento de los paquetes 0, 2 y 3 y solicitud de reenvío del paquete 1. La repetición selectiva requiere más gestión, pero usa mejor el ancho de banda de la red. Ya que la pérdida de paquetes en redes locales raramente ocurre, conviene evitar el uso de la repetición selectiva. En redes de área ancha la repetición selectiva es una opción conveniente. Fig. 2.12 a) Un mensaje de 4 Kbytes. b) Protocolo de parada y espera. c) Protocolo blast. Un problema incluso más importante en el diseño de protocolos de red y transporte es el de control de flujo. Cuando llega un paquete a un adaptador de Ethernet, por ejemplo, este eleva una interrupción a la UCP para que el manejador copie el paquete del adaptador a la memoria principal. Algunos de estos adaptadores son desabilitados mientras el paquete se lee, de mo- do que si un segundo paquete llega en medio de la lectura, parte del mismo se pierde. En ge- neral, cuando los paquetes llegan más aprisa de lo que pueden ser atendidos, parte de los mismos se pierden, produciéndose un error denominado de "overrun" o sobreflujo. El sobre- flujo es un problema más serio que los paquetes corrompidos por el ruido en las líneas. Volvamos a la figura 2.12. Con un protocolo de parada y espera el error de sobreflujo no puede producirse, porque el segundo paquete no se envía hasta de que no se ha reconocido el primero. Sí puede producirse sobreflujo en un servidor con un número alto de clientes, no obstante. Con el protocolo de ráfaga, mucho más eficiente que el de parada y espera, tenemos el problema del sobreflujo. La solución es que el cliente no envíe el segundo paquete hasta después de un tiempo suficiente como para que termine el trabajo de la rutina de interrupción y el adaptador vuelva a aceptar paquetes. Si el retraso necesario para enviar el segundo pa- quete es corto, el cliente puede realizar espera activa. Si es largo puede establecer una alar- ma.
  • 23. UNIVERSIDAD NACIONAL DE TRUJILLO 23 ESCUELA DE INFORMATICA Un protocolo de transporte de propósito general no tiene por qué tener conocimiento del tipo de adaptador de red existente en la máquina. Al fin y al cabo, este es un problema del nivel de enlace. Si el protocolo de nivel de enlace es Ethernet, no fiable, la fiabilidad se deja en manos del protocolo de red. Si este protocolo, como IP, tampoco es fiable, la fiabilidad des- cansa en el nivel de transporte. Si el protocolo de transporte es UDP, no fiable, es la aplica- ción de usuario -por ejemplo, el cabo RPC- el garante de la fiablilidad de la llamada RPC, a través de reconocimientos. Otra posibilidad es que el software RPC implemente el nivel de transporte, descansando di- rectamente sobre el nivel de red. Esta segunda posibilidad permite la optimización del proto- colo de transporte por dos razones. La primera es el conocimiento de que está sirviendo úni- camente a llamadas RPC, lo que puede ahorrar reconocimientos debido al modelo de interac- ción cliente servidor. La segunda razón es que el transporte RPC puede ser codificado con conocimiento del tipo de adaptador hardware de la red a la que pertenecen clientes y servido- res, evitando desde un principio el problema del sobreflujo, por ejemplo. Copias La copia de datos entre espacios de direccionamiento es el cuello de botella en las prestacio- nes de un software RPC. En el mejor de los casos, cuando un mensaje llega al adaptador de red, este puede copiarlo a un buffer del driver del adaptador en el kernel. El kernel lo copia a continuación al espacio del proceso de usuario en una estructura de datos del cabo. 2.3.7 Problemas abiertos La llamada a procedimiento remoto es una primitiva de comunicación más abstracta y por tanto más potente que el paso de un mensaje. Ello hace de RPC una herramienta más valiosa que el paso de mensaje en los complejos problemas que plantea la escritura de un sistema operativo distribuido. No obstante, algunos problemas no han sido aún resueltos por las ac- tuales implementaciones de RPC. Una de las metas de una llamada RPC es que sea completamente transparente al programa- dor. Supongamos una aplicación que corre en una única UCP que queremos distribuir haciendo uso de llamadas a procedimientos remotos. La total transparencia de RPC supone: 1. La distribución de la aplicación o el sistema operativo no puede conllevar la prohibi- ción de ciertas construcciones en las llamadas a procedimiento remoto que son lega- les en las llamadas a procedimieto local. 2. Tampoco debe requerir de construcciones que antes eran opcionales. Uno de los problemas es el de las variables globales. Una de ellas es errno, para el lenguaje C. El servidor RPC es un proceso en la máquina remota. El cliente es un proceso en la máquina local. Esto significa que la variable errno es diferente en ambos procesos. Por de- finición, esta variable contiene un código de error correspondiente a la última llamada al sis- tema fallida. Si un procedimiento local realiza una llamada al sistema vuelve con error, la va- riable errno tiene el código del error y está disponible a todos los procedimientos del pro- ceso. Falso. A todos los procedimientos del proceso, pero siempre que sean los locales. Los procedimientos remotos ven otra variable errno, la del servidor, que nada tiene que ver con el errno local. La solución de una aplicación distribuida es prohibir el acceso a la variable errno, lo cual viola el segundo principio. Otro problema es el paso de punteros. Es fácil pasar un arbol a un procedimiento local, pero cómo se pasa un árbol a un procedimiento remoto? No se puede pasar el puntero a la estruc- tura padre del arbol, ya que no tiene ningún sentido en la máquina remota.
  • 24. UNIVERSIDAD NACIONAL DE TRUJILLO 24 ESCUELA DE INFORMATICA También la función C printf plantea problemas porque tiene un número de parámetros va- riable. La especificación del lenguaje C no pone límites al número de parámetros de printf. Si nuestra intención es implementar printf como uno de los procedimientos de un servidor RPC, es preciso empaquetar sus parámetros en el cabo antes de enviarlos. El problema es que este es de longitud variable, lo que viola la definición de interfaz del servi- dor, con declaraciones de rutinas de número fijo de parámetros. La solución es no hacer uso de printf remota. Pero esto viola la deseada transparencia de RPC. Hasta aquí hemos tratado algunos de los problemas que hay que superar para dotar de trans- parencia a RPC. Sin embargo, existen problemas mucho más serios, ya que cuestionan la uti- lidad misma del paradigma RPC. Considerar un sistema microkernel en el que el servidor de ficheros, escrito como servidor según el paradigma de la figura 2.9, ha sido dispuesto en otra máquina como un servidor RPC. De esta forma, todos los procesos locales actúan como clientes del servidor de ficheros. Consideremos el mandato UNIX: # sort <f1 >f2 sort ordena su entrada estándar y el resultado se envía a la salida estándar, de modo que puede ser programado como un cliente RPC. Para leer la entrada estándar realiza una llama- da RPC read y para escribir en la salida estándar realiza una llamada RPC write. El mo- delo cliente-servidor encaja perfertamente en la implementación distribuida del sistema de ficheros. Lo mismo ocurre con el mandato # grep qsd <f3 >f4 que busca el patrón qsd en el fichero f3 y escribe en f4 las líneas que lo contienen. Consi- deremos un sistema operativo distribuido en que los procesos se ejecutan en máquinas dife- rentes. Supongamos que grep y sort han sido asignadas a máquinas distinas y el usuario del sistema emite el mandato # grep qsd <f5 | sort >f6 De alguna manera, el sistema operativo debe implementarlo. Consideremos el paradigma cliente- servidor. El cliente se considera el elemento activo, por que de él parten las iniciati- vas de solicitud de servicio. El servidor se comporta como elemento pasivo, ya que no actúa a menos que reciba un estímulo de solicitud de servicio. Según lo hasta ahora establecido, te- nemos un proceso actuando como servidor que es el servidor de ficheros (pasivo) y dos pro- cesos actuando como clientes que son grep y sort (activos) por que así han sido progra- mados. Veamos si esta implementación sirve en esta ocasión. Si grep actúa como cliente, puede solicitar una petición de escritura a sort para enviarle la salida de grep. Sin embar- go, sort debería estar configurado como servidor (pasivo) a fin de recoger la salida de grep cuando grep lo solicite. Sin embargo, hemos decidido escribir sort como un cliente (activo) del sistema de ficheros. Bien sort, bien grep deberían haberse codificado como servidor en lugar de como cliente. El problema es que esta opción, que sirve para un mandato dado, es catastrófica para otro mandato. En general, el modelo cliente servidor no es apro- piado en estado puro en el problema de la tubería # p1 <f3 | p2 | p3 >f2 Son necesarias soluciones más elaboradas. Por ejemplo, la tubería misma puede ser imple- mentada como un proceso servidor que atiende peticiones de lectura y de escritura. Ahora p1, p2 y p3 pueden ser escritos como clientes de las tuberías y del servidor de ficheros. Ni
  • 25. UNIVERSIDAD NACIONAL DE TRUJILLO 25 ESCUELA DE INFORMATICA que decir tiene que esta solución representa una complejidad añadida al sistema operativo. Una solución más sencilla es implementar las pipelines como ficheros temporales en el ser- vidor de ficheros./**/ 2.4 Comunicación de grupos La comunicación RPC tiene dos partes, una, el cliente, dos, el servidor. Hay situaciones en que este modelo no es el idóneo en un sistema con un conjunto de servidores de ficheros re- plicados a fin de proporcionar tolerancia a fallos. Un programa cliente que hace una escritura a disco debe hacer llegar la petición simultánemante a todos los servidores y no a uno de ellos únicamente. El problema puede solucionarse invocando tantas llamadas RPC como ser- vidores existentes. Existe, sin embargo, otro paradigma de comunicación disponible para los sistemas distribuidos que es la comunicación de grupos, más apropiado en casos como este. 2.4.1 Introducción a la comunicación de grupos La característica principal de un grupo de procesos es que cuando se envía un mensaje al grupo, todos sus componentes lo reciben. Por otra parte, los grupos son dinámicos. Los grupos nacen y mueren y en cada grupo terminan algunos procesos y se incorporan otros. Por lo tanto es necesario un mecanismo de gestión de grupos. Un proceso puede pertenecer a más de un grupo y abandonar un grupo para unirse a otro. Un grupo es una abstracción cuyo propósito es evitar, en las llamadas de comunicación con grupos de procesos, parámetros molestos como el número de elementos en el grupo o la localización de cada proceso del grupo y proporcionar primitivas más potentes y transparentes, como el ejemplo anterior de envío de un mensaje a un conjunto de servidores de ficheros. El cliente no debería saber cuantos servidores están disponibles en cada momento ni en qué máquinas concretas han sido arrancados. La implementación de grupos depende mucho del hardware de comunicación disponible. En algunas redes, como ethernet, existen unas direcciones especiales en las que pueden escuchar más de una máquina. Para ello es necesario configurar el adaptador de red ethernet en cada máquina. Un único marco o enviado a esta dirección es leído por todas las máquinas que escuchan en ella. Estas direcciones se denominan multicasting. Si el nivel de enlace de la red soporta multicasting, como es el caso de ethernet, la implementación de grupos es sencilla. Basta asignar a cada grupo una dirección multicasting diferente. Existen redes que si bien no admiten multicasting, sí admiten difusión. Marcos ethernet con la dirección de destino 111...111 son recibidos por todas las máquinas de la red. La difusión puede ser utilizada para implementar grupos, pero es menos eficiente, porque el marco se envía a todas las máquinas, tanto las que pertenecen al grupo como las que no. De todas formas, el envío al grupo de procesos requiere de un solo paquete. Si el nivel de enlace no proporcio- na multicasting ni difusión, aún es posible la implementación de grupos. Para ello, el emisor debe enviar un paquete particular a cada miembro del grupo. Por supuesto, esta es la implementación menos eficiente. 2.4.2 Aspectos de diseño La comunicación de grupos comparte muchos aspectos de la comunicación estándar de paso de mensajes, tales como primitivas con buffer o sin buffer, bloqueantes o no bloqueantes, etc. No obstante, existen más posibilidades adicionales a elegir en la comunicación de grupos. En esta sección examinamos algunos de estos aspectos particulares en la comunicación de grupos. 2.4.2.1 Grupos cerrados frente a grupos abiertos Los protocolos que soportan comunicación de grupos pueden dividirse en dos categorías. Una es la de los grupos cerrados. En ellos sólo los miembros del grupo pueden enviarse mensajes entre sí.
  • 26. UNIVERSIDAD NACIONAL DE TRUJILLO 26 ESCUELA DE INFORMATICA Procesos que no pertenencen al grupo no pueden enviar mensajes al grupo como tal, si bien, por supuesto, sí pueden enviar mensajes particulares a cada miembro del grupo a título particular. Otros protocolos soportan grupos abiertos. Un proceso que no pertenece a un grupo puede enviar mensajes a este grupo. Los grupos cerrados son utilizados típicamente en procesamiento en paralelo, donde los procesos tienen su propio cometido y no interactúan con el mundo exterior. Los grupos abiertos son apropiados para poblemas como el de los servidores replicados, donde un cliente envía una petición al grupo. Los miembros del grupo también necesitan hacer uso de la comunicación en grupo y no sólo un proceso externo, por ejemplo para decidir quién debe ejecutar una petición dada. 2.4.2.2 Grupos de iguales frente a grupos jerárquicos En algunos grupos un proceso es el jefe o coordinador y el resto trabajan para él. En otros, todos los procesos tienen la misma categoría y las decisiones se toman de forma colectiva. En el primer caso, cuando uno de los trabajadores o un cliente externo solicita una petición, esta es enviada al coordinador, que decide cuál de los trabajadores es el más apropiado para servirla. Cada una de estas organizaciones tiene sus ventajas y sus inconvenietes. Los grupos pares no tienen un único punto de fallo. Si un trabajador deja de existir, la carga se reparte en el resto. Sin embargo, incurren en el retraso que supone el ponerse de acuerdo para dedidir quién sirve una petición. Los grupos jerárquicos tienen las propiedades opuestas. 2.4.2.3 Pertenencia a grupos Se necesita un método para crear, destruir y modificar los grupos. Una solución es introducir un proceso denominado el servidor de grupos. El servidor de grupos mantiene tablas con los grupos existentes y sus integrantes. Esta solución es eficiente y fácil de implementar. El problema es que el servidor de grupos es una técnica centralizadora y, como tal, constituye un único punto de fallo. La opción opuesta es la gestión distribuida. Un nuevo proceso que se incorpora al grupo puede enviar un mensaje al grupo y todos los procesos toman nota de su existencia. Cuando un proceso del grupo termina, envía un mensaje de adiós. Surge un problema cuando un proceso del grupo termina inesperadamente. El resto del grupo tiene que descubrirlo experimentalmente, ya que el proceso nunca responde a nada. Cuando todos los miembros lo han constatado, se le da de baja. 2.4.2.4 Direccionamiento de grupos Para dirigir un mensaje a un grupo, el grupo debe tener una dirección. Si el nivel de enlace de la red -en adelante, la red- soporta multicasting, se puede implementar una dirección de grupo como una dirección multicasting. Si la red soporta difusión, pero no multicasting, el mensaje debe ser recibido por todos los núcleos y extraer de él la dirección del grupo. Si ninguno de los procesos de la máquina es miembro del grupo, el mensaje es descartado. En otro caso, es pasado a todos los procesos que pertenecen al grupo. Si la red no soporta ni difusión ni multicasting, el núcleo de la máquina emisora tendrá que tener una lista de los procesos que pertenecen al grupo y enviar un mensaje a cada uno de los componentes del grupo. 2.4.2.5 Primitivas send y receive No es conveniente que los procesos de usuario puedan utilizar las primitivas send y receive por separarado. Según Tanenbaum, send y receive se corresponden en programación distribuida con la construcción "go to" en programación convencional. Su utilización provoca más trastornos que utilidad. Si RPC es la primitiva de comunicación usada por los procesos de usuario, la comunicación de grupo debiera poder constuirse mediante RPC. El problema es tratar con una llamada a procedi- miento que devuelve tantos valores como procesos tiene un grupo. No parece posible, de modo que una aproximación común es volver a las primitivas send y receive en los procesos de usuario.
  • 27. UNIVERSIDAD NACIONAL DE TRUJILLO 27 ESCUELA DE INFORMATICA Si se permite send y receive a los procesos de usuario, se pueden aprovechar estas primitivas para realizar la comunicación de grupo. En el caso de la comunicación convencional cliente servidor, el primer parámetro de send es un número de puerto en la red y el segundo parámetro es el mensaje. Se puede utilizar send para la comunicación de grupos empleando como primer parámetro la dirección de un grupo de procesos en lugar de un puerto determinado. Así unificamos la comunica- ción punto a punto y la comunicación de grupos en una primitiva única. La implementación de send que haga el núcleo o la rutina de biblioteca puede ser una de las tres citadas en el apartado de direccionamiento de grupos. send puede ser con buffer o sin buffer, bloqueante o no bloqueante, fiable o no fiable, etc, igual que en la comunicación punto a punto. La comunicación de grupo no cambia las cosas. Enviar a un grupo obliga al núcleo del sistema que envía a hacer una comunicación multicasting a todos los miembros del grupo, pero ¿qué es recibir de un grupo? Puede entenderse que todos los miembros del grupo van a enviar una réplica diferente y por lo tanto un envío a un grupo debería continuar en el programa de usuario con tantas operaciones receive como miembros tuviese el grupo. Ello, no obstante, significa una pérdida de transparencia, ya que un proceso externo no debe conocer la estructura interna de un grupo. 2.4.2.6 Atomicidad de la difusión Una de las características de la comunicación de grupos es que un mensaje enviado a un grupo debe ser recibido por todos los miembros del grupo o por ninguno de ellos. A esta propiedad se la denomina la atomicidad de la difusión o simplemente la atomicidad. La atomicidad facilita en gran medida la programación de sistemas distribuidos. Supongamos, por ejemplo, una base de datos distribuida. Una base de datos distribuida puede tener una relación cuyos atributos estén repartidos en máquinas dispersas geográficamente. El acceso a una tupla significa enviar un mensaje a todas las máquinas. Supongamos la creación de una tupla de estas características. Si uno de los mensajes se pierde, la base de datos queda en un estado inconsistente. La tupla debe crearse en su totalidad o no crearse y la aplicación ser informada del éxito o del fracaso de la operación entera, no sólo un éxito parcial. Implementar la atomicidad de la difusión no es tan simple como parece. Por ejemplo, uno de los adaptadores de red tal vez acaba de recibir un paquete y antes de que esté preparado para recibir uno nuevo, llega el paquete de difusión, que no puede ser aceptado y simplemente se pierde. Todas las máquinas del grupo han recibido el paquete excepto una, lo que arruina la difusión completa. Para cerciorarse de que todo ha ido bien, el emisor de la difusión debe esperar las confirmaciones de los miembros del grupo. Si una falta, deberá repetir la difusión o reenviar el mensaje en particular. Puede ocurrir que antes de repetir la difusión o hacer el reenvío, el emisor de la difusión se caiga. En esta situación, el cliente debe rearrancar, pero nunca sabrá cuántos son los mensajes que realmente han sido enviados y cuántos los que han fallado. Algunos miembros del grupo han recibido el mensaje y otros no. Una situación inaceptable e ¿incorregible? No, queda alguna esperanza. Existe un algoritmo que demuestra que la atomicidad es posible. El emisor realiza la difusión, inicializa temporizadores y realiza los reenvíos necesarios. Cuando un miembro del grupo recibe un mensaje nuevo, envía el mensaje a todos los miembros del grupo -de nuevo utilizando temporizadores y retransmisiones si son necesarias-. Si el mensaje no es nuevo, simplemente es descartado. No importa cuantas máquinas caigan en el proceso de envíos y reenvíos, lo importante es que de los procesos supervivientes en el grupo todos han recibido el mensaje. 2.4.2.7 Ordenación de mensajes Para que la comunicación en grupo sea fácil de usar y comprender requiere de dos pro- piedades. La primera es la atomicidad, examinada más arriba y la segunda es el orden de los mensajes. Supongamos cinco máquinas, cada una con un proceso. Los procesos 0, 1, 3 y 4 pertenecen a un grupo de procesos. Supongamos que los procesos 0 y 4 deciden enviar un mensaje al resto de los procesos del grupo. Supongamos que el proceso 0 lo ha decidido un
  • 28. UNIVERSIDAD NACIONAL DE TRUJILLO 28 ESCUELA DE INFORMATICA instante de tiempo antes. La propiedad de orden temporal global exige que cada miembro del grupo reciba primero el mensaje del proceso 0 y después el mensaje del proceso 4. Una red local que soporte difusión garantiza el orden temporal global. Todos los mensajes del proceso 0 llegan al resto del grupo ya que el paquete con dirección difusión es recibido por todos los adaptadores de red de forma simultánea. Sólo después, cuando el mensaje ha sido enviado y deja libre el canal el proceso 4 puede emitir su paquete de difusión. Una red sin difusión no garantiza el orden temporal global, que debe implementar la difusión envian- do cuatro mensajes consecutivos que pueden entrelazarse con los del proceso 4. Así, el pro- ceso 1 puede recibir primero el mensaje del proceso 0 y después el del 4 y el proceso 3 puede recibir primero el mensaje del proceso 4 y después el del proceso 0 como indica la figura 2.13. Fig. 2.13 Violación del principio de ordenación tempo- ral global en una red sin difusión. Los mensajes envia- dos se entrelazan. Existen algunas versiones más relajadas del orden temporal global. Una de ellas es el orden temporal consistente. Si los procesos 0 y 4 toman la decisión de enviar los mensajes al gru- po de forma independiente de forma casi instantánea, tal vez no haya forma de saber quien fue el primero en enviar. Tampoco importa, de manera que el sistema elige uno como el pri- mero. A partir de aquí se exige el cumplimiento del principio de orden temporal global. 2.4.2.8 Grupos solapados En el apartado anterior vimos el problema de la ordenación temporal global aplicada a un grupo dado. Dos procesos del mismo grupo enviaban simultáneamente un mensaje al grupo. Hemos mencionado previamente que un proceso puede pertenecer a más de un grupo, de manera que los grupos pueden solaparse. Este solapamiento produce un nuevo tipo de inconsistencia temporal. La figura 2.14 muestra el problema planteado. Los pro- cesos A y D, en distinto grupo, envían simultáneamente un mensaje a su propio grupo. Como en el caso anterior supongamos que la red no proporciona difusión y esta se im- plementa mediante unicasting. El envío simultáneo es consitente si B y C reciben prime- ro el mensaje del grupo 1 y después el mensaje del grupo 2 (o viceversa). Unicasting no puede garantizar esto, de modo que es posible el escenario de la figura 2.14. B recibe el mensaje dirigido al grupo 1 y después el mensaje al grupo 2. C, por el contrario, primero recibe el mensaje dirigido al grupo 2 y después el mensaje al grupo 1.