Tema 2 Comunicación y sincronización entre procesos

Documentos relacionados
SISTEMAS OPERATIVOS:

SISTEMAS OPERATIVOS: COMUNICACIÓN Y SINCRONIZACIÓN ENTRE PROCESOS. Hilos y mecanismos de comunicación y sincronización

Sistemas operativos: una visión aplicada. Capítulo 5 Comunicación y sincronización de procesos

Sistemas operativos: una visión aplicada. Capítulo 5 Comunicación y sincronización de procesos

Procesos ligeros. Arquitectura de Computadores II Universidad Carlos III de Madrid

SISTEMAS OPERATIVOS: PROCESOS. Hilos y Procesos

Programación Concurrente

Comunicación y Sincronizacion de procesos. Ingeniería del Software EUITI UPM. Seccion critica Productor consumidor Lectores escritores

Sincronización de Threads

Analista Universitario en Sistemas. Sistemas Operativos. Instituto Politécnico Superior THREADS

Comunicación y Sincronizacion de procesos. Ingeniería del Software EUITI UPM

SISTEMAS OPERATIVOS: COMUNICACIÓN Y SINCRONIZACIÓN ENTRE PROCESOS. Desarrollo de servidores concurrentes

Informática Electrónica Concurrencia

SISTEMAS OPERATIVOS: COMUNICACIÓN Y SINCRONIZACIÓN ENTRE PROCESOS. Procesos concurrentes y problemas en la comunicación y la sincronización

Sistemas operativos. Comunicación y sincronización de procesos

Nº Mat. Calificación APELLIDOS NOMBRE. CURSO 4º GRUPO Julio 2014 ASIGNATURA: SISTEMAS INFORMÁTICOS INDUSTRIALES

Tema 4 El paradigma cliente-servidor

Biblioteca de sistema

SISTEMAS OPERATIVOS:

Sistemas operativos: una visión aplicada. Capítulo 3 Procesos

Sincronización de procesos

Unidad 1: Gestión de Procesos

SISTEMAS OPERATIVOS:

Fundamentos de los Sistemas Operativos

Sistemas Operativos: Programación de Sistemas. Curso Oscar Déniz Suárez Alexis Quesada Arencibia Francisco J.

Hilos Secciones Stallings:

SISTEMAS OPERATIVOS Manejo de procesos

Acceso coordinado a recursos compartidos

T5-multithreading. Indice

Estándares POSIX. Estándares base

Sistemas operativos. Hasta ahora hemos visto. Relación programa-sistema operativo Gestión de memoria

Programación de Multitareas utilizando Hilos

Clases 04 y 05: Repaso de programación de sistemas basados en UNIX

Función monitoreo descriptor archivo #include <sys/types.h> #include<unistd.h> #include<errno.h> extern void procesamiento_datos(char *, int); void pr

Sistemas Operativos. Procesos

Capítulo 2 Introducción a los sistemas operativos

Informática I Threads

PROCESAMIENTO DISTRIBUIDO

26/01/2010. Espera activa Semáforos Problemas clásicos de com. y sin. Servicios POSIX

Bloque I: Principios de sistemas operativos

Procesos y Threads Procesos y Threads. Concurrencia Concurrencia Ventajas Ventajas. Rendimiento Rendimiento (paralelismo) (paralelismo)

Fundamentos de los Sistemas Operativos. Tema 2. Procesos José Miguel Santos Alexis Quesada Francisco Santana

ISO Tema 8,

Concurrencia de Procesos

Programación Concurrente

PROGRAMACIÓN MULTITHREADING

Taller de Programación Paralela

Concurrencia Monitores. Guillermo Román Díez

Procesos e hilos: cálculo de

Programación Concurrente Recopilación de teoría referente a la materia

Contenido 1. INTRODUCCIÓN A LOS SISTEMAS OPERATIVOS PROCESOS Prólogo...

Sincronización de Hilos POSIX

Threads. Hilos - Lightweight process - Procesos ligeros

Programación Concurrente y Paralela. Unidad 1 Introducción

Plataformas de Tiempo Real

Sistemas Operativos 1

Comunicación y sincronización

UNIVERSIDAD CARLOS III DE MADRID DEPARTAMENTO DE INFORMÁTICA INGENIERÍA EN INFORMÁTICA. ARQUITECTURA DE COMPUTADORES II 10 junio de 2006

MC Hilda Castillo Zacatelco PROCESOS

PARTE II PROGRAMACION CON THREADS EN C

Ejercicios sobre tuberías

Comunicación y sicronización de procesos

Si un candado mutex es usado por hilos en el mismo proceso pero no por hilos en diferentes procesos, los primeros dos pasos pueden simplificarse a:

Capítulo 5 Comunicación y sincronización de procesos

PROCESOS E HILOS - Hilo

Tema 3. Paso de mensajes. mensajes. Bibliografía. Sistemas de paso de mensajes (2) Sistemas de paso de mensajes. Ventajas del paso de.

