Mensajería
Es una unidad de información que se intercambia entre dos o más procesos.
Mediante los mensajes podemos transmitir información y sincronizar procesos (mediante la espera de un cierto mensaje).
Los sistemas operativos generalmente ofrecen dos llamadas al sistema (o primitivas básicas) para los procesos, enviar y recibir mensajes:
- send(mensaje): Para enviar un mensaje
- receive(mensaje): Para recibir un mensaje
Contenido
Destino y fuente
- Denominación Directa
- Se emplea ID para identificar al destinatario.
- Valores especiales: BROADCAST (a todos), MULTICAST (a un grupo).
- Denominación Indirecta
- Se emplea un elemento intermediario.
- Recurso compartido especial en el sistema: BUZÓN.
- Habiendo intermediarios, hay que comprobar las identidades pues pueden ser falsas/erróneas
Formas de transmisión
- Transmisión por copia
- Directa: el mensaje se copia de espacio de emisor a espacio de receptor.
- Indirecta: el mensaje se copia de espacio de emisor a espacio (buzón) de SO, y de ahí a espacio de receptor.
- Transmisión por referencia
- Directa: lo que se copia es un puntero al mensaje
- Global: el emisor crea mensaje en espacio de SO, y se copia a espacio de receptor un puntero al mismo.
- Transmisión por copia de escritura: el mensaje sólo se copia si se modifica por emisor o receptor.
Formas de comunicación
- Comportamiento del emisor, send()
- Síncrona: el proceso emisor que realiza el send() queda bloqueado hasta que el receptor llama a recv()
- Asíncrona: suponemos capacidad de almacenamiento en el destinatario o en el buzón. Allí acumulamos los mensajes entrantes y el receptor irá leyendo cuando pueda. Es más ágil pero el destinatario/buzón necesita capacidad de almacenamiento, la cual será limitada y los mensajes posteriores pueden caer en saco roto
- Comportamiento del receptor, recv()
- Bloqueante: un recv() sin mensajes a procesar pasa a estado bloqueado. Si se hace un send() vuelve a estado preparado
- No bloqueante: recv() sin mensajes a procesar devuelve un "prueba más tarde"
Formato de los mensajes
Fijo
Los procesos acuerdan emplear un formato fijo para sus mensajes.
Ejemplo: Simple Network Time Protocol. Ver http://tools.ietf.org/html/rfc4330, sección 4, Message Format.
1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |LI | VN |Mode | Stratum | Poll | Precision | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Root Delay | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Root Dispersion | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Reference Identifier | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | Reference Timestamp (64) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | Originate Timestamp (64) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | Receive Timestamp (64) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | Transmit Timestamp (64) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Key Identifier (optional) (32) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | | | Message Digest (optional) (128) | | | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Variable
- Type-Length-Value.
Ejemplo: Usado en Netlink para la codificación de atributos de un mensaje. Ver Communicating between the kernel and user-space in Linux using Netlink Sockets (1984.lsi.us.es/~pablo/docs/spae.pdf).
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Length | Type | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / / / Value / / / /////////////////////////////////////////////////////////////////
- Text-based human-readable.
- Comma-Separated Value (CSV): http://en.wikipedia.org/wiki/Comma-separated_values
- Extensible Markup Language (XML): http://en.wikipedia.org/wiki/XML
- JavaScript Object Notation (JSON): http://en.wikipedia.org/wiki/JSON
Mixto
Los procesos acuerdan emplear mensaje con partes cuyo formato es fijo, como por ejemplo una cabecera inicial, seguido de partes de tamaño variable.
Ejemplo: Internet Protocol (IPv4). Ver http://www.ietf.org/rfc/rfc791.txt, sección 3.1.
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Version| IHL |Type of Service| Total Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Identification |Flags| Fragment Offset | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Time to Live | Protocol | Header Checksum | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Source Address | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Destination Address | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Options | Padding | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ / / / Payload / / / /////////////////////////////////////////////////////////////////
Mensajería a través de la red
- Unidad del destinatario
- Fiabilidad en la transmisión
- Formato de los datos (http://www.cs.umd.edu/class/sum2003/cmsc311/Notes/Data/endian.html): Enviar un entero a través de la red puede ser un problema debido a la forma en el que se representan los datos en la memoria dependiente de la arquitectura. Por ejemplo, un PC con arquitectura Intel x86 emplea formato little-endian, mientras que un SPARC de Sun Microsystems (ahora Oracle) emplea big-endian.
- Little Endian: Bytes menos significativo al principio.
int main(void)
{
int a = 10, i;
char *p = &a;
for (i=0; i<sizeof(a); i++) {
printf("posición %d: %.2x\n", i, p[i]);
}
}
Muestra el siguiente resultado en un PC:
posición 0: 0a (n+3) posición 1: 00 (n+2) posición 2: 00 (n+1) posición 3: 00 (n)
- Big Endian: Bytes menos significativo al final.
posición 0: 00 (n) posición 1: 00 (n+1) posición 2: 00 (n+2) posición 3: 0a (n+3)
En Internet se sigue la convención de expresar datos en Big Endian, habría que hacer la conversión. Habría que usar ntohl (network to host long).
En little-endian, la implementación de ntohl es la siguiente:
- define __constant_ntohl(x) ___constant_swab32((__be32)(x)
Ver /usr/include/linux/byteorder/little_endian.h
mientras que en big-endian es:
- define __constant_ntohl(x) ((__u32)(__be32)(x))
Si empleamos formato textuales, como CSV, XML o JSON, que codifican la información en bytes, no tenemos este problema.