Sistemas operativos: una visión aplicada. Capítulo 5 Comunicación y sincronización de 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

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

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

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

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

Tema 2 Comunicación y sincronización entre procesos

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

Comunicación y sicronización de procesos

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

Sincronización de Threads

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

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

Sincronización de procesos

SISTEMAS OPERATIVOS:

Sincronización de Hilos POSIX

Tema 4 El paradigma cliente-servidor

Acceso coordinado a recursos compartidos

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

Redirecciones y Tuberías

Biblioteca de sistema

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

Fundamentos de los Sistemas Operativos

Sistemas Operativos sesión 12: tuberías

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

Taller de Programación Paralela

SISTEMAS OPERATIVOS:

Informática Electrónica Concurrencia

Formatos para prácticas de laboratorio

Taller de Programación Paralela

ISO Tema 8,

SISTEMAS OPERATIVOS Manejo de procesos

Práctica 1: Intérprete de mandatos. Sistemas Operativos Área de Arquitectura y Tecnología de Computadores

ASIGNATURA: SISTEMAS INFORMÁTICOS INDUSTRIALES. CURSO 4º GRUPO Diciembre 2013

SISTEMAS OPERATIVOS AVANZADOS

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

Concurrencia Monitores. Guillermo Román Díez

Programación Concurrente

Sincronizacion de procesos

Bloque I: Principios de sistemas operativos

Estados de un proceso

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

MC Hilda Castillo Zacatelco PROCESOS

PROGRAMACIÓN MULTITHREADING

Tema 3. Concurrencia entre procesos

Prácticas de Sistemas operativos

Comunicación entre Procesos

Unidad 1: Gestión de Procesos

Informática I Threads

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

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:

ASIGNATURA: SISTEMAS INFORMÁTICOS INDUSTRIALES. CURSO 4º GRUPO Enero 2016

Ejercicios sobre tuberías

Plataformas de Tiempo Real

Procesos e hilos: cálculo de

Interbloqueo. Concurrencia: Interbloqueo e Inanición

Comunicación y sincronización

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

Plataformas de Tiempo Real

Sistemas Operativos 1

Examen Final de SO Grau

Entrada y Salida de Archivos

A2. Diseñar una solución basada en varios procesos pesados emparentados, cada uno de los cuáles procesará una parte de los votos.

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

Funciones POSIX (I): Introducción

Hilos de ejecución POSIX

Concurrencia de Procesos

Sistemas Operativos. Procesos

UNIVERSIDAD CARLOS III DE MADRID AREA DE ARQUITECTURA Y TECNOLOGÍA DE COMPUTADORES GRADO EN INGENIERÍA INFORMÁTICA. SISTEMAS DISTRIBUIDOS

Segundo control de teoría Q1

Segundo control de teoría

dit Programación concurrente Sincronización condicional UPM

Capítulo 2 Introducción a los sistemas operativos

Lecturas: Ben-Ari, secciones 4.1, 4.2, 4.3, 4.6 Andrews, intro. cap. 4 y sección 4.1

1. Interfaz de llamadas a la librería de fluxes

Sincronización de Procesos

Introducción a Sistemas Operativos: Concurrencia

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

Llamadas a Sistema para procesos

Lecturas: Ben-Ari, secciones 4.1, 4.2, 4.3, 4.6 Andrews, intro. cap. 4 y sección 4.1. Exclusión mutua con semáforos

Examen Final de Teoría. Grupo de teoría:

Taller de pthreads. Sistemas Operativos. Verano de 2009

Mensajes. Interbloqueo

Tema 4: Gestión de Procesos

Unidad 2: Gestión de Procesos

Concurrencia. Primitivas IPC con bloqueo

Sistemas Operativos II Junio 2006 Nombre:

Segundo control de teoría

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

Semáforos. Lecturas: Ben-Ari, secciones 4.1, 4.2, 4.3, 4.6 Andrews, intro. cap. 4 y sección 4.1. Exclusión mutua con semáforos

T5-multithreading. Indice

Arquitectura de Computadores. Práctica 3: Mecanismos de comunicación entre procesos

Concurrencia: deberes. Concurrencia: Exclusión Mutua y Sincronización. Concurrencia. Dificultades con la Concurrencia

Programación Concurrente

Nombre Apellidos. DNI Titulación Grupo.

Tema 3. Concurrencia entre procesos

Examen de Programación Concurrente - Clave: a Junio 2008 Departamento de Lenguajes, Sistemas Informáticos e Ingeniería del Software.

Transcripción:

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

Contenido Procesos concurrentes. Problemas clásicos de comunicación y sincronización. Mecanismos de comunicación y sincronización. Paso de mensajes. Aspectos de implementación Interbloqueos. Servicios POSIX Sistemas operativos: una visión aplicada 2 J. Carretero, F. García, P. de Miguel, F. Pérez

Procesos concurrentes Modelos Multiprogramación en un único procesador Multiprocesador Multicomputador (proceso distribuido) Razones Compartir recursos físicos Compartir recursos lógicos Acelerar los cálculos Modularidad Comodidad Sistemas operativos: una visión aplicada 3 J. Carretero, F. García, P. de Miguel, F. Pérez

Sistema multiprogramado con un una CPU P r o c e s o A P r o c e s o B P r o c e s o C T i e m p o Sistemas operativos: una visión aplicada 4 J. Carretero, F. García, P. de Miguel, F. Pérez

Ejecución en un sistema multiprocesador P P P r o c e s o A r o c e s o B r o c e s o C C P U 1 C P U 2 P r o c e s o D T i e m p o Sistemas operativos: una visión aplicada 5 J. Carretero, F. García, P. de Miguel, F. Pérez

Tipos de procesos concurrentes Tipos de procesos Independientes Cooperantes Interacción entre procesos Compiten por recursos Comparten recursos Sistemas operativos: una visión aplicada 6 J. Carretero, F. García, P. de Miguel, F. Pérez

Contenido Procesos concurrentes. Problemas clásicos de comunicación y sincronización. Mecanismos de comunicación y sincronización. Paso de mensajes. Aspectos de implementación Interbloqueos. Servicios POSIX Sistemas operativos: una visión aplicada 7 J. Carretero, F. García, P. de Miguel, F. Pérez

Problemas clásicos de comunicación y sincronización El problema de la sección crítica El problema del productor-consumidor El problema de los lectores-escritores Comunicación cliente-servidor Sistemas operativos: una visión aplicada 8 J. Carretero, F. García, P. de Miguel, F. Pérez

Problema de la sección crítica Sistema compuesto por n procesos Cada uno tiene un fragmento de código: sección crítica Sólo uno de los procesos en cada instante puede ejecutar en la sección crítica Cuando un proceso está ejecutando en la sección crítica, ningún otro puede hacerlo Sistemas operativos: una visión aplicada 9 J. Carretero, F. García, P. de Miguel, F. Pérez