SISTEMAS OPERATIVOS PROCESOS. Pedro de Miguel Anasagast

Bloque I: Principios de sistemas operativos

Comunicación entre Procesos

6. Enumere tres ventajas de los ULT frente a los KLT.

Tema 1: Programación Multiproceso. Curso

ESCUELA DE INGENIERIA Informática Y Sistemas

Formatos para prácticas de laboratorio

Procesos Definición y Estados

Concurrencia. Primitivas IPC con bloqueo

Concurrencia en UNIX / LINUX. Introducción: Procesos e Hilos POSIX

TEMA 3. CONCEPTOS FUNDAMENTALES DEL NIVEL DEL SISTEMA OPERATIVO. Definición y objetivos de un S.O

SISTEMAS OPERATIVOS INTRODUCCIÓN. Pedro de Miguel Anasagast

Entorno de programación de nivel 1: La librería PCAP

Plataformas de Tiempo Real

*** SOLUCIONES *** SISTEMAS OPERATIVOS Examen Parcial 24 de Abril de 2010

Hilos de ejecución POSIX

Taller de Programación Paralela

Sistemas Operativos sesión 12: tuberías

Funciones POSIX III Funciones POSIX III. No Nombrados Nombrados. sem_open sem_open. sem_close sem_close. sem_unlink sem_unlink

Concurrencia, exclusión mutua y sincronización. Capítulo 5 HungriaBerbesi

Sistemas operativos: una visión aplicada. Capítulo 3 Procesos. Contenido

Taller de pthreads. Sistemas Operativos. Verano de 2009

dit Programación concurrente Sincronización condicional UPM

Prácticas de Sistemas operativos

de Gran Canaria Centro de Tecnología Médica Programación Concurrente

Tema 4: Gestión de Procesos

Funciones POSIX (I): Introducción

Procesos. Procesos. Sistemas Operativos Procesos KMC 2017

Message Passing Interface (MPI)

Interbloqueo. Concurrencia: Interbloqueo e Inanición

Universisdad de Los Andes Facultad de Ingeniería Escuela de Sistemas

Guillermo Román Díez

Transcripción:

Tema 2 Comunicación y sincronización entre procesos Grupo ARCOS Grado en Ingeniería Informática Universidad Carlos III de Madrid

Contenido Repaso de los conceptos de proceso y threads Concurrencia Mecanismos de comunicación Mecanismos de sincronización Llamadas al sistema de POSIX para comunicación y sincronización de procesos Paso de mensajes 2

Bibliografía Bibliografía básica: Sistemas Operativos: una visión aplicada. Por Jesús Carretero, Félix García, Pedro de Miguel y Fernando Pérez Mc. Graw-Hill Prácticas de Sistemas Operativos: de la base al diseño Por Jesús Carretero, Félix García, Pedro de Miguel y Fernando Pérez Mc. Graw-Hill 3

Sistema Distribuido Sistema compuesto por recursos de computación (hardware y software) físicamente distribuidos e interconectados a través de una red, que son capaces de colaborar con el fin de realizar una determinada tarea La espina dorsal de Red los sistemas distribuidos son los mecanismos de comunicación entre procesos (IPC) 4

Conceptos previos Un programa es un conjunto de instrucciones Un proceso es un programa en ejecución Una red de computadores es un conjunto de computadores conectados por una red de interconexión Un sistema distribuido es un conjunto de computadores (sin memoria ni reloj común) conectados por una red Aplicaciones distribuidas: conjunto de procesos que ejecutan en uno o más computadores que colaboran y comunican intercambiando mensajes Un protocolo es un conjunto de reglas e instrucciones que gobiernan la comunicación en un sistema distribuido, es decir, el intercambio y formato de los mensajes 5

Sistema Operativo Gestión de los recursos del computador Ejecución de servicios para los programas en ejecución Ejecución de los mandatos de los usuarios Usuarios Procesos de usuario Shell Servicios Núcleo Hardware API Sistema operativo 6

Componentes del Sistemas Operativo Objetivo Tema 2 Objetivo Tema 2 Usuarios Programas de usuario Shell 1 Shell 2 Gestión de procesos Interfaz de llamadas al SO Gestión de memoria Gestión de la E/S Núcleo Hardware Gestión de archivos y directorios Seguridad y protección Comunicac. y sincroniz. Sistema operativo 7

Proceso Definición Programa en ejecución Unidad de procesamiento gestionada por el SO Para que un programa pueda ser ejecutado ha de residir en memoria principal Árbol de procesos Proc. Inic. Relación de jerarquía Inicio Inicio Inicio Inicio Dem. Impr. Dem. Com.. Shell Shell Editor Proceso A Proceso B Proceso D Proceso C Proceso E Proceso F 8

