La comunicación entre procesos (comúnmente IPC, del inglésInter-Process Communication) es una función básica de los sistemas operativos. Los procesos pueden comunicarse entre sí a través de compartir espacios de memoria, ya sean variables compartidas o buffers, o a través de las herramientas provistas por las rutinas de IPC. La IPC provee un mecanismo que permite a los procesos comunicarse y sincronizarse entre sí, normalmente a través de un sistema de bajo nivel de paso de mensajes que ofrece la red subyacente.
La forma básica de comunicación entre dos procesos o hilos en un sistema operativo con micronúcleo son los mensajes. Un mensaje incluye una cabecera que identifica a los procesos remitente y receptor y un cuerpo que contiene directamente los datos, un puntero a un bloque de datos, o alguna información de control del proceso. Normalmente podemos pensar que las IPC se fundamentan en puertos asociados a cada proceso.
Un puerto es, en esencia, una cola de mensajes destinada a un proceso particular; un proceso puede tener múltiples puertos. Asociada a cada puerto existe una lista que indica qué procesos se pueden comunicar con éste. Las identidades y funcionalidades de cada puerto se mantienen en el núcleo. Un proceso puede concederse nuevas funcionalidades mandando un mensaje al núcleo con las nuevas funcionalidades del puerto.
Los procesos pueden estar ejecutándose en una o más computadoras conectadas a una red. Las técnicas de IPC están divididas dentro de métodos para: paso de mensajes, sincronización, memoria compartida y llamadas de procedimientos remotos (RPC). El método de IPC usado puede variar dependiendo del ancho de banda y latencia (el tiempo desde el pedido de información y el comienzo del envío de la misma) de la comunicación entre procesos, y del tipo de datos que están siendo comunicados.
Conceptos básicos
El sistema operativo provee mínimamente dos primitivas, enviar y recibir, normalmente llamadas send y receive.
Asimismo, debe implementarse un enlace de comunicación entre los procesos de la comunicación.
Este enlace puede ser unidireccional o multidireccional según permita la comunicación en solo uno o en varios sentidos.
Tipos de comunicación
La comunicación puede ser:
Síncrona o asíncrona
Persistente (persistent) o momentánea (transient)
Directa o indirecta
Simétrica o asimétrica
Con uso de buffers explícito o automático
Envío por copia del mensaje o por referencia
Mensajes de tamaño fijo o variable
Síncrona
Quien envía permanece bloqueado esperando a que llegue una respuesta del receptor antes de realizar cualquier otro ejercicio.
Asíncrona
Quien envía continúa con su ejecución inmediatamente después de enviar el mensaje al receptor.
Persistente
El receptor no tiene que estar operativo al mismo tiempo que se realiza la comunicación, el mensaje se almacena tanto tiempo como sea necesario para poder ser entregado (Ej.: e-Mail).
Momentánea (transient)
El mensaje se descarta si el receptor no está operativo al tiempo que se realiza la comunicación. Por lo tanto, no será entregado.
Directa
Las primitivas enviar y recibir explicitan el nombre del proceso con el que se comunican.
Ejemplo:
enviar (mensaje, A) envía un mensaje al proceso A
Es decir se debe especificar cual va a ser el proceso fuente y cual va a ser el proceso Destino.
Las operaciones básicas Send y Receive se definen de la siguiente manera:
Send (P, mensaje); envía un mensaje al proceso P (P es el proceso destino).
Receive (Q, mensaje); espera la recepción de un mensaje por parte del proceso Q (Q es el proceso fuente).
Nota: Receive puede esperar de un proceso cualquiera, un mensaje, pero el Send sí debe especificar a quién va dirigido y cuál es el mensaje.
Indirecta
La comunicación Indirecta: Es aquella donde la comunicación está basada en una herramienta o instrumento ya que el emisor y el receptor están a distancia.
Simétrica
Todos los procesos pueden enviar o recibir. También llamada bidireccional para el caso de dos procesos.
Es una comunicación equilibrada donde tanto emisor como receptor reciben la misma información.
Asimétrica
Un proceso puede enviar, los demás procesos solo reciben. También llamada unidireccional.
Suele usarse para hospedar servidores en Internet.
Tipos de comandos
Comandos paralelos
Un comando paralelo especifica la ejecución concurrente de sus procesos constituyentes. Todos comienzan simultáneamente y el comando paralelo termina con éxito solo siempre y cuando todos hayan terminado con éxito.
Comandos de asignación
Un comando de asignación especifica la evaluación de una expresión y asignación de un valor denotado como variable destino. Una variable simple puede tener un valor simple o estructurado.
Cuando una asignación falla es cuando el valor de su expresión es indefinido, o si es que el valor no coincide.
Comandos Input and Output
Los comandos de entrada y de salida especifican la comunicación entre dos procesos secuenciales que operan al mismo tiempo. El proceso se puede implementar en hardware o en los procesos paralelos. La comunicación ocurre de la siguiente manera:
Un comando da entrada a un proceso
Un comando de salida en otro proceso especifica como su destino el nombre del primer proceso
La variable de destino del comando coincide con el valor denotado por la expresión del comando de salida.
Un comando de entrada falla si se termina su fuente, un comando de salida falla si se termina su destino o si su expresión no está definida.
Comandos alternativos y repetitivos
Un comando alternativo especifica la ejecución de exactamente uno de sus comandos custodiados constituyentes. Como consecuencia, si todos los guardias fallan, el comando alternativo falla. De lo contrario, uno arbitrario con ejecutable con éxito se selecciona y ejecuta la guardia.
Un comando repetitivo especifica tantas iteraciones como posible de su mando alternativo constituyente. Como consecuencia, cuando todos los guardias fallan, el comando repetitivo termina sin efecto. De lo contrario, el comando alternativo
se ejecuta una vez y luego todo el comando repetitivo se ejecuta de nuevo.
Uso de buffers automático
El transmisor se bloquea hasta que el receptor recibe el mensaje (capacidad cero).
RPC
(Remote Procedure Call / llamada a un procedimiento remoto) Permitir que los programas realicen llamadas a funciones localizadas en otras máquinas. Los programadores no se tienen que preocupar por los detalles de la programación de la red. Conceptualmente simple.
Desde el punto de vista de un programador la llamada a una función remota es y funciona de la misma manera que lo haría si la llamada fuese local. En este sentido, se logra transparencia.
Cada función pasa a tener dos partes: cliente, la máquina local donde se implementa la interface (prototipo de una función) para invocar las funciones remotas. Servidor, implementación de las funciones propiamente dichas. :>
Paso de parámetros
No debería de existir ningún problema si dos máquinas son homogéneas, sin embargo la realidad no suele ser ésta. Pueden surgir problemas de diferentes codificación de caracteres (ej.: mainframe IBM: EBCDIC, IBM PC: ASCII) o diferentes tipos de ordenación de bytes (ej.: Intel: little endian, Sun SPARC: big endian).
Como solución a estos problemas es importante lograr un acuerdo del protocolo usado. La parte encargada de generar los mensajes no debe de presuponer el uso de un lenguaje de programación específico.
Es un mecanismo de expansión de RPC cuyo objetivo es dar soporte a sistemas orientado a objetos.
La idea es tener objetos distribuidos. Para acceder al estado de un objeto solo se realiza a través de métodos definidos por un objeto interface. Un objeto ofrece múltiples interfaces. Un interface puede ser implementado por múltiples objetos.
Comunicación orientada a mensajes
Las comunicaciones RPC se basan en la idea de que el receptor esté operativo para poder invocar una cierta función. No obstante, no podemos suponer que el receptor siempre estará operativo y esperando a comunicarse. La solución es definir la comunicación en término de paso de mensajes.
Mensajes momentáneos vs. mensajes persistentes
Momentáneos: no soportan el envío de mensajes persistentes. (1) Sockets, (2) Message-passing interface (MPI).
accept: queda bloqueado hasta la llegada de un pedido de conexión.
connect: pedido de establecimiento de conexión.
send: enviar datos por la conexión.
receive: recibir datos por la conexión.
close: desvincula el socket la dirección local.
Message-passing interface (MPI)
Diseñado para aplicaciones paralelas crea un nivel de abstracción más alto que el provisto por sockets. Provee una interface con primitivas más avanzadas. Por el contrario cuenta con una gran cantidad de implementaciones (librería y protocolos) propietarias lo que genera la necesidad de una interfaz estándar.
MPI API:
MPI_bsend: vincula la salida de mensajes con el buffer de salida local.
MPI_send: envía un mensaje y espera hasta que es copiado al buffer.
MPI_send: envía un mensaje y espera hasta que el receptor inicie.
MPI_sendrecv: envía un mensaje y espera respuesta.
MPI_isend: pasa la referencia de un mensaje y continúa.
MPI_issend: para la referencia de un mensaje y espera hasta que el receptor inicie.
MPI_recv: recibe un mensaje; se bloquea en el caso de no haberlo.
MPI_irecv: verifica si hay mensajes entrantes; no se bloquea.
Persistentes: el mensaje se encola y se entrega cuando se pide. (1) Message-oriented middleware (MOM)
Monitores y programación
Un monitor puede ser considerado como un único proceso que se comunica con más de un proceso de usuario. Sin embargo, cada proceso de usuario debe tener un nombre diferente (por ejemplo, productor, consumidor) o un subíndice diferente (por ejemplo, X (0) y cada comunicación con un usuario debe identificar su origen o destino de forma única.
En consecuencia, cuando un monitor se dispone a comunicarse con cualquiera de sus procesos de usuario (es decir, con el que llame primero) utilizará un comando guardado con un rango. Por ejemplo: [(i: 1... 100) X (0! (parámetros de valor) --> X (0! (resultados)]. Aquí, la variable vinculada i se utiliza para enviar los resultados de vuelta al proceso de llamada. Si el monitor no está preparado para aceptar la entrada de algún usuario en particular (por ejemplo, X(j)) en una ocasión determinada, el comando de entrada puede ser precedido por una guardia booleana. Por ejemplo, dos entradas sucesivas del mismo proceso son inhibidas por j = 0; *[(i: 1... 100) i # j; X (0! (valores) --> j...i]. Cualquier intento de salida de X(j) se retrasará hasta una iteración posterior, después de que la salida de algún otro proceso X(i) haya sido aceptada y tratada.
Del mismo modo, las condiciones se pueden utilizar para retrasar la aceptación de las entradas que violarían las restricciones de programación - posponiéndolas hasta alguna ocasión posterior en la que algún otro proceso haya llevado al monitor a un estado en el que la entrada pueda ser aceptada válidamente. Esta técnica es similar a una región crítica condicional y evita la necesidad de variables especiales de sincronización como eventos, colas o condiciones. Sin embargo, la ausencia de estas facilidades especiales ciertamente hace más difícil o menos eficiente la resolución de problemas que involucran prioridades--por ejemplo, la programación del movimiento de cabezas en un disco.
Buffer limitado
Problema: Construir un proceso de buffering X para suavizar las variaciones en la velocidad de salida de porciones por un proceso productor y de entrada por un proceso consumidor. ¡El consumidor contiene pares de órdenes X! more (); X! p, y el productor contiene órdenes de la forma X! p. El buffer debe contener hasta diez porciones. Solución:
X::
buffer:(0...9) portion;
in, out:integer, in >=0; out >=0;
comment 0 <= out <=in <= out+10;
(in < out + 10; producer?buffer(in mod 10) -> in >= +1
(out < in; consumer?more() -> consumer?buffer(out mod 10);
out >= out+1)
Cuando out < in < out + 10, la selección de la alternativa en el comando repetitivo dependerá de si el productor produce antes que el consumidor, o viceversa. Cuando out -- in, el buffer está vacío y la segunda alternativa no puede ser seleccionada, aunque el consumidor esté listo con su comando X!more(). Sin embargo, después de que el productor haya producido su siguiente porción, la petición del consumidor puede ser concedida en la siguiente iteración. Observaciones similares se aplican al productor, cuando in -- out + 10. X está diseñado para terminar cuando out = in y el productor ha terminado.
Implementaciones
Hay un número de API que pueden ser usadas por IPC. Un número de plataformas independientes de API incluidas las siguientes:
Las siguientes son plataformas específicas de API:
Apple Computer's Apple events (previamente conocido como Interapplication Communications (IAC)).
Freedesktop.org's D-Bus
KDE's Desktop Communications Protocol (DCOP)
Libt2n parar C++ solamente, manejos de objetos y excepciones complejos.
The Mach kernel's Mach Ports
Microsoft's ActiveX, Component Object Model (COM), Distributed Component Object Model (DCOM), Dynamic Data Exchange (DDE), Object Linking and Embedding (OLE), anonymous pipes, named pipes, Local Procedure Call
Novell's SPX
POSIX mmap, message queues, semaphores, and Shared memory
RISC OS's messages
Solaris's Doors
System V's message queues, semaphores, and Shared memory
Message-oriented middleware o Message-queuing systems
Aparece un tercer componente de la conexión que realiza tareas de almacenamiento de mensajes. Esto permite que el emisor y el receptor estén inactivos. Permite comunicaciones persistentes asíncronas. Transferencia de mensajes que duren minutos a comparación de segundos o milisegundos. La aplicación más conocida que utiliza dicho modelo es el correo electrónico (e-Mail).
La idea básica consiste en insertar (putting) o quitar (taking) mensajes en una cola. Al emisor solo se le puede garantizar que el mensaje ha sido insertado correctamente en la cola. No existen garantías de cuándo será leído dicho mensaje.
No está ligado a ningún tipo específico de modelo de red.
Message-queuing system API:
put: añadir un mensaje a una cola.
get: bloquear hasta que la cola no esté vacía, luego quitar el primer elemento.
poll: verificar si hay mensaje, quitar el primero. Nunca se bloquea.
notify: instalar en la cola un dispositivo que avisará cuando un nuevo mensaje se inserte en la cola.
Comunicación orientada a streams
Los modelos RPC, RMI y MOM realizan comunicaciones independientes del tiempo. Existen también sistemas donde el tiempo es crucial en la comunicación, o los resultados de salida serán incorrecto; es así el caso de trasmisión de audio, video, sensor de datos, etc. (comunicación continua de datos) donde cortes de comunicación generan retardos no deseados.
Comunicación entre procesos Linux
La comunicación puede simplemente ser cuestión de dejar que otro proceso sepa que ha ocurrido algún evento, o puede implicar la transferencia de datos de un proceso a otro.
Señales
El mecanismo estándar para informar a un proceso que ha ocurrido un evento es la señal. Se pueden enviar señales de un proceso a otro pero sin enviar información. Las señales no necesitan ser generadas por otro proceso, también puede ser generada por el kernel.
Linux también implementa un mecanismo de semáforos. Un proceso puede esperar un semáforo tan fácilmente como espera una señal.
Paso de datos entre procesos
El mecanismo de tubería (pipe) estándar permite a un proceso hijo heredar un canal de comunicación con su padre; los datos que se escriben en un extremo de la tubería se leen en el otro. También define un conjunto de servicios para trabajo en red que pueden enviar flujos de datos tanto a procesos locales como remotos.
Hay otro método que es la memoria compartida que ofrece una forma extremadamente rápida de comunicar cantidades grandes o pequeñas de datos; cualquier dato escrito por un proceso en una región de memoria compartida puede ser leído por cualquier otro proceso que haya mapeado dicha región en su espacio de direcciones.
Freedesktop
Para comunicación entre aplicaciones gráficas existe D-Bus, usado por GNOME y KDE entre otros. Permite fácilmente comunicar unas aplicaciones con otras o controlar cualquier elemento de una interfaz gráfica desde consola a con un programa hecho al efecto.
Comunicación multicast
Es la abstracción de diseminación de datos. Utilizando el soporte de difusión (broadcast) en las redes locales para realizar tareas como protocolos epidémicos.
La mayoría de los Sistemas Operativos; algunos, como Windows, solo implementan señales en las librerías de C run-time de C y actualmente no proveen soportes para su uso como técnica de IPC.