Ejemplo 1 P r o c e s o l i g e r o p r i n c i p a l n i = 1 n f = 5 0 S 1 = 1 +... + 5 0 S 2 = 5 1 +.... + 1 0 0 n i = 5 1 n f = 1 0 0 s u m a _ t o t a l = S 1 + S 2 Sistemas operativos: una visión aplicada 10 J. Carretero, F. García, P. de Miguel, F. Pérez

Ejemplo 1 Calcula la suma de los N primeros números utilizando procesos ligeros. int suma_total = 0; void suma_parcial(int ni, int nf) { int j = 0; int suma_parcial = 0; for (j = ni; j <= nf; j++) suma_parcial = suma_parcial + j; suma_total = suma_total + suma_parcial; pthread_exit(0); Si varios procesos ejecutan concurrentemente este código se puede obtener un resultado incorrecto. Solución: secciones críticas Sistemas operativos: una visión aplicada 11 J. Carretero, F. García, P. de Miguel, F. Pérez

Ejemplo con sección crítica void suma_parcial(int ni, int nf) { int j = 0; int suma_parcial = 0; for (j = ni; j <= nf; j++) suma_parcial = suma_parcial + j; <Entrada en la sección crítica> suma_total = suma_total + suma_parcial; <Salida de la sección crítica> pthread_exit(0); Sistemas operativos: una visión aplicada 12 J. Carretero, F. García, P. de Miguel, F. Pérez

Ejemplo 2 void ingresar(char *cuenta, int cantidad) { int saldo, fd; fd = open(cuenta, O_RDWR); read(fd, &saldo, sizeof(int)); saldo = saldo + cantidad; lseek(fd, 0, SEEK_SET); write(fd, &saldo, sizeof(int)); close(fd); return; Si dos procesos ejecutan concurrentemente este código se puede perder algún ingreso. Solución: secciones críticas Sistemas operativos: una visión aplicada 13 J. Carretero, F. García, P. de Miguel, F. Pérez

Ejemplo 2 con sección crítica void ingresar(char *cuenta, int cantidad) { int saldo, fd; fd = open(cuenta, O_RDWR); <Entrada en la sección crítica> read(fd, &saldo, sizeof(int)); saldo = saldo + cantidad; lseek(fd, 0, SEEK_SET); write(fd, &saldo, sizeof(int)); <Salida de la sección crítica> close(fd); return; Sistemas operativos: una visión aplicada 14 J. Carretero, F. García, P. de Miguel, F. Pérez

Ejemplo 3 P r o c e s a d o r 1 P r o c e s a d o r 2 L e e P I D P I D = 5 0 0 R e g i s t r o o p o s i c i ó n d e m e m o r i a P I D = 5 0 0 I n c r e m e n t a y a s i g n a P I D L e e P I D P I D = 5 0 0 P I D = 5 0 1 E s c r i b e P I D P I D = 5 0 1 I n c r e m e n t a y a s i g n a P I D P I D = 5 0 1 P I D = 5 0 1 E s c r i b e P I D Sistemas operativos: una visión aplicada 15 J. Carretero, F. García, P. de Miguel, F. Pérez

Solución al problema de la sección crítica 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 Sistemas operativos: una visión aplicada 16 J. Carretero, F. García, P. de Miguel, F. Pérez

Problema del productor-consumidor P r o c e s o P r o d u c t o r P r o c e s o C o n s u m i d o r F l u j o d e d a t o s M e c a n i s m o d e c o m u n i c a c i ó n Sistemas operativos: una visión aplicada 17 J. Carretero, F. García, P. de Miguel, F. Pérez

El problema de los lectores-escritores L e c t o r L e c t o r E s c r i t o r L e c t o r E s c r i t o r R e c u r s o Sistemas operativos: una visión aplicada 18 J. Carretero, F. García, P. de Miguel, F. Pérez

Comunicación cliente-servidor C o m p u t a d o r C o m p u t a d o r P e t i c i ó n P r o c e s o c l i e n t e P r o c e s o s e r v i d o r S. O. R e s p u e s t a Sistemas operativos: una visión aplicada 19 J. Carretero, F. García, P. de Miguel, F. Pérez

Contenido Procesos concurrentes. Problemas clásicos de comunicación y sincronización. Mecanismos de comunicación y sincronización. Paso de mensajes. Aspectos de implementación Interbloqueos. Servicios POSIX Sistemas operativos: una visión aplicada 20 J. Carretero, F. García, P. de Miguel, F. Pérez

Mecanismos de comunicación Archivos Tuberías (pipes, FIFOS) Variables en memoria compartida Paso de mensajes Sistemas operativos: una visión aplicada 21 J. Carretero, F. García, P. de Miguel, F. Pérez

Mecanismos de Sincronización Construcciones de los lenguajes concurrentes (procesos ligeros) Servicios del sistema operativo: Señales (asincronismo) Tuberías (pipes, FIFOS) Semáforos Mutex y variables condicionales Paso de mensajes Las operaciones de sincronización deben ser atómicas Sistemas operativos: una visión aplicada 22 J. Carretero, F. García, P. de Miguel, F. Pérez

Tuberías (POSIX) Mecanismo de comunicación y sincronización Sin nombre: pipes Con nombre: FIFOS Sólo puede utilizarse entre los procesos hijos del proceso que creó el pipe int pipe(int fildes[2]); Identificación: dos descriptores de archivo Para lectura Para escritura Flujo de datos: unidireccional Mecanismo con capacidad de almacenamiento Sistemas operativos: una visión aplicada 23 J. Carretero, F. García, P. de Miguel, F. Pérez

Comunicación unidireccional con tuberías w r i t e P r o c e s o P r o c e s o r e a d d e U s u a r i o d e U s u a r i o S O p i p e F l u j o d e d a t o s Sistemas operativos: una visión aplicada 24 J. Carretero, F. García, P. de Miguel, F. Pérez

Comunicación bidireccional con tuberías w r i t e P r o c e s o r e a d w r i t e P r o c e s o r e a d d e U s u a r i o d e U s u a r i o S O p i p e F l u j o d e d a t o s p i p e F l u j o d e d a t o s Sistemas operativos: una visión aplicada 25 J. Carretero, F. García, P. de Miguel, F. Pérez

Tuberías (II) read(fildes[0], buffer, n) Pipe vacío se bloquea el lector Pipe con p bytes Si p n devuelve n Si p < n devuelve p Si pipe vacío y no hay escritores devuelve 0 write(fildes[1], buffer, n) Pipe lleno se bloquea el escritor Si no hay lectores se recibe la señal SIGPIPE Lecturas y escrituras atómicas (cuidado con tamaños grandes) Sistemas operativos: una visión aplicada 26 J. Carretero, F. García, P. de Miguel, F. Pérez

Secciones críticas con tuberías void main(void) { int fildes[2]; /* pipe para sincronizar */ char c; /* caracter para sincronizar */ pipe(fildes); write(fildes[1], &c, 1); /* necesario para entrar en la seccion critica la primera vez */ if (fork() == 0) { /* proceso hijo */ for(;;) { read(fildes[0], &c, 1); /* entrada seccion critica */ < Seccion critica > write(fildes[1], &c, 1); /* salida seccion critica */ Sistemas operativos: una visión aplicada 27 J. Carretero, F. García, P. de Miguel, F. Pérez

Secciones críticas con tuberías (II) else { /* proceso padre */ for(;;) { read(fildes[0], &c, 1); /* entrada seccion critica */ < seccion critica > write(fildes[1], &c, 1); /* salida seccion critica */ Sistemas operativos: una visión aplicada 28 J. Carretero, F. García, P. de Miguel, F. Pérez

Productor-consumidor con tuberías void main(void) { int fildes[2]; /* pipe para comunicar y sincronizar */ int dato_p[4]; /* datos a producir */ int dato_c; /* dato a consumir */ pipe(fildes); if (fork() == 0) { /* proceso hijo: productor */ for(;;) { < producir dato_p, escribe 4 enteros * write(fildes[1], dato_p, 4*sizeof(int)); Sistemas operativos: una visión aplicada 29 J. Carretero, F. García, P. de Miguel, F. Pérez

Productor-consumidor con tuberías (II) else { /* proceso padre: consumidor */ for(;;) { read(fildes[0], &dato, sizeof(int)); /* consumir dato, lee un entero */ Proceso hijo Pipe Proceso padre Sistemas operativos: una visión aplicada 30 J. Carretero, F. García, P. de Miguel, F. Pérez

Ejecución de mandatos con tuberías /* programa que ejecuta el mandato ``ls wc'' */ void main(void) { int fd[2]; pid_t pid; ls pipe wc if (pipe(fd) < 0) { perror(``pipe''); exit(-1); pid = fork(); switch(pid) { case -1: /* error */ perror(``fork''); exit(-1); Sistemas operativos: una visión aplicada 31 J. Carretero, F. García, P. de Miguel, F. Pérez

Ejecución de mandatos con tuberías (II) case 0: /* proceso hijo ejecuta ``ls'' */ close(fd[0]); /* cierra el pipe de lectura */ close(stdout_fileno); /* cierra la salida estandar */ dup(fd[1]); close(fd[1]); execlp(``ls'',``ls'',null); perror(``execlp''); exit(-1); default: /* proceso padre ejecuta ``wc'' */ close(fd[1]); /* cierra el pipe de escritura */ close(stdin_fileno); /* cierra la entrada estandar */ dup(fd[0]); close(fd[0]); execlp(``wc'',``wc'',null); perror(``execlp''); Sistemas operativos: una visión aplicada 32 J. Carretero, F. García, P. de Miguel, F. Pérez

Ejecución de mandatos con tuberías (III) Proceso Proceso STDIN STDOUT pipe(fd) STDIN STDOUT fd[0] fd[1] pipe fork() Proceso Proceso hijo STDIN STDOUT fd[0] fd[1] pipe STDIN STDOUT fd[0] fd[1] redirección Proceso Proceso hijo STDIN STDOUT pipe STDIN STDOUT exec Proceso Proceso hijo STDIN STDOUT pipe STDIN STDOUT ls wc Sistemas operativos: una visión aplicada 33 J. Carretero, F. García, P. de Miguel, F. Pérez

Tuberías con nombre en POSIX (FIFOS) Igual que los pipes Mecanismo de comunicación y sincronización con nombre Misma máquina Servicios int mkfifo(char *name, mode_t mode); Crea un FIFO con nombre name int open(char *name, int flag); Abre un FIFO (para lectura, escritura o ambas) Bloquea hasta que haya algún proceso en el otro extremo Lectura y escritura mediante read() y write() Igual semántica que los pipes Cierre de un FIFO mediante close() Borrado de un FIFO mediante unlink() Sistemas operativos: una visión aplicada 34 J. Carretero, F. García, P. de Miguel, F. Pérez

Semáforos Mecanismo de sincronización Misma máquina Objeto con un valor entero Dos operaciones atómicas wait signal Sistemas operativos: una visión aplicada 35 J. Carretero, F. García, P. de Miguel, F. Pérez

Operaciones sobre emáforos wait(s) { s = s - 1; if (s < 0) { <Bloquear al proceso> signal(s) { s = s + 1; if (s <= 0) <Desbloquear a un proceso bloqueado por la operacion wait> Sistemas operativos: una visión aplicada 36 J. Carretero, F. García, P. de Miguel, F. Pérez

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 P 1 P 2 1 0-1 -2 wait(s) wait(s) wait(s) -1 signal(s) desbloquea 0 signal(s) desbloquea Ejecutando código de la sección crítica 1 signal(s) Proceso bloqueado en el semáforo Sistemas operativos: una visión aplicada 37 J. Carretero, F. García, P. de Miguel, F. Pérez

Semáforos POSIX int sem_init(sem_t *sem, int shared, int val); Inicializa un semáforo sin nombre int sem_destroy(sem_t *sem); Destruye un semáforo sin nombre sem_t *sem_open(char *name, int flag, mode_t mode, int val); Abre (crea) un semáforo con nombre. int sem_close(sem_t *sem); Cierra un semáforo con nombre. int sem_unlink(char *name); Borra un semáforo con nombre. int sem_wait(sem_t *sem); Realiza la operación wait sobre un semáforo. int sem_post(sem_t *sem); Realiza la operación signal sobre un semáforo. Sistemas operativos: una visión aplicada 38 J. Carretero, F. García, P. de Miguel, F. Pérez

Productor-consumidor con semáforos (buffer acotado y circular) Productor Consumidor Sistemas operativos: una visión aplicada 39 J. Carretero, F. García, P. de Miguel, F. Pérez

Productor-consumidor con semáforos (II) #define MAX_BUFFER 1024 /* tamanio del buffer */ #define DATOS_A_PRODUCIR 100000 /* datos a producir */ sem_t elementos; /* elementos en el buffer */ sem_t huecos; /* huecos en el buffer */ int buffer[max_buffer]; /* buffer comun */ void main(void) { pthread_t th1, th2; /* identificadores de threads */ /* inicializar los semaforos */ sem_init(&elementos, 0, 0); sem_init(&huecos, 0, MAX_BUFFER); Sistemas operativos: una visión aplicada 40 J. Carretero, F. García, P. de Miguel, F. Pérez

Productor-consumidor con semáforos (III) /* crear los procesos ligeros */ pthread_create(&th1, NULL, Productor, NULL); pthread_create(&th2, NULL, Consumidor, NULL); /* esperar su finalizacion */ pthread_join(th1, NULL); pthread_join(th2, NULL); sem_destroy(&huecos); sem_destroy(&elementos); exit(0); Sistemas operativos: una visión aplicada 41 J. Carretero, F. García, P. de Miguel, F. Pérez

Productor-consumidor con semáforos (IV) void Productor(void) /* codigo del productor */ { int pos = 0; /* posicion dentro del buffer */ int dato; /* dato a producir */ int i; for(i=0; i < DATOS_A_PRODUCIR; i++ ) { dato = i; /* producir dato */ sem_wait(&huecos); /* un hueco menos */ buffer[pos] = i; pos = (pos + 1) % MAX_BUFFER; sem_post(&elementos); /* un elemento mas */ pthread_exit(0); Sistemas operativos: una visión aplicada 42 J. Carretero, F. García, P. de Miguel, F. Pérez

Productor-consumidor con semáforos (V) void Consumidor(void) /* codigo del Consumidor */ { int pos = 0; int dato; int i; for(i=0; i < DATOS_A_PRODUCIR; i++ ) { sem_wait(&elementos); /* un elemento menos */ dato = buffer[pos]; pos = (pos + 1) % MAX_BUFFER; sem_post(&huecos); /* un hueco mas */ /* cosumir dato */ pthread_exit(0); Sistemas operativos: una visión aplicada 43 J. Carretero, F. García, P. de Miguel, F. Pérez

Lectores-escritores con semáforos int dato = 5; /* recurso */ int n_lectores = 0; /* numero de lectores */ sem_t sem_lec; /* controlar el acceso n_lectores */ sem_t mutex; /* controlar el acceso a dato */ void main(void) { pthread_t th1, th2, th3, th4; sem_init(&mutex, 0, 1); sem_init(&sem_lec, 0, 1); pthread_create(&th1, NULL, Lector, NULL); pthread_create(&th2, NULL, Escritor, NULL); pthread_create(&th3, NULL, Lector, NULL); pthread_create(&th4, NULL, Escritor, NULL); Sistemas operativos: una visión aplicada 44 J. Carretero, F. García, P. de Miguel, F. Pérez

Lectores-escritores con semáforos (II) pthread_join(th1, NULL); pthread_join(th2, NULL); pthread_join(th3, NULL); pthread_join(th4, NULL); /* cerrar todos los semaforos */ sem_destroy(&mutex); sem_destroy(&sem_lec); exit(0); Sistemas operativos: una visión aplicada 45 J. Carretero, F. García, P. de Miguel, F. Pérez

Lectores-escritores con semáforos (III) /* codigo del lector */ void Lector(void) { /* codigo del lector */ sem_wait(&sem_lec); n_lectores = n_lectores + 1; if (n_lectores == 1) sem_wait(&mutex); sem_post(&sem_lec); printf(``%d\n'', dato); /* leer dato */ sem_wait(&sem_lec); n_lectores = n_lectores - 1; if (n_lectores == 0) sem_post(&mutex); sem_post(&sem_lec); pthread_exit(0); Sistemas operativos: una visión aplicada 46 J. Carretero, F. García, P. de Miguel, F. Pérez

Lectores-escritores con semáforos (IV) /* código del escritor */ void Escritor(void) { /* codigo del escritor */ sem_wait(&mutex); dato = dato + 2; /* modificar el recurso */ sem_post(&mutex); pthread_exit(0); Sistemas operativos: una visión aplicada 47 J. Carretero, F. García, P. de Miguel, F. Pérez

Memoria compartida P r o c e s o A P r o c e s o B T e x t o D a t o s T e x t o D a t o s v a r 2 v a r 1 P i l a 2 S e g m e n t o d e m e m o r i a c o m p a r t i d a P i l a Declaración independiente de variables Sistemas operativos: una visión aplicada 48 J. Carretero, F. García, P. de Miguel, F. Pérez

Productor-consumidor con memoria compartida Productor: Crea los semáforos (shm_open) Crea la zona de memoria compartida utilizando un archivo proyectado en memoria (open) Le asigna espacio (ftruncate) Proyecta el archivo en su espacio de direcciones (mmap) Utiliza la zona de memoria compartida Desproyecta la zona de memoria compartida Cierra y borra el archivo. Consumidor: Abre los semáforos (shm_open) Debe esperar a que archivo esté creado para abrirlo (open) Proyecta el archivo en su espacio de direcciones (mmap) Utiliza la zona de memoria compartida Cierra el archivo. Sistemas operativos: una visión aplicada 49 J. Carretero, F. García, P. de Miguel, F. Pérez

Código del productor #define MAX_BUFFER 1024 /* tamaño del buffer */ #define DATOS_A_PRODUCIR 100000 /* datos a producir */ sem_t *elementos; /* elementos en el buffer */ sem_t *huecos; /* huecos en el buffer */ void main(int argc, char *argv[]){ int shd; int *buffer; /* buffer comun */ /* el productor crea el archivo a proyectar */ shd = open("buffer", O_CREAT O_WRONLY, 0700); ftruncate(shd, MAX_BUFFER * sizeof(int)); /*proyectar el objeto de memoria compartida en el espacio de direcciones del productor*/ buffer = (int *) mmap(null, MAX_BUFFER * sizeof(int), PROT_WRITE, MAP_SHARED, shd, 0); Sistemas operativos: una visión aplicada 50 J. Carretero, F. García, P. de Miguel, F. Pérez

Código del productor (II) /* El productor crea los semaforos */ elementos = sem_open("elementos", O_CREAT, 0700, 0); huecos = sem_open("huecos", O_CREAT, 0700, MAX_BUFFER); Productor(buffer); /* desproyectar el buffer compartido */ munmap(buffer, MAX_BUFFER * sizeof(int)); close(shd); /* cerrar el objeto de memoria compartida */ unlink("buffer"); /* borrar el objeto de memoria */ sem_close(elementos); sem_close(huecos); sem_unlink("elementos"); sem_unlink("huecos"); Sistemas operativos: una visión aplicada 51 J. Carretero, F. García, P. de Miguel, F. Pérez

Código del productor (III) void Productor(int *buffer) /* codigo del productor */ { int pos = 0; /* posicion dentro del buffer */ int dato; /* dato a producir */ int i; for(i=0; i < DATOS_A_PRODUCIR; i++ ) { dato = i; /* producir dato */ sem_wait(huecos); /* un hueco menos */ buffer[pos] = i; pos = (pos + 1) % MAX_BUFFER; sem_post(elementos); /* un elemento mas */ return; Sistemas operativos: una visión aplicada 52 J. Carretero, F. García, P. de Miguel, F. Pérez

Código del consumidor #define MAX_BUFFER 1024 /* tamanio del buffer */ #define DATOS_A_PRODUCIR 100000 /* datos a producir */ sem_t *elementos; /* elementos en el buffer */ sem_t *huecos; /* huecos en el buffer */ void main(int argc, char *argv[]){ int shd; int *buffer; /* buffer comun */ /* el consumidor abre el archivo a proyectar */ shd = open("buffer", O_RDONLY); /*proyectar el objeto de memoria compartida en el espacio de direcciones del productor*/ buffer = (int *) mmap(null, MAX_BUFFER * sizeof(int), PROT_READ, MAP_SHARED, shd, 0); Sistemas operativos: una visión aplicada 53 J. Carretero, F. García, P. de Miguel, F. Pérez

Código del consumidor (II) /* El consumidor abre los semaforos */ elementos = sem_open("elementos", 0); huecos = sem_open("huecos", 0); Consumidor(buffer); /* desproyectar el buffer compartido */ munmap(buffer, MAX_BUFFER * sizeof(int)); close(shd); /* cerrar el objeto de memoria compartida */ /* cerrar los semaforos */ sem_close(elementos); sem_close(huecos); Sistemas operativos: una visión aplicada 54 J. Carretero, F. García, P. de Miguel, F. Pérez

Código del consumidor (III) void Consumidor(char *buffer) /* codigo del Consumidor */ { int pos = 0; int i, dato; for(i=0; i < DATOS_A_PRODUCIR; i++ ) { sem_wait(elementos); /* un elemento menos */ dato = buffer[pos]; pos = (pos + 1) % MAX_BUFFER; sem_post(huecos); /* un hueco mas */ printf("consume %d \n", dato); /* cosumir dato */ return; Sistemas operativos: una visión aplicada 55 J. Carretero, F. García, P. de Miguel, F. Pérez

Mutex y variables condicionales Un mutex es un mecanismo de sincronización indicado para procesos ligeros. Es un semáforo binario con dos operaciones atómicas: lock(m) Intenta bloquear el mutex, si el mutex ya está bloqueado el proceso se suspende. unlock(m) Desbloquea el mutex, si existen procesos bloqueados en el mutex se desbloquea a uno. Sistemas operativos: una visión aplicada 56 J. Carretero, F. García, P. de Miguel, F. Pérez

Secciones críticas con mutex lock(m); /* entrada en la seccion critica */ < seccion critica > unlock(s); /* salida de la seccion critica */ La operación unlock debe realizarla el proceso ligero que ejecutó lock P r o c e s o l i g e r o A P r o c e s o l i g e r o B l o c k m u t e x l o c k m u t e x S e c c i ó n c r í t i c a u n l o c k m u t e x o b t i e n e m u t e x P r o c e s o l i g e r o e j e c u t a n d o P r o c e s o li g e r o b l o q u e a d o P u n t o d e s i n c r o n i z a c i ó n Sistemas operativos: una visión aplicada 57 J. Carretero, F. García, P. de Miguel, F. Pérez

Variables condicionales Variables de sincronización asociadas a un mutex Conveniente ejecutarlas entre lock y unlock Dos operaciones atómicas: wait Bloquea al proceso ligero que la ejecuta y le expulsa del mutex signal Desbloquea a uno o varios procesos suspendidos en la variable condicional. El proceso que se despierta compite de nuevo por el mutex Sistemas operativos: una visión aplicada 58 J. Carretero, F. García, P. de Miguel, F. Pérez

Variables condicionales (II) P r o c e s o l i g e r o A P r o c e s o l i g e r o B l o c k l o c k w a i t u n l o c k m u t e x A d q u i e r e e l m u t e x S e c o m p i t e p o r e l m u t e x A d q u i e r e e l m u t e x s i g n a l u n l o c k P r o c e s o l i g e r o b l o q u e a d o e s p e r a n d o u n l o c k P r o c e s o l i g e r o b l o q u e a d o e s p e r a n d o s i g n a l Sistemas operativos: una visión aplicada 59 J. Carretero, F. García, P. de Miguel, F. Pérez

Uso de mutex y variables condicionales Proceso ligero A lock(mutex); /* acceso al recurso */ comprobar las estructuras de datos; while (recurso ocupado) wait(condition, mutex); marcar el recurso como ocupado; unlock(mutex); Proceso ligero B lock(mutex); /* acceso al recurso */ marcar el recurso como libre; signal(condition, mutex); unlock(mutex); Importante utilizar while Sistemas operativos: una visión aplicada 60 J. Carretero, F. García, P. de Miguel, F. Pérez

Servicios POSIX int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t * attr); Inicializa un mutex. int pthread_mutex_destroy(pthread_mutex_t *mutex) ; Destruye un mutex. int pthread_mutex_lock(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_unlock(pthread_mutex_t *mutex); Desbloquea el mutex. int pthread_cond_init(pthread_cond_t*cond, pthread_condattr_t*attr); Inicializa una variable condicional. Sistemas operativos: una visión aplicada 61 J. Carretero, F. García, P. de Miguel, F. Pérez

Servicios POSIX (II) int pthread_cond_destroy(pthread_cond_t *cond); Destruye un variable condicional. 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. int pthread_cond_wait(pthread_cond_t*cond, pthread_mutex_t*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. Sistemas operativos: una visión aplicada 62 J. Carretero, F. García, P. de Miguel, F. Pérez

Productor-consumidor con mutex #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 */ 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); Sistemas operativos: una visión aplicada 63 J. Carretero, F. García, P. de Miguel, F. Pérez

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); exit(0); Sistemas operativos: una visión aplicada 64 J. Carretero, F. García, P. de Miguel, F. Pérez

Productor-consumidor con mutex (III) void Productor(void) { /* codigo del productor */ 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(&no_lleno, &mutex); /* se bloquea */ buffer[pos] = i; pos = (pos + 1) % MAX_BUFFER; n_elementos ++; pthread_cond_signal(&no_vacio); /* buffer no vacio */ pthread_mutex_unlock(&mutex); pthread_exit(0); Sistemas operativos: una visión aplicada 65 J. Carretero, F. García, P. de Miguel, F. Pérez

Productor-consumidor con mutex (IV) void Consumidor(void) { /* codigo del sonsumidor */ 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 vacio */ pthread_cond_wait(&no_vacio, &mutex); /* se bloquea */ dato = buffer[pos]; pos = (pos + 1) % MAX_BUFFER; n_elementos --; pthread_cond_signal(&no_lleno); /* buffer no lleno */ pthread_mutex_unlock(&mutex); printf("consume %d \n", dato); /* consume dato */ pthread_exit(0); Sistemas operativos: una visión aplicada 66 J. Carretero, F. García, P. de Miguel, F. Pérez

Lectores-escritores con mutex int dato = 5; /* recurso */ int n_lectores = 0; /* numero de lectores */ pthread_mutex_t mutex; /* controlar el acceso a dato */ pthread_mutex_t mutex_lectores; /* controla la variable n_lectores */ main(int argc, char *argv[]) { pthread_t th1, th2, th3, th4; pthread_mutex_init(&mutex, NULL); pthread_cond_init(&no_lectores, NULL); pthread_create(&th1, NULL, Lector, NULL); pthread_create(&th2, NULL, Escritor, NULL); pthread_create(&th3, NULL, Lector, NULL); pthread_create(&th4, NULL, Escritor, NULL); Sistemas operativos: una visión aplicada 67 J. Carretero, F. García, P. de Miguel, F. Pérez

Lectores-escritores con mutex (II) pthread_join(th1, NULL); pthread_join(th2, NULL); pthread_join(th3, NULL); pthread_join(th4, NULL); pthread_mutex_destroy(&mutex); pthread_cond_destroy(&no_lectores); exit(0); void Escritor(void) { /* codigo del escritor */ pthread_mutex_lock(&mutex); dato = dato + 2; /* modificar el recurso */ pthread_mutex_unlock(&mutex); pthread_exit(0); Sistemas operativos: una visión aplicada 68 J. Carretero, F. García, P. de Miguel, F. Pérez

Lectores-escritores con mutex (III) void Lector(void) { /* codigo del lector */ pthread_mutex_lock(&mutex_lectores); n_lectores++; if (n_lectores == 1) pthread_mutex_lock(&mutex); pthread_mutex_unlock(&mutex_lectores); printf("%d\n", dato); /* leer dato */ pthread_mutex_lock(&mutex_lectores); n_lectores--; if (n_lectores == 0) pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex_lectores); pthread_exit(0); Sistemas operativos: una visión aplicada 69 J. Carretero, F. García, P. de Miguel, F. Pérez

Contenido Procesos concurrentes. Problemas clásicos de comunicación y sincronización. Mecanismos de comunicación y sincronización. Paso de mensajes. Aspectos de implementación Interbloqueos. Servicios POSIX Sistemas operativos: una visión aplicada 70 J. Carretero, F. García, P. de Miguel, F. Pérez

Paso de mensajes Permite resolver: Exclusión mutua Sincronizar entre un proceso que recibe un mensaje y otro que lo envía Comunicación de datos entre espacios de memoria diferentes (mismo computador, diferentes computadores) Primitivas básicas: send(destino, mensaje) envía un mensaje al proceso destino receive(destino, mensaje) recibe un mensaje del proceso destino Múltiples soluciones Aspectos de diseño Tamaño del mensaje Flujo de datos (unidireccional, bidireccional) Nombrado Directo Indirecto (puertos, colas) Sincronización (síncrono, asíncrono) Almacenamiento Sistemas operativos: una visión aplicada 71 J. Carretero, F. García, P. de Miguel, F. Pérez

Uso de colas y puertos P r o c e s o c l i e n t e P r o c e s o c l i e n t e s e n d r e c e i v e P r o c e s o c l i e n t e P r o c e s o c l i e n t e s e n d P u e r t o m e n s a j e m e n s a j e C o l a d e m e n s a j e s C o m u n i c a c i ó n c o n c o l a s d e m e n s a j e s C o m u n i c a c i ó n c o n p u e r t o s Sistemas operativos: una visión aplicada 72 J. Carretero, F. García, P. de Miguel, F. Pérez

Colas de mensajes POSIX mqd_t mq_open(char *name, int flag, mode_t mode, mq_attr *attr); Crea una cola de mensajes con nombre y atributos attr: Número máximo de mensajes. Tamaño máximo del mensaje. Bloqueante, No bloqueante. int mq_close (mqd_t mqdes); Cierra una cola de mensajes. int mq_unlink(char *name); Borra una cola de mensajes. Sistemas operativos: una visión aplicada 73 J. Carretero, F. García, P. de Miguel, F. Pérez

Colas de mensajes POSIX (II) int mq_send(mqd_t mqdes, char *msg, size_t len, int prio); Envía el mensaje msg de longitud len a la cola de mensajes mqdes con prioridad prio; Si la cola está llena el envío puede ser bloqueante o no. 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. Sistemas operativos: una visión aplicada 74 J. Carretero, F. García, P. de Miguel, F. Pérez

Secciones críticas con colas de mensajes void main(void) { mqd_t mutex; /* cola de mensajes para sincronizar el acceso a la seccion critica */ struct mq_attr attr; /* atributos de la cola de mensajes */ char c; /* caracter para sincronizar */ attr.mq_maxmsg = 1; /* numero maximo de mensajes */ attr.mq_msgsize = 1; /* tamanio del mensaje */ mutex = mq_open(``mutex'', O_CREAT O_RDWR, 0777, &attr); mq_send(mutex, &c, 1, 0); seccion /* necesario para entrar en la critica la primera vez */ Sistemas operativos: una visión aplicada 75 J. Carretero, F. García, P. de Miguel, F. Pérez

Secciones críticas con colas de mensajes (II) if (fork() == 0) { /* proceso hijo */ for(;;) { mq_receive(mutex, &c, 1, 0); /* entrada seccion critica */ /* seccion critica */ mq_send(mutex, &c, 1, 0); /* salida seccion critica */ else { /* proceso padre */ for(;;) { mq_receive(mutex, &c, 1, 0); /* entrada seccion critica */ /* seccion critica */ mq_send(mutex, &c, 1, 0); /* salida seccion critica */ Sistemas operativos: una visión aplicada 76 J. Carretero, F. García, P. de Miguel, F. Pérez

Productor-consumidor con colas de mensajes #define MAX_BUFFER 1024 /* tamanio del buffer */ #define DATOS_A_PRODUCIR 100000 /* datos a producir */ mqd_t almacen; /* cola de mensaje donde dejar los datos producidos y recoger los datos a consumir */ void main(void) { struct mq_attr attr; attr.mq_maxmsg = MAX_BUFFER; attr.mq_msgsize = sizeof(int); almacen = mq_open("almacen", O_CREAT O_RDWR, 0777, &attr); if (almacen == -1) { perror("mq_open"); exit(0); Sistemas operativos: una visión aplicada 77 J. Carretero, F. García, P. de Miguel, F. Pérez

Productor-consumidor con colas de mensajes (II) if (fork() == 0) /* proceso hijo */ Productor(); else /* proceso padre */ Consumidor(); exit(0); void Productor(void) /* codigo del productor */ { int dato, i; for(i=0; i < DATOS_A_PRODUCIR; i++ ) { dato = i; /* producir dato */ printf("produce %d \n", dato); mq_send(almacen, &dato, sizeof(int), 0); return; Sistemas operativos: una visión aplicada 78 J. Carretero, F. García, P. de Miguel, F. Pérez

Productor-consumidor con colas de mensajes (III) /* codigo del consumidor */ void Consumidor(void) { int dato; int i; for(i=0; i < DATOS_A_PRODUCIR; i++ ) { mq_receive(almacen, &dato, sizeof(int), 0); /* cosumir dato */ printf("consume %d \n", dato); return; Sistemas operativos: una visión aplicada 79 J. Carretero, F. García, P. de Miguel, F. Pérez

Servidor multithread con colas de mensajes P r o c e s o c l i e n t e P r o c e s o c l i e n t e C o l a d e l C o l a d e l c l i e n t e p e t i c i ó n c l i e n t e P r o c e s o s e r v i d o r p e t i c i ó n r e s p u e s t a C o l a d e l s e r v i d o r C r e a c i ó n d e l t h r e a d r e s p u e s t a C r e a c i ó n d e l t h r e a d T h r e a d q u e s i r v e l a p e t i c i ó n T h r e a d q u e s i r v e l a p e t i c i ó n Sistemas operativos: una visión aplicada 80 J. Carretero, F. García, P. de Miguel, F. Pérez

Servidor multithread con colas de mensajes (II) /* estructura de un mensaje */ struct mensaje { char buffer[1024]; /* datos a enviar */ char cliente[256]; /* cola del cliente */ ; /* mutex y variables condicionales para proteger la copia del mensaje */ pthread_mutex_t mutex_mensaje; int mensaje_no_copiado = TRUE; pthread_cond_t cond; void main(void){ mqd_t q_servidor; /* cola del servidor */ struct mensaje mess; /* mensaje a recibir */ struct mq_attr q_attr; /* atributos de la cola */ pthread_attr_t t_attr; /* atributos de los threads */ Sistemas operativos: una visión aplicada 81 J. Carretero, F. García, P. de Miguel, F. Pérez

Servidor multithread con colas de mensajes (II) attr.mq_maxmsg = 20; attr.mq_msgsize = sizeof(struct mensaje)); q_servidor = mq_open("servidor", O_CREAT O_RDONLY, 0700, &attr); pthread_mutex_init(&mutex_mensaje, NULL); pthread_cond_init(&cond, NULL); pthread_attr_init(&attr); pthread_attr_setscope(&attr,pthread_scope_system); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); Sistemas operativos: una visión aplicada 82 J. Carretero, F. García, P. de Miguel, F. Pérez

Servidor multithread con colas de mensajes (III) while (TRUE) { mq_receive(q_servidor, &mess, sizeof(struct mensaje), 0); pthread_create(&thid, &attr, tratar_mensaje, &mess); /* se espera a que el thread copie el mensaje */ pthread_mutex_lock(&mutex_mensaje); while (mensaje_no_copiado) pthread_cond_wait(&cond, &mutex_mensaje); mensaje_no_copiado = TRUE; pthread_mutex_unlock(&mutex_mensaje); Sistemas operativos: una visión aplicada 83 J. Carretero, F. García, P. de Miguel, F. Pérez

Servidor multithread con colas de mensajes (IV) void tratar_mensaje(struct mensaje *mes) { struct mensaje mensaje_local; struct mqd_t q_cliente; /* cola del cliente */ struct mensaje respueta; /* mensaje de respuesta al cliente */ /* el thread copia el mensaje */ pthread_mutex_lock(&mutex_mensaje); memcpy((char *) &mensaje_local, (char *)&mes, sizeof(struct mensaje)); /* ya se puede despertar al servidor*/ pthread_mutex_lock(&mutex_mensaje); mensaje_no_copiado = FALSE; pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex_mensaje); Sistemas operativos: una visión aplicada 84 J. Carretero, F. García, P. de Miguel, F. Pérez

Servidor multithread con colas de mensajes (V) /* ejecutar la petición del cliente */ /* y preparar respuesta */ /* responder al cliente a su cola */ q_cliente = mq_open(mensaje_local.nombre, O_WRONLY); mqsend(q_cliente, (char *) &respueta, sizeof(respuesta), 0); mq_clise(q_cliente); pthread_exit(0); Sistemas operativos: una visión aplicada 85 J. Carretero, F. García, P. de Miguel, F. Pérez

Ejemplo de código cliente /* estructura de un mensaje */ struct mensaje { char buffer[1024]; /* datos a enviar */ char cliente[256]; /* cola del cliente */ ; void main(void) { mqd_t q_servidor; /* cola del servidor */ mqd_t q_cliente; /* cola del cliente */ struct mq_attr q_attr; /* atributos de la cola */ struct mensaje peticion; /* peticion al servidor */ struct mensaje respuesta; /* respuesta del servidor */ attr.mq_maxmsg = 1; attr.mq_msgsize = sizeof(struct mensaje)); Sistemas operativos: una visión aplicada 86 J. Carretero, F. García, P. de Miguel, F. Pérez

Ejemplo de código cliente (II) q_cliente = mq_open("cliente", O_CREAT O_RDONLY, 0700, 0); q_servidor = mq_open("servidor", O_WRONLY); /* preparar peticion */ mq_send(q_servidor, &petcicion, sizeof(struct mensaje), 0); /* esperar respuesta */ mq_receive(q_cliente, &respuesta, sizeof(struct mensaje), 0); mq_close(q_servidor); mq_close(q_cliente); mq_unlink("cliente"); exit(0); Sistemas operativos: una visión aplicada 87 J. Carretero, F. García, P. de Miguel, F. Pérez

Contenido Procesos concurrentes. Problemas clásicos de comunicación y sincronización. Mecanismos de comunicación y sincronización. Paso de mensajes. Aspectos de implementación Interbloqueos. Servicios POSIX Sistemas operativos: una visión aplicada 88 J. Carretero, F. García, P. de Miguel, F. Pérez

Implementación de mecanismos de sincronización Espera activa: wait(s) { s = s 1; while (s < 0) ; signal(s) { s = s + 1; Espera pasiva wait(s) { s = s 1; if (s < 0) Bloquear al proceso; signal(s) { s = s + 1; if (s <= 0) Desbloquear a un proceso bloqueado en la operación wait; Sistemas operativos: una visión aplicada 89 J. Carretero, F. García, P. de Miguel, F. Pérez

Implementación de la espera pasiva Operaciones para bloquear a un proceso en un semáforo T a b l a d e p r o c e s o s E s t a d o P I D B C P 1 B C P 2 B C P 3 B C P 4 B C P 5 B C P 6 B C P 7 B C P 8 B C P 9 B C P 1 0 B C P 1 1 B C P 1 2 B l o q. E j e c. 0 7 6 1 1 1 5 0 8 9 C o l a a s o c i a d a a l s e m á f o r o 7 ( a ) T a b l a d e p r o c e s o s E s t a d o P I D B C P 1 B C P 2 B C P 3 B C P 4 B C P 5 B C P 6 B C P 7 B C P 8 B C P 9 B C P 1 0 B C P 1 1 B C P 1 2 B l o q. B l o q. B l o q. 0 7 6 1 1 1 5 0 8 9 C o l a a s o c i a d a a l s e m á f o r o 7 1 1 ( b ) Sistemas operativos: una visión aplicada 90 J. Carretero, F. García, P. de Miguel, F. Pérez

Implementación de la espera pasiva Operaciones para desbloquear a un proceso bloqueado en un semáforo T a b l a d e p r o c e s o s E s t a d o P I D B C P 1 B C P 2 B C P 3 B C P 4 B C P 5 B C P 6 B C P 7 B C P 8 B C P 9 B C P 1 0 B C P 1 1 B C P 1 2 B l o q. B l o q. B l o q. 0 7 6 1 1 1 5 0 8 9 C o l a a s o c i a d a a l s e m á f o r o 7 1 1 ( a ) T a b l a d e p r o c e s o s E s t a d o P I D B C P 1 B C P 2 B C P 3 B C P 4 B C P 5 B C P 6 B C P 7 B C P 8 B C P 9 B C P 1 0 B C P 1 1 B C P 1 2 L i s t o B l o q. B l o q. 0 7 6 1 1 1 5 0 8 9 C o l a a s o c i a d a a l s e m á f o r o 1 1 ( b ) Sistemas operativos: una visión aplicada 91 J. Carretero, F. García, P. de Miguel, F. Pérez

Instrucciones hardware especiales Operación atómicas int test-and-set(int *valor) { int temp; temp = *valor; *valor = 1; /* true */ return temp; void swap (int *a, int *b) { int temp; temp = *a; *a = *b; *b = temp; return; Sistemas operativos: una visión aplicada 92 J. Carretero, F. García, P. de Miguel, F. Pérez

Sección crítica con test-and-set Los procesos comparten la variable lock (con valor inicial a false) while (test-and-set(&lock)) ; <Código de la sección crítica> lock = false; Sistemas operativos: una visión aplicada 93 J. Carretero, F. García, P. de Miguel, F. Pérez

Sección crítica con swap Los procesos comparten la variable lock con valor inicial false. Cada proceso utiliza una variable local llave. llave = true; do swap(lock, llave); while (llave!= false); <Código de la sección crítica> lock = false; Sistemas operativos: una visión aplicada 94 J. Carretero, F. García, P. de Miguel, F. Pérez

Implementación de un semáforo con test-andset wait(s){ while (test-and-set(&valor_s)) ; s = s - 1; if (s < 0){ valor_s = false; Bloquear al proceso; else valor_s = false; signal(s){ while (test-and-set(&valor_s)) ; s = s + 1; if ( s <= 0){ Desbloquear a un proceso bloqueado en la operación wait; valor_s = false; Sistemas operativos: una visión aplicada 95 J. Carretero, F. García, P. de Miguel, F. Pérez

Contenido Procesos concurrentes. Problemas clásicos de comunicación y sincronización. Mecanismos de comunicación y sincronización. Paso de mensajes. Aspectos de implementación Interbloqueos. Servicios POSIX Sistemas operativos: una visión aplicada 96 J. Carretero, F. García, P. de Miguel, F. Pérez

Interbloqueos Bloqueo permanente de un conjunto de procesos que compiten por los recursos del sistema o se comunican entre sí. Ejemplo: Si P y Q con semáforos con valor inicial 1 P1 P2 wait(p) wait(q) wait(q) wait(p)...... signal(p) signal(q) signal(q) siangl(p) Sistemas operativos: una visión aplicada 97 J. Carretero, F. García, P. de Miguel, F. Pérez

Ejemplo de interbloqueo P A B Q Sistemas operativos: una visión aplicada 98 J. Carretero, F. García, P. de Miguel, F. Pérez

Interbloqueos II Ejemplo: Si C1 y C2 son dos colas de mensajes: P1 P2 receive(p2, M) receive(p1, N)...... send(p2, M) send(p1, N) Condiciones del interbloqueo: Exclusión mutua Retención y espera No apropiación Espera circular Sistemas operativos: una visión aplicada 99 J. Carretero, F. García, P. de Miguel, F. Pérez

Contenido Procesos concurrentes. Problemas clásicos de comunicación y sincronización. Mecanismos de comunicación y sincronización. Paso de mensajes. Aspectos de implementación Interbloqueos. Servicios POSIX Sistemas operativos: una visión aplicada 100 J. Carretero, F. García, P. de Miguel, F. Pérez

Tuberías Crear una tubería sin nombre int pipe(int fildes[2]); Crear una tuberías con nombre int mkfifo(char *name, mode_t mode); Abrir una tubería con nombre int open(char *fifo, int flag); Cerrar una tubería int close(int fd); Borrar una tubería con nombre int unlink(char *fifo); Leer de una tubería int read(fildes[0], buffer, n); Escribir en una tubería int write(fildes[1], buffer, n); Sistemas operativos: una visión aplicada 101 J. Carretero, F. García, P. de Miguel, F. Pérez

Semáforos int sem_init(sem_t *sem, int shared, int val); Inicializa un semáforo sin nombre int sem_destroy(sem_t *sem); Destruye un semáforo sin nombre sem_t *sem_open(char *name, int flag, mode_t mode, int val); Abre (crea) un semáforo con nombre. int sem_close(sem_t *sem); Cierra un semáforo con nombre. int sem_unlink(char *name); Borra un semáforo con nombre. int sem_wait(sem_t *sem); Realiza la operación wait sobre un semáforo. int sem_post(sem_t *sem); Realiza la operación signal sobre un semáforo. Sistemas operativos: una visión aplicada 102 J. Carretero, F. García, P. de Miguel, F. Pérez

Mutex int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t * attr); Inicializa un mutex. int pthread_mutex_destroy(pthread_mutex_t *mutex) ; Destruye un mutex. int pthread_mutex_lock(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_unlock(pthread_mutex_t *mutex); Desbloquea el mutex. Sistemas operativos: una visión aplicada 103 J. Carretero, F. García, P. de Miguel, F. Pérez

Variables condicionales int pthread_cond_init(pthread_cond_t*cond, pthread_condattr_t*attr); Inicializa una variable condicional. int pthread_cond_destroy(pthread_cond_t *cond); Destruye un variable condicional. 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. int pthread_cond_wait(pthread_cond_t*cond, pthread_mutex_t*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. Sistemas operativos: una visión aplicada 104 J. Carretero, F. García, P. de Miguel, F. Pérez

Colas de mensajes mqd_t mq_open(char *name, int flag, mode_t mode, mq_attr *attr); Crea una cola de mensajes con nombre y atributos attr: Número máximo de mensajes. Tamaño máximo del mensaje. Bloqueante, No bloqueante. int mq_close (mqd_t mqdes); Cierra una cola de mensajes. int mq_unlink(char *name); Borra una cola de mensajes. Sistemas operativos: una visión aplicada 105 J. Carretero, F. García, P. de Miguel, F. Pérez

Colas de mensajes (II) int mq_send(mqd_t mqdes, char *msg, size_t len, int prio); Envía el mensaje msg de longitud len a la cola de mensajes mqdes con prioridad prio; Si la cola está llena el envío puede ser bloqueante o no. 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. Sistemas operativos: una visión aplicada 106 J. Carretero, F. García, P. de Miguel, F. Pérez