Información de los procesos El sistema operativo mantiene un conjunto de estructuras de información que permiten identificar y gestionar los procesos Registros especiales Mapa de memoria del Proceso A Registros generales PC SP Estado Mapa de memoria del Proceso B Mapa de memoria del Proceso C Tablas SO Mapa de Memoria Tablas del sistema operativo Tabla de procesos BCP Proceso A BCP Proceso B BCP Proceso C - Estado (registros) - Estado (registros) - Estado (registros) - Identificación - Control - Identificación - Control - Identificación - Control - Tabla de memoria - Tabla de E/S - Tabla de ficheros 9

Proceso monothread o multithread Un proceso ligero, hilo o thread es un programa en ejecución (flujo de ejecución) que comparte la imagen de memoria (y otras informaciones) con otros procesos ligeros Dependiendo del número de procesos que puedan ejecutar simultáneamente, un SO es monotarea o multitarea Un proceso ligero puede contener un solo flujo de ejecución (monothread) o más (multithread) Por ejemplo, en el lenguaje C el hilo de ejecución primario se corresponde con la función principal main Proceso 10 Procesos ligeros

Información propia/compartida Por thread (información propia) Contador de programa, Registros Pila Estado (ejecutando, listo o bloqueado) Por proceso (información compartida) Espacio de memoria Variables globales Ficheros abiertos Procesos hijos Temporizadores Señales y semáforos Contabilidad 11

Estructura de un proceso con threads Proceso Código Datos Recursos (ficheros,...) Entorno del proceso Hilo 1 Registros Pila Hilo n Registros Pila 12

Mapa de memoria de un proceso con threads Mapa de memoria Código Datos con valor inicial Fichero ejecutable Datos sin valor inicial Heap Fichero Fichero proyectado F Zona de memoria compartida Código biblioteca dinámica B Bibliotecas Pila de thread 1 Swap Pila del thread n 13

Estados del proceso ligero Como los procesos convencionales, un proceso ligero puede estar en varias situaciones o estados: ejecutando, listo o bloqueado El estado del proceso será la combinación de los estados de sus procesos ligeros. Proceso Bloqueado por comunicación Bloqueado por acceso a disco Activo Procesos ligeros 14

Threads y paralelismo Los procesos ligeros permiten paralelizar una aplicación Un programa puede dividirse en procedimientos que pueden ejecutar de manera independiente mediante procesos ligeros Los procesos ligeros pueden lanzar su ejecución de manera simultánea Diseño modular de la aplicación La base del paralelismo: Mantener algún proceso ligero siempre en estado de ejecución: mientras que un proceso está bloqueado otro podría estar ejecutando main(){ main(){ function1(args); function2(args); } Diseño secuencial lanzar_thread( function1(args)); lanzar_thread( } function2(args)); Diseño paralelo 15

Ejemplo: ejecución serie vs. paralela Procedimiento 1 P Espera en E/S F Procedimiento 2 P Espera en E/S F Ejecución serie Procedimiento 1 P Procedimiento 2 Espera en E/S F Ejecución paralela P Espera en E/S F Procesamiento 16

Programación concurrente En SSOO multitarea pueden coexisitir varios procesos activos a la vez Multiprogramación con un único procesador Multiprocesador Multicomputadora En general, para p procesadores y n procesos, la concurrencia es: Aparente si n>p real si n<=p 17

Comunicación entre procesos Proceso de Usuario Proceso de Usuario Proceso de Usuario Proceso de Usuario SO SO SO Un computador Dos computadores 18

Ejemplo: Servidores concurrentes con threads Los procesos concurrentes deben comunicar y sincronizarse Cliente petición servidor Cliente Petición/respuesta Crea thread de servicio Cliente servidor respuesta Thread de servicio Cliente Recurso Diseño concurrente Diseño secuencial 19

Diseño de servidores mediante threads Distintas arquitecturas de SW para construir servidores paralelos: Un proceso distribuidor que acepta peticiones y las distribuye entre un pool de procesos ligeros Cada proceso ligero realiza las mismas tareas: aceptar peticiones, procesarlas y devolver su resultado Segmentación: cada trabajo se divide en una serie de fases, cada una de ellas se procesa por un proceso ligero especializado Distribuidor Trabajador Núcleo E/S Solicitudes Núcleo E/S Solicitudes Núcleo E/S Solicitudes 20

Programación con procesos ligeros Servicios UNIX incluyen: Operaciones de gestión Creación e identificación de procesos ligeros Atributos de un proceso ligero Planificación de procesos ligeros Prioridades, políticas de planificación Terminación de procesos ligeros 21

