Programación Concurrente y Tiempo Real Tema 3. Paso de Mensajes Escuela Superior de Informática Universidad de Castilla-La Mancha Curso 2011/2012 Grado en Ing. Informática Tema 3. Paso de Mensajes 1. Conceptos básicos [Stallings 5.5] 2. Implementación [Rochk 7.4, 7.7] 3. Problemas clásicos de sincronización Curso 2011/2012 Grado en Ing. Informática Conceptos | Implementación | Problemas Fundamentos básicos Info a compartir Espacio de direcciones de p0 Curso 2011/2012 Mensaje Mecanismo de comunicación entre procesos (IPC) del sistema operativo Copia de info Espacio de direcciones de p1 Trp 3 de 25 Conceptos | Implementación | Problemas Fundamentos básicos ● Concepto de cola o buzón de mensajes Proceso1 send () Message Message Mensaje receive () Proceso2 Cola de mensajes Curso 2011/2012 Trp 4 de 25 Conceptos | Implementación | Problemas Fundamentos básicos Proceso 1 Proceso 2 while (1) { // W_previo_1 send ('*', P2) // W_restante_1 } while (1) { // W_previo_2 receive (&msg, P1) // W_restante_2 } Sincronización (P2 no avanza hasta que no recibe de P1) Curso 2011/2012 Trp 5 de 25 Conceptos | Implementación | Problemas Fundamentos básicos Aspectos de diseño en el paso de mensajes Sincronización Receive Send Bloqueante ●No bloq. ● Bloqueante ●No bloq. ●Comprob. llegada ● Curso 2011/2012 Direccionamiento Directo Send ●Receive ● Indirecto Estático ●Dinámico ●Propiedad ● Formato Contenido Disciplina de cola Longitud ● ● FIFO Prioridad Fija Variable Trp 6 de 25 Conceptos | Implementación | Problemas El problema de la sección crítica do { SECCIÓN_ENTRADA SECCIÓN_CRÍTICA SECCIÓN_SALIDA SECCIÓN_RESTANTE while(1); Curso 2011/2012 Trp 7 de 25 Conceptos | Implementación | Problemas El problema de la sección crítica do { receive (buzón, &msg) SECCIÓN_CRÍTICA send (buzón, msg) SECCIÓN_RESTANTE while(1); Curso 2011/2012 ¡La cola de mensajes actúa de semáforo! Mutex ~ Cola 1 msg Semáforo contador ~ Cola n msg Trp 8 de 25 Conceptos | Implementación | Problemas POSIX Message Queues Apertura de una cola de mensajes #include <fcntl.h> #include <sys/stat.h> #include <mqueue.h> // Para constantes O_*. // Para los permisos. // Devuelve el descriptor de la cola de mensajes // o -1 si hubo error (ver errno). mqd_t mq_open ( const char *name, // Nombre de la cola. int oflag // Flags (menos O_CREAT). ); mqd_t mq_open ( const char *name, int oflag mode_t perms, struct mq_attr *attr ); Curso 2011/2012 // // // // Nombre de la cola. Flags (incluyendo O_CREAT). Permisos. Atributos (o NULL). Trp 9 de 25 Conceptos | Implementación | Problemas POSIX Message Queues Ejemplo de creación // Descriptor de cola de mensajes. mqd_t qHandler; int rc; struct mq_attr mqAttr; // Estructura de atributos. mqAttr.mq_maxmsg = 10; // Máximo nº de mensajes. mqAttr.mq_msgsize = 1024; // Tamaño máximo de mensaje. // Creación del buzón. qHandler = mq_open(“/prueba”, O_RDWR | O_CREAT, S_IWUSR | S_IRUSR, &mqAttr); // Manejo de errores. if (qHandler == -1) { fprintf(stderr, "%s\n", strerror(errno)); exit(EXIT_FAILURE); } Curso 2011/2012 Trp 10 de 25 Conceptos | Implementación | Problemas POSIX Message Queues Cierre de la cola de mensajes #include <mqueue.h> int mq_close ( mqd_t mqdes ); // Descriptor de la cola de mensajes. Eliminación de la cola de mensajes #include <mqueue.h> int mq_unlink ( const char *name ); Curso 2011/2012 // Nombre de la cola. Trp 11 de 25 Conceptos | Implementación | Problemas POSIX Message Queues Envío / recepción de mensajes #include <mqueue.h> int mq_send ( mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned msg_prio ); // // // // Descriptor de la cola. Mensaje. Tamaño del mensaje. Prioridad. ssize_t mq_receive ( mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio ); // // // // Descriptor de la cola. Buffer para el mensaje. Tamaño del buffer. Prioridad o NULL. Curso 2011/2012 Trp 12 de 25 Conceptos | Implementación | Problemas Recibiendo mensajes... Ejemplo de recepción bloqueante mqd_t qHandler; int rc; unsigned int prioridad; char buffer[2048]; rc = mq_receive(qHandler, buffer, sizeof(buffer), &prioridad); if (rc == -1) fprintf(stderr, "%s\n", strerror(errno)); else printf ("Recibiendo mensaje: %s\n", buffer); ¡El buffer de recepción ha de ser mayor o igual a mq_msgsize! Curso 2011/2012 Trp 13 de 25 Conceptos | Implementación | Problemas Enviando mensajes... Ejemplo de envío [no] bloqueante mqd_t qHandler; int rc; unsigned int prioridad; char buffer[512]; sprintf (buffer, "[ Saludos de %d ]", getpid()); mq_send(qHandler, buffer, sizeof(buffer), 1); ¡El buffer de envío ha de ser menor o igual a mq_msgsize! Curso 2011/2012 Trp 14 de 25 Conceptos | Implementación | Problemas Custom messages ● Muchos APIs utilizan char* como buffer genérico... ¡Considera un puntero a un buffer junto con el tamaño del buffer para usar tus TADs! Curso 2011/2012 Trp 15 de 25 Conceptos | Implementación | Problemas Custom messages Ejemplo de uso de custom data typedef struct { int valor; } TData; TData buffer; // Atributos del buzón. mqAttr.mq_maxmsg = 10; mqAttr.mq_msgsize = sizeof(TData); // Recepción. mq_receive(qHandler, (char *)&buffer, sizeof(buffer), &prioridad); // Envío. mq_send(qHandler, (const char *)&buffer, sizeof(buffer), 1); Curso 2011/2012 Trp 16 de 25 Conceptos | Implementación | Problemas POSIX Message Queues Notificación de mensajes #include <mqueue.h> int mq_notify ( // Descriptor de la cola. mqd_t mqdes, // Estructura de notificación. // Contiene funciones de retrollamada // para notificar la llegada de un nuevo mensaje. const struct sigevent *sevp ); Curso 2011/2012 Trp 17 de 25 Conceptos | Implementación | Problemas El problema del bloqueo ● ● Con POSIX Message Queues, no es posible recuperar mensajes por tipo ¿Cómo atender distintas peticiones (tipos de tareas) de manera eficiente? ● Sin bloquearse en una cola... ● Ver qt_notify () ● Ver [Roch 5.18] Curso 2011/2012 Trp 18 de 25 Conceptos | Implementación | Problemas Esquema beeper ● Procesos bloqueados (receive ()) a la espera de una tarea (mensaje) 1 Proceso1 Curso 2011/2012 re e ceiv () receive () Buzón Beeper Proceso2 r ec e iv e () Proceso3 Trp 19 de 25 Conceptos | Implementación | Problemas Esquema beeper receive () ¡Garantiza no bloqueo! Buzón Beeper r ec eiv e () Proceso2 Proceso1 Proceso3 2 receive () Buzón A Curso 2011/2012 Buzón B Trp 20 de 25 Conceptos | Implementación | Problemas Productor/Consumidor while (1) { // Producir... producir(); // Nuevo item... send (buzón, msg); } Se bloquea si la cola está llena Curso 2011/2012 Se bloquea si no hay elementos (mensajes) while (1) { recibir (buzón, &msg) // Consumir... consumir(); } Trp 21 de 25 Conceptos | Implementación | Problemas Filósofos comensales Proceso filósofo while (1) { // Pensar... wait(palillos[i]); wait(palillos[(i+1) % 5]); // Comer... signal(palillos[i]); signal(palillos[(i+1) % 5]); } Curso 2011/2012 Trp 22 de 25 Conceptos | Implementación | Problemas Filósofos comensales Proceso filósofo while (1) { // Pensar... receive(mesa, &m); receive(palillo[i], &m); receive(palillo[i+1], &m); // Comer... send(palillo[i], m); send(palillo[i+1], m); send(mesa, m); } Curso 2011/2012 Trp 23 de 25 Conceptos | Implementación | Problemas Los fumadores de cigarrillos Tabaco Papel Fósforos Agente Curso 2011/2012 Tabaco Papel Fósforos Fumador1 Fumador2 Fumador3 Tabaco Papel Trp 24 de 25 Conceptos | Implementación | Problemas Traducción de cadenas ● Sesión 4 Laboratorio Curso 2011/2012 Trp 25 de 25