Bloqueado Ejecutando (Gp:) Listo
Bloqueado
Ejecutando Ejemplo de comunicación con comandos bloqueantes … int x = leerDato(); int y = leerOtroDato(); int z = x + y; String resultado=“Suma=“+z; enviar(procesoII, resultado); … … llamarYoda(); sacarEspadaLaser(); matarSauron(); int z = recibir(procesoI) pagarImpuestos(z); … ProgramaII ProgramaI (Gp:) Listo
Bloqueado Ejecutando (Gp:) Listo
Bloqueado
Ejecutando Ejemplo de comunicación con comandos bloqueantes … int x = leerDato(); int y = leerOtroDato(); int z = x + y; String resultado=“Suma=“+z; enviar(procesoII, resultado); … … llamarYoda(); sacarEspadaLaser(); matarSauron(); int z = recibir(procesoI) pagarImpuestos(z); … ProgramaII ProgramaI (Gp:) Listo
Bloqueado Ejecutando (Gp:) Listo
Bloqueado
Ejecutando Ejemplo de comunicación con comandos bloqueantes … int x = leerDato(); int y = leerOtroDato(); int z = x + y; String resultado=“Suma=“+z; enviar(procesoII, resultado); … … llamarYoda(); sacarEspadaLaser(); matarSauron(); int z = recibir(procesoI) pagarImpuestos(z); … ProgramaII ProgramaI (Gp:) Listo
Bloqueado Ejecutando (Gp:) Listo
Bloqueado
Ejecutando Ejemplo de comunicación con comandos bloqueantes … int x = leerDato(); int y = leerOtroDato(); int z = x + y; String resultado=“Suma=“+z; enviar(procesoII, resultado); … … llamarYoda(); sacarEspadaLaser(); matarSauron(); int z = recibir(procesoI) pagarImpuestos(z); … ProgramaII ProgramaI (Gp:) Listo
Bloqueado Ejecutando (Gp:) Listo
Bloqueado
Ejecutando Ejemplo de comunicación con comandos bloqueantes … int x = leerDato(); int y = leerOtroDato(); int z = x + y; String resultado=“Suma=“+z; enviar(procesoII, resultado); … … llamarYoda(); sacarEspadaLaser(); matarSauron(); int z = recibir(procesoI) pagarImpuestos(z); … ProgramaII ProgramaI (Gp:) Listo
Bloqueado Ejecutando (Gp:) Listo
Bloqueado Mensaje
Ejecutando Ejemplo de comunicación con comandos bloqueantes … int x = leerDato(); int y = leerOtroDato(); int z = x + y; String resultado=“Suma=“+z; enviar(procesoII, resultado); … … llamarYoda(); sacarEspadaLaser(); matarSauron(); int z = recibir(procesoI) pagarImpuestos(z); … ProgramaII ProgramaI Listo Bloqueado Ejecutando (Gp:) Listo
Bloqueado Mensaje
Ejecutando Ejemplo de comunicación con comandos bloqueantes … int x = leerDato(); int y = leerOtroDato(); int z = x + y; String resultado=“Suma=“+z; enviar(procesoII, resultado); … … llamarYoda(); sacarEspadaLaser(); matarSauron(); int z = recibir(procesoI) pagarImpuestos(z); … ProgramaII ProgramaI Listo Bloqueado Ejecutando (Gp:) Listo
Bloqueado Mensaje
Las operaciones de IPC que bloquean al proceso llamante se llaman síncronas Una operación bloqueante solo se desbloquea cuando sucede el evento esperado en el extremo remoto. Es decir, garantizamos que hay una sincronización Existen multitud de APIs de IPC síncronas y es posible programar con ellas Existen también APIs de IPC asíncronas, en las que las llamadas no se bloquean En estos casos, es responsabilidad del programador lograr la sincronización
¿Por qué puede querer alguien llamadas asíncronas? Para evitar bloqueos indefinidos Para mejorar las prestaciones y no desperdiciar ciclos de reloj Ejemplo: programa que recibe de muchas fuentes y almacena paquetes
while(true){ int resultado = recibir(paquete); if(resultado == -1) continue; else almacena(paquete); }
El programador debe saber si trabaja con llamadas síncronas o asíncronas Envío y recepción síncronas
Al desarrollar programas distribuidos, es necesario codificar tanto la parte receptora como la parte emisora ¿qué modelo hay que usar en cada caso? La sincronía/asincronía de las llamadas depende del servicio subyacente Para comprenderlo, necesitamos realizar diagramas de eventos Llamadas síncronas y asíncronas Evento Tiempo Periodo suspendido Proceso E Proceso R Mensaje Obligatorio
El Proceso R (receptor) se bloquea al invocar RECIBIR El Proceso E (emisor) se bloquea al invocar ENVIAR El Proceso R puede continuar ejecutando cuando ha terminado de recibir el mensaje El Proceso E requiere un acuse de recibo (ACK) confirmando una recepción correcta para poder desbloquearse Enviar síncrono y recibir síncrono Proceso E Proceso R ENVIAR RECIBIR Asentimiento El asentimiento forma parte del protocolo que implementa el servicio ICP (es transparente para el programador) El mecanismo enviar-síncrono/recibir-síncrono es aconsejable cuando la lógica de la aplicación de ambos procesos necesita que los datos enviados se reciban antes de continuar con el procesamiento Este mecanismo es utilizado cuando el servicio IPC es de transporte fiable orientado a conexión (p.e. TCP) La realidad puede ser un poco más complicada (bufferes intermedios de recepción, ACKs perdidos, etc)
El Proceso R (receptor) se bloquea al invocar RECIBIR El Proceso E (emisor) no se bloquea al invocar ENVIAR El Proceso E envía el mensaje y continúa sin esperar El Proceso E no requiere un acuse de recibo (ACK) confirmando la recepción Enviar asíncrono y recibir síncrono Proceso E Proceso R ENVIAR RECIBIR Este esquema es apropiado cuando la lógica de la aplicación emisora no depende de la recepción de los datos en el otro extremo Este esquema suele utilizarse cuando el mecanismo IPC subyacente no garantiza que los datos enviados sean, realmente, entregados al receptor (p.e. UDP)
El Proceso R (receptor) no se bloquea al invocar RECIBIR El Proceso E (emisor) se bloquea al invocar ENVIAR El Proceso E envía el mensaje y se bloquea El Proceso E requiere un acuse de recibo (ACK) para desbloquearse Hay 3 escenarios Enviar síncrono y recibir asíncrono Escenario 1 Los datos ya han llegado al Proceso R cuando se invoca RECIBIR En este caso, los datos se entregan al Proceso R inmediatamente Un ACK desbloquea al Proceso E Proceso E Proceso R ENVIAR RECIBIR Asentimiento
Escenario 2 Cuando el Proceso R invoca RECIBIR, los datos no han llegado El Proceso R no recoge ningún dato Para evitar un bloqueo indefinido del Proceso E, es necesario invocar RECIBIR nuevamente Enviar síncrono y recibir asíncrono Cont En este tipo de escenario el receptor se programa como un bucle en el que, cada cierto tiempo, se chequea si hay nuevos datos recibidos A esta técnica se le denomina polling Cuando los datos son finalmente recibidos, el Proceso E puede desbloquearse Proceso E Proceso R ENVIAR RECIBIR Asentimiento RECIBIR RECIBIR
Escenario 3 Cuando el Proceso R invoca RECIBIR, los datos no han llegado El Proceso R no recoge ningún dato Para evitar un bloqueo indefinido del Proceso E, se eleva un evento en el Proceso R cuando los datos realmente se reciben Enviar síncrono y recibir asíncrono Cont. Este evento tiene asociado un manejador, que ejecuta la recepción real de los datos El manejador es un método (función) que se invoca en el momento de la recepción, normalmente en un hilo diferente Para que este esquema funcione, el mecanismo IPC debe implementar el servio de evento con retrollamada
Los tres escenarios se pueden usar cuando se requiere un transporte fiable de los datos (p.e. TCP) y, al mismo tiempo, se requiere que el receptor no se bloquee Proceso E Proceso R ENVIAR RECIBIR Asentimiento Evento
Ninguno de los dos procesos se bloquea Este mecanismo sólo tiene sentido cuando no se requiere un transporte fiable y, además, se usa un mecanismo de eventos con retrollamadas Este esquema no es muy utilizado Enviar asíncrono y recibir asíncrono Proceso E Proceso R ENVIAR RECIBIR Evento
Ventaja clara: facilita la vida del programador a la hora de sincronizar los procesos Inconvenientes: Puede producir bloqueos indefinidos de un proceso (p.e. RECIBIR sin ENVIAR) Puede producir interbloqueos (p.e. los dos extremos llaman a RECIBIR) Es inaceptable cuando se requieren altas prestaciones (p.e. servidores)
Dos estrategias para minimizar los inconvenientes de llamadas síncronas
Estrategia I: Temporizadores La mayoría de las APIs de IPC de red permiten el uso de temporizadores (timeouts) que se pueden utilizar para fijar el tiempo máximo de bloqueo Ejemplo: RECIBIR(procesoRemoto, bufferDatos, 3000)
Revisión crítica del mecanismo de bloqueo RECIBIR timeout Recepcion correcta Continúa el programa Código error o excepción
Estrategia II: Uso de múltiples hilos de ejecución Esta estrategia se utiliza habitualmente para el desarrollo de servidores Consiste en crear hilos específicos para algunas operaciones bloqueantes La operación bloqueante, sólo detiene su propio hilo sin afectar al resto Este tipo de estrategia suele requerir el uso de control de concurrencia Revisión crítica del mecanismo de bloqueo Cont. Proceso Nuevo hilo RECIBIR Nuevo hilo ENVIAR
Definición de Paradigma: “Patrón, ejemplo o modelo” “Estilo o conjunto de prácticas utilizadas para desarrollar un programa” (software) Es decir, identificar los paradigmas de la computación distribuida es identificar los modelos, patrones y prácticas que se utilizan habitualmente para desarrollar programas que funcionan en un sistema distribuido En computación distribuida existen centenares de paradigmas, vamos a identificar los más habituales y populares ordenándolos según su nivel de abstracción Paradigmas de computación distribuida Hardware Cliente–servidor, peer-to-peer RPC y RMI Servicios de red, ORB Espacios de objetos, aplicaciones colaborativas Modelo OSI, modelo TCP/IP Paso de mensajes Nivel de abstracción creciente Estudiado en cursos anteriores Estudiado en este curso No se ve en este curso
El paradigma de paso de mensajes es una abstracción para lograr IPC ¿Qué simplifica esta abstracción? Abstrae todas las complejidades del modelo en capas (es decir, de la red) Servicio con primitivas ENVIAR, RECIBIR, ESPERAR-CONEXIÓN, INICIAR-CONEXIÓN Se logra que la E/S por red sea similar a la E/S típica de ficheros ¿Qué restringe esta abstracción? Hace invisibles (e intocables) los detalles de las capas inferiores (¿Qué pasa si quiero crear un paquete IP falsificando la dirección de origen?) Ejemplo de implementación La API Sockets implementa este modelo
Paradigma de paso de mensajes Proceso E Proceso R Mensaje I Mensaje II
Página anterior | Volver al principio del trabajo | Página siguiente |