Creación e identificación de threads Crear un thread: int pthread_create(pthread_t* thread, const pthread_attr_t* attr, void * (*funcion)(void *), void * arg); donde: thread se crea) attr funcion arg devuelve: int Identificador del nuevo thread (se captura cuando Atributos a aplicar al nuevo thread o NULL Función a ejecutar por el thread que es creado Puntero a el/los argumentos del thread Devuelve 0 si éxito o -1 si error Obtener el identificador de un thread: pthread_t pthread_self(void) 22

Atributos de un proceso ligero Un hilo se crea con una serie de atributos por defecto Ejemplo: Por defecto, un hilo es joinable o No Independiente Es posible modificar los atributos por defecto del hilo: 23 Inicia un objeto atributo que se puede utilizar para crear nuevos procesos ligeros int pthread_attr_init(pthread_attr_t *attr); Destruye un objeto de tipo atributo int pthread_attr_destroy(pthread_attr_t *attr); Cambiar el estado de terminación (Joinable / Detached) int pthread_attr_setdetachstate( pthread_attr_t *a, int detachstate); Si detachstate es PTHREAD_CREATE_DETACHED el proceso se crea independiente PTHREAD_CREATE_JOINABLE el proceso se crea no independiente Otras atributos: tamaño de pila, planificación, prioridad, etc.

Terminación de procesos ligeros Finaliza la ejecución del proceso ligero: int pthread_exit(void *value); Para procesos creados como NO independientes es además necesario: int pthread_join(pthread_t thid, void **value); Espera la terminación del proceso con identificador thid Devuelve en el segundo argumento el valor pasado en pthread_exit. Sólo se puede esperar la terminación de procesos ligeros no independientes (PTHREAD_CREATE_JOINABLE ) 24

Ejemplo: Jerarquía de threads Thread A p_create No independiente p_create Thread D p_create Thread C Thread B p_exit p_join p_exit 25

Ejemplo I: creación y terminación #include <stdio.h> /* printf */ #include <pthread.h> /* Para threads */ #define NUM_THREADS 10 int funcion(int *idthread){ printf( Thread id = %d\ti=%d:, pthread_self(),*idthread); pthread_exit(null); } int main () { pthread_t arraythread[num_threads]; /* Array de threads */ int i; /* CREAR THREADS */ for(i=0;i<num_threads;i++){ if (pthread_create(&arraythread[i],null,(void *)funcion, &i)==-1) printf( Error al crear proceso ligero\n ); } /* ESPERAR TERMINACIÓN DE THREADS */ for(i=0;i<num_threads;i++) pthread_join (arraythread[i], NULL); exit(0); 26

Ejemplo II: Modificar atributos #include <stdio.h> /* printf */ #include <pthread.h> /* Para threads */ #define MAX_THREADS 10 void func(void) { } printf("thread %d \n", pthread_self()); pthread_exit(0); main() { int j; pthread_attr_t attr; pthread_t thid[max_threads]; } 27 pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr,pthread_create_detached); for(j = 0; j < MAX_THREADS; j ++) pthread_create(&thid[j], &attr, func, NULL); sleep(5); pthread_attr_destroy(&attr);

Concurrencia Modelos: Multiprogramación en un único procesador Multiprocesador Multicomputador (proceso distribuido) Ventajas: Facilita la programación Acelera los cálculos Posibilita el uso interactivo a múltiples usuarios Mejor aprovechamiento de los recursos 28

Monoprocesador vs. Multiprocesador Proceso A Proceso B Proceso C Tiempo Proceso A Proceso B Proceso C CPU 1 CPU 2 Proceso D Tiempo 29

Tipos de procesos concurrentes Tipos de procesos: Independientes: su ejecución no requiere la ayuda o cooperación con otros procesos Cooperantes: su ejecución requiere trabajar conjuntamente con otros procesos para realizar una actividad En ambos casos se produce una interacción entre procesos Compiten por recursos Comparten recursos 30

Conceptos previos Una condición de carrera es el acceso concurrente a los recursos compartidos sin coordinación Puede producir resultados diferentes a los esperados Una sección crítica (SC) es un fragmento de código en el que los distintos procesos pueden acceder y modificar recursos compartidos Una sección es atómica si se ejecuta por un thread completamente de manera indivisible, de principio a fin, sin que su ejecución se pueda interrumpir por ningún otro thread Tienen una semántica de éxito-o-fallo 31

Ejemplo I: Servidor concurrente Distribuidor Cache Núcleo E/S Solicitudes 32

Ejemplo II: Acceso a una caché compartida thread principal Petición 1 Petición 2 Update_block() Update_block() Condición de carrera en la sentencia: Update_block Update_block(bloque) { } b = Get_block(); copy(b, bloque); Cache copy(b1, b2){ for (i=0; i<length;i++) *b1++ = *b2++; 33

Acceso a una caché compartida thread principal Petición 1 Petición 2 Update_block() Update_block() Condición de carrera en la sentencia: Update_block Update_block(bloque) { } b = Get_block(); copy(b, bloque); Cache copy(b1, b2){ for (i=0; i<length;i++) *b1++ = *b2++; Operación no atómica 34

El problema de la sección crítica Sistema compuesto por n procesos Cada uno tiene un fragmento de código: sección crítica Los procesos deben acceder a la SC con exclusividad Estructura general de cualquier mecanismo utilizado para resolver el problema de la sección crítica: Entrada en la sección crítica Código de la sección crítica Salida de la sección crítica Requisitos que debe ofrecer cualquier solución para resolver el problema de la sección crítica: Exclusión mutua Progreso Espera limitada 35

Modelos de comunicación y sincronización Modelo productor-consumidor Modelo de lectores-escritores Modelo de acceso a recursos limitados Modelo cliente-servidor 36

Modelo productor-consumidor Proceso Productor Proceso Consumidor Flujo de datos Mecanismo de comunicación 37

Modelo de lectores-escritores Lector Lector Escritor Lector Escritor Recurso 38

Modelo de acceso a recursos limitados Ejemplo: problema de los filósofos comensales 39

Modelo cliente-servidor Petición S.O. Proceso cliente Respuesta Proceso servidor 40

Comunicación cliente-servidor Muy utilizada en entornos distribuidos (más del 90% de los sistemas distribuidos utilizan la arquitectura clienteservidor) Máquina A petcición Máquina B cliente NÚCLEO respuesta servidor NÚCLEO RED Protocolo típico: petición-respuesta 41

Mecanismos de comunicación Ficheros Tuberías (pipes, FIFOS) Variables en memoria compartida Paso de mensajes 42

Comunicación mediante archivos Un archivo es un mecanismo que puede emplearse para comunicar procesos Un proceso puede escribir datos y otro puede leerlos Proces o escritor Dato1 Dato2 Dato3 Dato n Proces o lector Fichero compartido 43

Comunicación mediante tuberías Una tubería (pipe) es un mecanismo de comunicación y sincronización Comunicación: archivo compartido Sincronización: semántica bloqueante Puede verse como un pseudoarchivo identificado por dos descriptores, uno se usa para leer y el otro para escribir Los servicios utilizados para lectura y escritura de pipes son los mismos que los usados sobre ficheros write Proces o usuario Tubería SO Proces o usuario read 44 Flujo de datos

Ejemplo III: Productor-consumidor con tuberías #include <stdio.h> /* printf */ #include <unistd.h> struct elemento dato; /* dato a producir */ int fildes[2]; int main () { if (pipe(fildes)<0){ } printf( Error al crear la tubería); exit(1); if (fork() == 0){ }else{ for (;;){ } for (;;){ } <Producir dato> write (fildes[1], (char*)&dato, sizeof (struct elemento)); read (fildes[0], (char*)&dato, sizeof (struct elemento)); <Consumir dato> } 45

Mecanismos de sincronización Señales (asincronismo) Tuberías (pipes, FIFOS) Semáforos Mutex y variables condicionales Paso de mensajes 46

Semáforos Un semáforo [Dijkstra, 1965] es un mecanismo de sincronización de procesos que ejecutan en la misma máquina Idea muy simple: Un semáforo es un objeto con un valor entero inicialmente no negativo Dos operaciones atómicas wait signal 47

Operaciones sobre semáforos Operación wait wait(s) { s = s - 1; if (s < 0) { <bloquear al proceso> } } s: valor entero asociado al semáforo Estructura para projeger la SC: Operación signal signal(s) { s = s + 1; if (s <= 0) <Desbloquear a un proceso bloqueado por la operacion wait> } } wait(s) Código de la sección crítica signal(s) 48

Secciones críticas con semáforos wait(s); /* entrada en la seccion critica */ < seccion critica > signal(s); /* salida de la seccion critica */ El semáforo debe tener valor inicial 1 Valor del semáforo (s) P 0 1 0-1 -2 wait(s) wait(s) wait(s) P 1 P 2 Ejecutando código de la sección crítica Proceso bloqueado en el semáforo desbloquea -1 signal(s) 0 signal(s) desbloquea 1 signal(s) 49

Productor-consumidor con semáforos Productor Consumidor 50

Ejemplo IV: Productor-consumidor con semáforos #define TAMAÑO_DEL_BUFFER 1024 Productor() { int posicion = 0; for(;;) { Producir un dato; wait(huecos); Consumidor() { int posición = 0; for(;;) { wait(elementos); dato = buffer[posicion]; posicion = (posicion + 1) % TAMAÑO_DEL_BUFFER; } } buffer[posicion] = dato; posicion = (posicion + 1) % TAMAÑO_DEL_BUFFER; signal(elementos); } } signal(huecos); Consumir el dato extraído; 51

Ejemplo V: Lectores-escritores con semáforos Lector() { Escritor(){ wait(sem_lectores); n_lectores = n_lectores + 1; if (n_lectores == 1) wait(sem_recurso); signal(sem_lectores); Consultar el recurso compartido } wait(sem_recurso); /*se puede modificar el recurso*/ signal(sem_recurso); } wait(sem_lectores); n_lectores = n_lectores - 1; if (n_lectores == 0) signal(sem_recurso); signal(sem_lectores); 52

Mutex Un mutex es un mecanismo de sincronización especialmente indicado para procesos ligeros Se emplean para tener exclusión mutua sobre SC y tener acceso exclusivo a los recursos compartidos Es un semáforo binario (valor inicial 1) con dos operaciones atómicas: lock(m) Intenta bloquear el mutex. Si el mutex ya está bloqueado el proceso se suspende unlock(m) Desbloquear el mutex.si existen procesos bloqueados en el mutex se desbloquea a uno 53

Secciones críticas con mutex lock(m); /* entrada en la seccion critica */ < seccion critica > unlock(m); /* salida de la seccion critica */ La operación unlock debe realizarla el proceso ligero que ejecutó lock Thread A Thread B thread ejecutando lock mutex lock mutex thread bloqueado Sección crítica unlock mutex obtiene mutex Punto de sincronización 54

Variables condicionales Una variable condicional es una variable de sincronización asociada a un mutex Bloquea o desbloquea el proceso hasta que ocurra algún suceso Conveniente ejecutarlas entre las llamadas lock y unlock Dos operaciones atómicas: c_wait Bloquea al proceso ligero que la ejecuta y libera el mutex c_signal Desbloquea a uno o varios procesos suspendidos en la variable condicional El proceso que se despierta compite de nuevo por el mutex 55

Uso de mutex y variables condicionales Thread A lock(m); /* Código de la sección crítica */ while (condición == FALSE) c_wait(c,m); /* Resto la sección crítica */ unlock(m); /* Salida de la SC */ Thread B lock(m); /* Código de la sección crítica */ /* Se modifica la condición */ condición = TRUE; c_signal(c); /* Resto la sección crítica */ unlock(m); /* Salida de la SC */ Thread A Thread B Thread bloqueado esperando unlock lock c_wait unlock mutex lock Adquiere el mutex Thread bloqueado esperando c_signal Se compite por el mutex Adquiere el mutex c_signal unlock 56

Uso de mutex y variables condicionales Thread A lock(mutex); /* acceso al recurso */ comprobar las estructuras de datos; while (recurso ocupado) wait(condition, mutex); marcar el recurso como ocupado; unlock(mutex); Thread B lock(mutex); /* acceso al recurso */ marcar el recurso como libre; signal(condition); unlock(mutex); Importante utilizar while 57

Ejemplo VI: Productor-consumidor con mutex y variables condicionales Productor() { int pos = 0; for(;;) { < Producir un dato > lock(mutex); /* acceder al buffer */ while (n_elementos == TAMAÑO_DEL_BUFFER) c_wait(lleno, mutex); buffer[pos] = dato; pos = (pos + 1) % TAMAÑO_DEL_BUFFER; n_elementos ++; if (n_elementos == 1) c_signal(vacio); unlock(mutex); } } Consumidor() { int = 0; for(;;) { lock(mutex); } } while (n_elementos == 0) c_wait(vacío, mutex); dato = buffer[pos]; pos = (pos + 1) % TAMAÑO_DEL_BUFFER; n_elementos --; if (n_elementos == (TAMAÑO_DEL_BUFFER - 1)); c_signal(lleno); unlock(mutex); < Consumir el dato > 58

Servicios UNIX para mutex Inicializa un mutex int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t * attr); Destruye un mutex int pthread_mutex_destroy(pthread_mutex_t *mutex) ; Intenta obtener el mutex. Bloquea al proceso ligero si el mutex se encuentra adquirido por otro proceso ligero int pthread_mutex_lock(pthread_mutex_t *mutex); Desbloquea el mutex 59 int pthread_mutex_unlock(pthread_mutex_t *mutex);

Servicios UNIX para variables condicionales (I) Inicializa una variable condicional int pthread_cond_init(pthread_cond_t*cond, pthread_condattr_t* attr); Destruye una variable condicional int pthread_cond_destroy(pthread_cond_t *cond); Bloquea al proceso ligero y libera el mutex: Suspende al proceso ligero hasta que otro proceso señaliza la variable condicional cond. Automáticamente se libera el mutex. Cuando se despierta el proceso ligero vuelve a competir por el mutex. int pthread_cond_wait(pthread_cond_t*cond, pthread_mutex_t*mutex); 60

Servicios UNIX para variables condicionales (II) Desbloquea el/los proceso(s) ligero(s) y libera el mutex int pthread_cond_signal(pthread_cond_t *cond); Se reactivan uno o más de los procesos ligeros que están suspendidos en la variable condicional cond No tiene efecto si no hay ningún proceso ligero esperando (diferente a los semáforos) int pthread_cond_broadcast(pthread_cond_t *cond); Todos los threads suspendidos en la variable condicional cond se reactivan No tiene efecto si no hay ningún proceso ligero esperando 61

Ejemplo VII: Productor-consumidor con mutex (I) #define MAX_BUFFER 1024 /* tamanio del buffer */ #define DATOS_A_PRODUCIR 100000 /* datos a producir */ pthread_mutex_t mutex; /* mutex para controlar el acceso al buffer compartido */ pthread_cond_t no_lleno; /* controla el llenado del buffer */ pthread_cond_t no_vacio; /* controla el vaciado del buffer */ int n_elementos; /* numero de elementos en el buffer */ int buffer[max_buffer]; /* buffer comun */ int main(int argc, char *argv[]){ pthread_t th1, th2; pthread_mutex_init(&mutex, NULL); pthread_cond_init(&no_lleno, NULL); pthread_cond_init(&no_vacio, NULL); 62

Ejemplo VII: Productor-consumidor con mutex (II) pthread_create(&th1, NULL, Productor, NULL); pthread_create(&th2, NULL, Consumidor, NULL); pthread_join(th1, NULL); pthread_join(th2, NULL); pthread_mutex_destroy(&mutex); pthread_cond_destroy(&no_lleno); pthread_cond_destroy(&no_vacio); } return 0; 63

Ejemplo VII: Productor-consumidor con mutex (III) void Productor(void) { int dato, i,pos = 0; for(i=0; i<datos_a_producir; i++ ) { dato = i; /* producir dato */ pthread_mutex_lock(&mutex); /* acceder al buffer */ while (n_elementos == MAX_BUFFER)/* si buffer lleno */ pthread_cond_wait(&lleno, &mutex); /* se bloquea*/ buffer[pos] = i; pos = (pos + 1) % MAX_BUFFER; n_elementos = n_elementos + 1; if (n_elementos == 1) pthread_cond_signal(&vacio); /* buffer no vacío*/ } pthread_mutex_unlock(&mutex); } pthread_exit(0); 64

Ejemplo VII: Productor-consumidor con mutex (IV) void Consumidor(void) { int dato, i,pos = 0; for(i=0; i<datos_a_producir; i++ ) { pthread_mutex_lock(&mutex); /* acceder al buffer */ while (n_elementos == 0) /* si buffer vacío */ pthread_cond_wait(&vacio, &mutex); /* se bloquea */ dato = buffer[pos]; pos = (pos + 1) % MAX_BUFFER; n_elementos = n_elementos - 1 ; if (n_elementos == MAX_BUFFER - 1); pthread_cond_signal(&lleno);/* buffer no lleno */ pthread_mutex_unlock(&mutex); } printf( Consume %d \n, dato); /* consume dato */ } pthread_exit(0); 65

Paso de mensajes: conceptos básicos Mecanismo de comunicación y sincronización de procesos que ejecutan en distintas máquinas En este tipo de comunicación, los procesos intercambian mensajes Entre los procesos que comunican debe existir un enlace de comunicación Dos primitivas básicas: send(destino, mensaje) receive(origen, mensaje) 66

Modelo de comunicación Proceso emisor mensaj e Proceso receptor Emisor: send(destino, mensaje) Receptor: receive(origen, mensaje) 67

Paso de mensajes: conceptos básicos Computador A Proceso de Usuario Computador B Proceso de Usuario mensaje1 dato mensaje2 SO SO 68

Proceso de comunicación Computador A Proceso de Usuario Computador B Proceso de Usuario mensaje1 dato mensaje2 (mensaje1) SO SO 69

Proceso de comunicación Computador A Proceso de Usuario Computador B Proceso de Usuario mensaje1 dato mensaje2 (mensaje1) SO SO dato 70

Proceso de comunicación Computador A Proceso de Usuario Computador B Proceso de Usuario mensaje1 dato mensaje2 (mensaje1) SO SO dato dato 71

Proceso de comunicación Computador A Proceso de Usuario Computador B Proceso de Usuario mensaje1 dato mensaje2 (mensaje1) SO SO dato dato dato 72

Proceso de comunicación Computador A Proceso de Usuario Computador B Proceso de Usuario mensaje1 dato mensaje2 (mensaje1) (mensaje2) SO SO dato dato dato 73

Proceso de comunicación Computador A Proceso de Usuario Computador B Proceso de Usuario mensaje1 dato dato mensaje2 (mensaje1) (mensaje2) SO SO dato dato dato 74

Paso de mensajes: cuestiones de diseño Tamaño del mensaje Longitud fija o variable Flujo de datos Bidireccional, unidireccional Nombrado Comunicación directa send(p, m): envía un mensaje m al proceso P receive(q, m): recibe un mensaje del proceso Q receive (ANY, m): recibe un mensaje de cualquiera Comunicación indirecta Colas de mensajes o puertos Tipos de comunicación (sincronización) Almacenamiento (buffering) Capacidad o no de almacenamiento del enlace de comunicaciones Fiabilidad Representación de datos, aplanamiento 75

Paso de mensajes: cuestiones de diseño Nombrado Comunicación indirecta: los datos se envían a estructuras intermedias Puertos: se asocian a un proceso (un único receptor) Ejemplo: sockets Colas de mensajes: múltiples emisores y receptores Ejemplo: Colas de mensajes POSIX Proceso cliente send Proceso cliente receive Proceso cliente send Proceso cliente Puerto mensaje mensaje Cola de mensajes Comunicación con colas de mensajes Comunicación con puertos 76

Paso de mensajes: cuestiones de diseño Tipos de comunicación (sincronización) Síncrona, asíncrona (bloqueante, no bloqueante) Proceso A Comunicación síncrona Proceso B Avanza la ejecución enviar Espera Proceso B recibir Proceso A enviar recibir Espera El proceso A espera al B El proceso B espera al A 77

Estructura de un servidor secuencial y concurrente Proceso cliente petición Proceso cliente Proceso cliente petición Proceso cliente respuesta Proceso servidor petición respuesta respuesta Proceso hijo Creación del proceso hijo Proceso servidor Creación del proceso hijo petición respuesta Proceso hijo Servidor secuencial Servidor concurrente 78

Colas de mensajes UNIX Mecanismo de comunicación y sincronización Nombrado indirecto Asignan a las colas nombres de ficheros Sólo pueden utilizar colas de mensajes procesos que comparten un mismo sistema de ficheros Tamaño del mensaje variable Flujo de datos bidireccional Sincronización: Envío asíncrono Recepción síncrona o asíncrona Los mensajes se pueden etiquetar con prioridades 79

Servicios UNIX para la gestión de colas de mensajes (I) Crear una cola de mensajes con nombre y atributos mqd_t mq_open(char *name, int flag, mode_t mode, struct mq_attr *attr) Los atributos se especifican en la estructura attr: mq_maxmsg mq_msgsize Número máximo de mensajes Tamaño del mensaje El segundo argumento es el modo de creación de la cola: O_NONBLOCK Envío y recepción no bloqueante Cerrar una cola de mensajes int mq_close(mqd_t mqdes) Borrar una cola de mensajes int mq_unlink(char *name) 80

Servicios UNIX para la gestión de colas de mensajes (II) Enviar un mensaje a una cola int mq_send(mqd_t mqdes, char *msg, size_t len, int prio) El mensaje msg de longitud len se envía a la cola de mensajes mqdes con prioridad prio Si la cola está llena el envío puede ser bloqueante o no (depende de O_NONBLOCK) Recibir un mensaje desde una cola int mq_receive(mqd_t mqdes, char *msg, size_t len, int prio) Recibe un mensaje msg de longitud len de la cola de mensajes mqdes con prioridad prio Recepción bloqueante o no (depende de O_NONBLOCK) 81

Productor-consumidor con paso de mensajes Productor () { } for(;;) { <Producir dato> send(consumidor, dato); } /* end for */ Consumidor () { } for(;;) { receive(productor, dato); <Consumir dato> } /* end for */ 82

Ejemplo VIII: Productor-consumidor con colas de mensajes #include <mqueue.h> #include <stdio.h> #define MAX_BUFFER 1024 /* tamaño del buffer */ #define DATOS_A_PRODUCIR 100000 /* datos a producir */ mqd_t almacen; void main(void){ } 83 /* cola de mensajes donde dejar los datos producidos y extraer los datos a consumir */ struct mq_attr attr; attr.mq_maxmsg = MAX_BUFFER; attr.mq_msgsize = sizeof (int); almacen = mq_open( ALMACEN, O_CREAT O_WRONLY, 0700, &attr); if (almacen == -1){ } Productor(); perror ( mq_open ); exit(-1); mq_close(almacen); exit(0);

Ejemplo VIII: Productor-consumidor con colas de mensajes Productor(void){ int dato; int i; for(i=0;i<datos_a_producir;i++){ /* producir dato */ dato = i; if (mq_send(almacen, &dato, siezof(int), 0)== -1){ perror( mq_send ); mq_close(almacen); exit(1); } } /* end for */ return; } /* end productor */ 84

Ejemplo VIII: Productor-consumidor con colas de mensajes #include <mqueue.h> #include <stdio.h> #define MAX_BUFFER 1024 /* tamaño del buffer */ #define DATOS_A_PRODUCIR 100000 /* datos a producir */ mqd_t almacen; void main(void){ /* cola de mensajes donde dejar los datos producidos y extraer los datos a consumir */ struct mq_attr attr; almacen = mq_open( ALMACEN, O_RDONLY); if (almacen == -1){ } Consumidor(); perror ( mq_open ); exit(-1); mq_close(almacen); } exit(0); 85

Ejemplo VIII: Productor-consumidor con colas de mensajes Consumidor(void){ int dato; int i; for(i=0;i<datos_a_producir;i++){ /* recibir dato */ dato = i; if (mq_receive(almacen, &dato, siezof(int), 0)== -1){ perror( mq_send ); mq_close(almacen); exit(1); } /* Consumir el dato */ printf( El dato consumido es: %d\n, dato); } /* end for */ return; } /* end consumidor */ 86

Comunicación de grupos Utiliza mensajes multicast Útil para: Ofrecer tolerancia a fallos basado en servicios replicados Localizar objetos en sistemas distribuidos Mejor rendimiento mediante datos replicados Actualizaciones múltiples Operaciones colectivas en cálculo paralelo emisor receptor IPC uno-a-uno IPC grupo o multidifusión 87

Tema 2 Comunicación y sincronización entre procesos Grupo ARCOS Grado en Ingeniería Informática Universidad Carlos III de Madrid