Download - Cs Posix Ssoo2
-
7/23/2019 Cs Posix Ssoo2
1/79
Comunicacin ysincronizacin entre procesos
Mara de los Santos PrezHernndez
-
7/23/2019 Cs Posix Ssoo2
2/79
ndice Procesos concurrentes. El problema de la seccin crtica. Problemas clsicos de comunicacin y
sincronizacin. Mecanismos de comunicacin y
sincronizacin. Interbloqueos.
-
7/23/2019 Cs Posix Ssoo2
3/79
Referencias bibliogrficas Sistemas Operativos: una visin aplicada Jess Carretero et al.
McGraw Hill, 2001 Sistemas Operativos Willian Stalling Willian Stalling Prentice Hall, 1997
Operating System Concepts A. Silberschatz, P. Galvin Addison-Wesley, 1998
-
7/23/2019 Cs Posix Ssoo2
4/79
Procesos concurrentes (I) Modelos
Multiprogramacin en un nico procesador Multiprocesador Multicomputador (proceso distribuido)
Razones Compartir recursos fsicos Compartir recursos lgicos Acelerar los clculos Modularidad Comodidad
-
7/23/2019 Cs Posix Ssoo2
5/79
Procesos concurrentes (II) Tipos de procesos
Independientes
Cooperantes Interaccin entre procesos
Compiten por recursos Comparten recursos
-
7/23/2019 Cs Posix Ssoo2
6/79
ro ema e a n eracc nentre procesos (procesos
ligeros) Calcula la suma de los N primeros
nmeros utilizando procesosligeros.
int suma_total = 0; void suma_parcial(int ni, int nf) { int j = 0; int suma_parcial = 0;
for (j = ni; j
-
7/23/2019 Cs Posix Ssoo2
7/79
Ejemplo con seccin crtica
(procesos ligeros) void suma_parcial(int ni, int nf) { int j = 0; int suma_parcial = 0;
for (j = ni; j
-
7/23/2019 Cs Posix Ssoo2
8/79
Problema de la interaccin
entre procesos 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 procesosejecutanconcurrentement
e este cdigo sepuede perderalgn ingreso.
Solucin:secciones
crticas
-
7/23/2019 Cs Posix Ssoo2
9/79
Ejemplo con seccin crtica void ingresar(char *cuenta, int cantidad) { int saldo, fd;
fd = open(cuenta, O_RDWR);
Entrada en la seccin crticaread(fd, &saldo, sizeof(int));
saldo = saldo + cantidad; lseek(fd, 0, SEEK_SET); write(fd, &saldo, sizeof(int)); Salida de la seccin crtica
close(fd); return; }
Requisitos paraofrecerseccionescrticas:
Exclusin mutua Progreso
Espera limitada
-
7/23/2019 Cs Posix Ssoo2
10/79
Mecanismos de comunicacin Ficheros Pipes FIFOS Variables en memoria compartida Paso de mensajes
Sockets
-
7/23/2019 Cs Posix Ssoo2
11/79
Mecanismos de
Sincronizacin Construcciones de los lenguajes concurrentes
(procesos ligeros) Servicios del sistema operativo:
Seales (asincronismo) Pipes FIFOS Semforos Mutex y variables condicionales Paso de mensajes
Las operaciones de sincronizacin deben seratmicas
-
7/23/2019 Cs Posix Ssoo2
12/79
arac er s cas e osmecanismos de
comunicacin Identificacin
Mecanismos de
nombrado Sin nombre Con nombre local Con nombre de
red
Identificador interno Identificadorpropio
Descriptor defichero
Flujo de datos Unidireccional
Bidireccional Buffering
Sin buffering Con buffering
Sincronizacin Sncrono(bloqueante)
Asncrono (nobloqueante)
-
7/23/2019 Cs Posix Ssoo2
13/79
ro emas c s cos ecomunicacin y
sincronizacin
P r o c e s oP r o d u c t o r
P r o c e s oC o n s u m i d o r
M e c a n i s m o d ec o m u n i c a c i n
F l u j o d ed a t o s
E s c r i t o r 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
R e c u r s o
-
7/23/2019 Cs Posix Ssoo2
14/79
Problemas clsicos decomunicacin y sincronizacin
(II)
Computad
ora
Computad
ora
Procesoclien
te
S.O.
Peticin
Respuesta
Procesoservid
or
-
7/23/2019 Cs Posix Ssoo2
15/79
Pipes Mecanismo de comunicacin y
sincronizacin sin nombre Slo puede utilizarse entre los
procesos hijos del proceso quecre el pipe int pipe(int fildes[2]);
Identificacin: dos descriptoresde fichero
Flujo de datos: unidireccional Con buffering
read(fildes[0],buffer,n) Pipe vaco se bloquea
el lector Pipe conp bytes
Si p n devuelve n Si p n devuelve p
Si pipe vaco y no hayescritores devuelve 0
write(fildes[1], buffer,n)
Pipe lleno se bloqueael escritor
Si no hay lectores serecibe la sealSIGPIPE
Lecturas y escrituras
atmicas (cuidado contamaos randes)
-
7/23/2019 Cs Posix Ssoo2
16/79
Secciones crticas con pipes void main(void) { int fildes[2]; /* pipe sincronizacin
*/ char c; /* carcter sincronizacin */
pipe(fildes); write(fildes[1], &c, 1); /* necesario para entrar en la seccion crtica la primera vez */
if (fork() == 0) { /* proceso hijo */
for(;;) { read(fildes[0], &c, 1); /* entrada seccin crtica */ /* seccin crtica */ write(fildes[1], &c, 1); /* salida seccion crtica */
} }
else /* proceso padre */
{
for(;;)
{
read(fildes[0], &c, 1);/* entrada seccin
crtica*/
/* seccin crtica */
write(fildes[1], &c, 1);/* salida seccin crtica
*/
}
} }
-
7/23/2019 Cs Posix Ssoo2
17/79
Productor-consumidor conpipes
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) /* productor */ { for(;;)
{ /* producir dato_p */ write(fildes[1], dato_p, 4*sizeof(int)); } }
else /* consumidor */
{
for(;;)
{
read(fildes[0],&dato_c,
sizeof(int));
/* consumir dato */
}
}
}
Proceso
hijo
Proceso
padre
pipe
SO
write read
Flujo dedatos
-
7/23/2019 Cs Posix Ssoo2
18/79
Ejecucin de mandatos conpipes
/* programa que ejecuta el mandato ls | wc*/
void main(void) {
int fd[2]; pid_t pid;
if (pipe(fd) < 0) { perror(``pipe''); exit(1);
}
pid = fork(); switch(pid) {
case -1: /* error */ perror(``fork''); exit(1); case 0: /* proceso hijo ejecuta ls
*/
close(fd[0]); /* cierra el pipe delectura */
close(STDOUT_FILENO); /* cierra lasalida 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''); } }
-
7/23/2019 Cs Posix Ssoo2
19/79
Ejecucin de mandatos conpipes (II)
P r o c e s o
S T D I NS T D O U T
p i p e ( f d )
f o r k ( )
P r o c e s o
S T D I NS T D O U T
f d [ 0 ]f d [ 1 ]
p i p e
r e d i r e c c i n
P r o c e s o h i j o
S T D I NS T D O U Tf d [ 0 ]f d [ 1 ]
P r o c e s o
S T D I NS T D O U Tf d [ 0 ]f d [ 1 ]
p i p e
e x e c
P r o c e s o h i jo
S T D I N
S T D O U T
P r o c e s o
S T D I N
S T D O U Tp i p e
P r o c e s o h i jo
S T D I N
S T D O U T
P r o c e s o
l s w c
S T D I N
S T D O U Tp i p e
-
7/23/2019 Cs Posix Ssoo2
20/79
FIFOS
Igual que los pipes Mecanismo de comunicacin y
sincronizacin con nombre Misma mquina
Servicios
mkfifo(char *name,mode_t mode); Crea un FIFO con nombre
name
open(char *name, intflag);
Abre un FIFO (paralectura, escritura o
ambas) Bloquea hasta quehaya algn procesoen el otro extremo
Lectura y escritura medianteread() y write()
Igual semntica que lospipes Cierre de un FIFO mediante
close() Borrado de un FIFO mediante
unlink()
-
7/23/2019 Cs Posix Ssoo2
21/79
Semforos Mecanismo de sincronizacin Misma mquina Objeto con un valor entero
Dos operaciones atmicas s_espera(s) { s = s - 1; if (s < 0) Bloquear al proceso }
s_abre(s) { s = s + 1; if (s
-
7/23/2019 Cs Posix Ssoo2
22/79
Semforos POSIX sem_init(sem_t *sem, int shared, int val);
Inicializa un semforo sin nombre int sem_destroy(sem_t *sem);
Destruye un semforo sin nombre sem_t *sem_open(char *name,int flag,mode_t mode,int val);
Abre (crea) un semforo con nombre. int sem_close(sem_t *sem);
Cierra un semforo con nombre. int sem_unlink(char *name);
Borra un semforo con nombre. int sem_wait(sem_t *sem);
Realiza la operacin s_espera sobre un semforo. int sem_post(sem_t *sem);
Realiza la operacin s_abre sobre un semforo.
P d t id
-
7/23/2019 Cs Posix Ssoo2
23/79
Productor-consumidor consemforos (buffer acotado ycircular)
C o n s u m i d o r
P r o d u c t o r
-
7/23/2019 Cs Posix Ssoo2
24/79
Productor-consumidor consemforos (II)
#define MAX_BUFFER 1024 #define DATOS_A_PRODUCIR 100000 sem_t elementos; /* elementos buffer
*/ sem_t huecos; /* huecos buffer */ sem_t mutex; /* controla excl.mutua
*/
int buffer[MAX_BUFFER];/*buffercomn*/
void main(void)
{ pthread_t th1, th2; /* id.
threads*/ /* inicializar los semaforos */ sem_init(&elementos, 0, 0); sem_init(&huecos, 0, MAX_BUFFER); sem_init(&mutex, 0, 1);
/* crear los procesosligeros */
pthread_create(&th1,NULL, Productor, NULL);
pthread_create(&th2,NULL, Consumidor, NULL);
/* esperar sufinalizacion */
pthread_join(th1, NULL); pthread_join(th2, NULL);
sem_destroy(&huecos); sem_destroy(&elementos); sem_destroy(&mutex);
exit(0); }
-
7/23/2019 Cs Posix Ssoo2
25/79
Productor-consumidor consemforos (III) void Productor(void) /* cdigo del productor */ { int pos = 0; /* posicin 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 */ sem_wait(&mutex); /* entra en la seccin crtica */ buffer[pos] = dato; pos = (pos + 1) % MAX_BUFFER; sem_post(&mutex); /* deja la seccin crtica */ sem_post(&elementos); /* un elemento ms */ } pthread_exit(0); }
-
7/23/2019 Cs Posix Ssoo2
26/79
Productor-consumidor consemforos (IV) void Consumidor(void) /* cdigo del Consumidor */ { int pos = 0; int dato;
int i;
for(i=0; i < DATOS_A_PRODUCIR; i++ ) { sem_wait(&elementos); /* un elemento menos */ sem_wait(&mutex); /* entra en la seccin crtica */ dato = buffer[pos]; pos = (pos + 1) % MAX_BUFFER; sem_post(&mutex); /* deja la seccin crtica */ sem_post(&huecos); /* un hueco ms */ /* consumir dato */ } pthread_exit(0); }
-
7/23/2019 Cs Posix Ssoo2
27/79
Lectores-escritores consemforos
int dato = 5; /* recurso */ int n_lectores = 0;/* num. Lectores
*/ sem_t sem_lec; /* acceso n_lectores
*/ sem_t mutex; /* 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);
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); }
-
7/23/2019 Cs Posix Ssoo2
28/79
Lectores-escritores consemforos (II) void Lector(void) /* cdigo 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);
}
-
7/23/2019 Cs Posix Ssoo2
29/79
Lectores-escritores consemforos (III)
void Escritor(void) /* cdigo del escritor */
{
sem_wait(&mutex);
dato = dato + 2; /* modificar el recurso */
sem_post(&mutex);
pthread_exit(0);
}
-
7/23/2019 Cs Posix Ssoo2
30/79
Objetos de memoriacompartida
Permiten crear unsegmento dememoria
compartido entreprocesos de lamisma mquina.
Declaracin
independiente devariables
D a t o s
T e x t o
P r o c e s o A P r o c e s o B
P i l a
T e x t o
D a t o s
P i l aS e g m e n t od e m e m o r i ac o m p a r t i d a
v a r 1
* v a r 1 = 2
2
v a r 2
-
7/23/2019 Cs Posix Ssoo2
31/79
Servicios int shm_open(char *name, int oflag, mode_t mode);
Crea un objeto de memoria a compartir entre procesos int shm_open (char *name, int oflag);
Slo apertura int close(int fd);
Cierre. El objeto persiste hasta que es cerrado por el ltimoproceso.
int shm_unlink(const char *name); Borra una zona de memoria compartida.
void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off);
Establece una proyeccin entre el espacio de direcciones deun proceso y un descriptor de fichero u objeto dememoria compartida.
-
7/23/2019 Cs Posix Ssoo2
32/79
Servicios (II) len especifica el nmero de bytes a proyectar. protel tipo de acceso (lectura, escritura o
ejecucin). PROT_READ, PROT_WRITE, PROT_EXEC o
PROT_NONE. flags especifica informacin sobre el manejo
de los datos proyectados (compartidos,privado, etc.).
MAP_SHARED, MAP_PRIVATE, ... fildes representa el descriptor de fichero del
fichero o descriptor del objeto de memoria aproyectar.
offdesplazamiento dentro del fichero a partirde cual se realiza la proyeccin.
void munmap(void *addr, size_t len); Desproyecta parte del espacio de direcciones de
un proceso comenzando en la direccin addr.El tamao de la regin a desproyectar es len.
ro uc or consum or con
-
7/23/2019 Cs Posix Ssoo2
33/79
ro uc or-consum or conobjetos de memoriacompartida
Productor: Crea la zona de memoria compartida
(shm_open) Le asigna espacio (ftruncate)
int ftruncate (int fd, size_t len); Proyecta la zona de memoria compartida
en su espacio
de direcciones (mmap) Utiliza la zona de memoria compartida Desproyecta la zona de memoria
compartida
Cierra y borra el objeto de memoriacompartida
Productor consumidor con
-
7/23/2019 Cs Posix Ssoo2
34/79
Productor-consumidor conobjetos de memoria compartida(II)
Consumidor: Debe esperar a que la zona de memoria
compartida este creada Abre la zona de memoria compartida
(shm_open) Proyecta la zona de memoria compartida
en su espacio de direcciones (mmap) Utiliza la zona de memoria compartida Cierra el objeto de memoria compartida
-
7/23/2019 Cs Posix Ssoo2
35/79
Cdigo del productor #define MAX_BUFFER 1024 /* tamao del buffer */ #define DATOS_A_PRODUCIR 100000 /* datos a producir */ sem_t *elementos; /* elementos en el buffer */ sem_t *huecos; /* huecos en el buffer */
sem_t *mutex; /* acceso al buffer */
void main(int argc, char *argv[]) { int shd; int *buffer; /* buffer comn */
/* el productor crea el segmento de memoria compartida */ shd = shm_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 */
-
7/23/2019 Cs Posix Ssoo2
36/79
Cdigo del productor (II)
buffer = (int *) mmap(NULL, MAX_BUFFER * sizeof(int), PROT_WRITE, MAP_SHARED, shd, 0);
/* El productor crea los semforos */
elementos = sem_open("ELEMENTOS", O_CREAT, 0700, 0); huecos = sem_open("HUECOS", O_CREAT, 0700, MAX_BUFFER); mutex = sem_open("MUTEX", O_CREAT, 0700, 1); Productor(buffer);
/* desproyectar el buffer compartido */
munmap(buffer, MAX_BUFFER * sizeof(int)); close(shd); /* cerrar el objeto de memoria compartida */ shm_unlink("BUFFER"); /* borrar el objeto de memoria */
sem_close(elementos); sem_close(huecos); sem_close(mutex); sem_unlink("ELEMENTOS"); sem_unlink("HUECOS");
sem_unlink("MUTEX"); }
-
7/23/2019 Cs Posix Ssoo2
37/79
Cdigo del productor (III) void Productor(int *buffer){ /* cdigo del productor */ int pos = 0; /* posicin 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 */ sem_wait(mutex);
buffer[pos] = dato; pos = (pos + 1) % MAX_BUFFER; sem_post(mutex); sem_post(elementos); /* un elemento ms */ } return;
}
-
7/23/2019 Cs Posix Ssoo2
38/79
Cdigo del consumidor #define MAX_BUFFER 1024 /* tamao del buffer */ #define DATOS_A_PRODUCIR 100000 /* datos a producir */
sem_t *elementos; /* elementos en el buffer */
sem_t *huecos; /* huecos en el buffer */ sem_t *mutex; /* acceso al buffer */ void main(int argc, char *argv[]) { int shd; int *buffer; /* buffer comn */
/* el consumidor abre el segmento de memoria compartida */ shd = shm_open("BUFFER", O_RDONLY);
/* proyectar el objeto de memoria compartida en el espacio de direcciones del productor */
-
7/23/2019 Cs Posix Ssoo2
39/79
Cdigo del consumidor (II) buffer = (int *) mmap(NULL, MAX_BUFFER * sizeof(int), PROT_READ, MAP_SHARED, shd, 0);
/* El consumidor abre los semforos */ elementos = sem_open("ELEMENTOS", 0); huecos = sem_open("HUECOS", 0); mutex = sem_open("MUTEX", 0); Consumidor(buffer);
/* desproyectar el buffer compartido */ munmap(buffer, MAX_BUFFER * sizeof(int)); close(shd); /* cerrar el objeto de memoria compartida */
/* cerrar los semforos */ sem_close(elementos); sem_close(huecos); sem_close(mutex); }
-
7/23/2019 Cs Posix Ssoo2
40/79
Cdigo del consumidor (III) void Consumidor(char *buffer) /*cdigo del Consumidor*/ { int pos = 0; int i, dato;
for(i=0; i < DATOS_A_PRODUCIR; i++ ) { sem_wait(elementos); /* un elemento menos */ sem_wait(mutex); dato = buffer[pos]; pos = (pos + 1) % MAX_BUFFER; sem_post(mutex); sem_post(huecos); /* un hueco mas */ printf("Consume %d \n", dato); /* consumir dato */ } return;
}
-
7/23/2019 Cs Posix Ssoo2
41/79
Mutex y variablescondicionales
Un mutex es un mecanismo desincronizacin indicado para procesosligeros.
Es un semforo binario con dosoperaciones atmicas: lock(m): Intenta bloquear el mutex; si el
mutex ya est bloqueado el proceso sesuspende. unlock(m): Desbloquea el mutex; si
existen procesos bloqueados en elmutex se desbloquea a uno.
-
7/23/2019 Cs Posix Ssoo2
42/79
Secciones crticas con mutex lock(m); /* entrada en la seccin crtica */
/* seccin crtica */
unlock(s); /* salida de la seccin crtica */
La operacin unlockdebe realizarla el proceso ligero queejecut lock P r o c e s o
l i g e r o A
l o c k m u t e x
S e c c i nc r t i c a
P r o c e s ol i g e r o B
l o c k m u t e x
u n l o c k m u t e x o b t ie 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 l i 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
-
7/23/2019 Cs Posix Ssoo2
43/79
Variables condicionales Variables de sincronizacin
asociadas a un mutex Conveniente ejecutarlas
entre locky unlock. Dos operaciones atmicas:
wait: Bloquea alproceso ligero que laejecuta y le expulsadel mutex
signal: Desbloquea a
uno o variosprocesossuspendidos en lavariable condicional.El proceso que sedespierta compitede nuevo por el
mutex
P r o c e s ol i g e r o B
P r o c e s ol i g e r o A
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
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
l o c kl o c k
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
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
s i g n a l
-
7/23/2019 Cs Posix Ssoo2
44/79
Uso de mutex y variablescondicionales
Proceso ligero A:
lock(mutex); /* acceso al
recurso */ /* codigo de la seccin crtica */ while (condicion == FALSE)
wait(condition, mutex); /* resto de la seccin
crtica */ unlock(mutex);
Proceso ligero B
lock(mutex); /* acceso alrecurso
*/ /* cdigo de la seccin
crtica */ /* se modifica la
condiccin y sta sehace TRUE */
condicion = true; signal(condition, mutex); unlock(mutex);
Importante utilizar
while
-
7/23/2019 Cs Posix Ssoo2
45/79
Servicios 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 elmutexse 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. int pthread_cond_destroy(pthread_cond_t *cond);
Destruye una variable condicional.
-
7/23/2019 Cs Posix Ssoo2
46/79
Servicios (II) int pthread_cond_signal(pthread_cond_t *cond);
Se reactivan uno o ms de los procesos ligeros que estnsuspendidos en la variable condicional cond.
No tiene efecto si no hay ningn proceso ligero esperando
(diferente a los semforos). int pthread_cond_broadcast(pthread_cond_t *cond);
Todos los threads suspendidos en la variable condicionalcond se reactivan.
No tiene efecto si no hay ningn proceso ligero esperando. int pthread_cond_wait(pthread_cond_t *cond,
pthread_mutex_t *mutex); Suspende al proceso ligero hasta que otro proceso sealiza la
variable condicional cond. Automticamente se libera el mutex. Cuando se despierta el
proceso ligero vuelve a competir por el mutex.
-
7/23/2019 Cs Posix Ssoo2
47/79
Productor-consumidor conmutex
#define MAX_BUFFER 1024 /* tamao 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; /* llenado del buffer */ pthread_cond_t no_vacio; /* vaciado del buffer */ int n_elementos; /* elementos en el buffer */ int buffer[MAX_BUFFER]; /* buffer comn */
main(int argc, char *argv[]) { pthread_t th1, th2;
pthread_mutex_init(&mutex, NULL);
-
7/23/2019 Cs Posix Ssoo2
48/79
Productor-consumidor conmutex (II)
pthread_cond_init(&no_lleno, NULL);
pthread_cond_init(&no_vacio, NULL);
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); }
-
7/23/2019 Cs Posix Ssoo2
49/79
Productor-consumidor conmutex (III)
void Productor(void) { /* cdigo 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);/* bloqueo*/
buffer[pos] = dato; pos = (pos + 1) % MAX_BUFFER; n_elementos ++; pthread_cond_signal(&no_vacio);/* buffer no vaco
*/ pthread_mutex_unlock(&mutex); }
-
7/23/2019 Cs Posix Ssoo2
50/79
Productor-consumidor conmutex (IV)
void Consumidor(void) { /* cdigo del consumidor */ 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 vaco */ pthread_cond_wait(&no_vacio, &mutex);/* bloqueo
*/ 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);
-
7/23/2019 Cs Posix Ssoo2
51/79
Lectores-escritores conmutex
int dato = 5; /* recurso */
int n_lectores = 0; /* numero de lectores */
pthread_mutex_t mutex; /* control del acceso a dato*/
pthread_mutex_t mutex_lectores; /* control de n_lectores */
main(int argc, char *argv[])
{
pthread_t th1, th2, th3, th4;
pthread_mutex_init(&mutex, NULL);
pthread_mutex_init(&mutex_lectores, NULL);
-
7/23/2019 Cs Posix Ssoo2
52/79
Lectores-escritores conmutex (II)
pthread_create(&th1, NULL, Lector, NULL); pthread_create(&th2, NULL, Escritor, NULL); pthread_create(&th3, NULL, Lector, NULL); pthread_create(&th4, NULL, Escritor, NULL);
pthread_join(th1, NULL); pthread_join(th2, NULL); pthread_join(th3, NULL); pthread_join(th4, NULL);
pthread_mutex_destroy(&mutex); pthread_mutex_destroy(&mutex_lectores);
exit(0); }
-
7/23/2019 Cs Posix Ssoo2
53/79
Lectores-escritores conmutex (III)
void Lector(void) { /* cdigo 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);
}
-
7/23/2019 Cs Posix Ssoo2
54/79
Lectores-escritores conmutex (IV) void Escritor(void) /* cdigo del escritor
*/
{
pthread_mutex_lock(&mutex);
dato = dato + 2; /* modificar el recurso*/
pthread_mutex_unlock(&mutex);
pthread_exit(0);
}
-
7/23/2019 Cs Posix Ssoo2
55/79
Paso de mensajes
Permite resolver: Exclusin mutua Sincronizar entre un
proceso que recibe un
mensaje y otro que loenva Comunicacin de datos
entre espacios dememoria diferentes(mismo computador,
diferentescomputadores) Primitivas bsicas:
send(destino, mensaje):enva un mensaje alproceso destino
receive(origen, mensaje):recibe un mensaje del
Mltiples soluciones Paso de mensajes en POSIX
(colas de mensajes): Misma mquina
(uniprocesador,multiprocesador omulticomputador)
Mecanismo denombrado: connombre local
Identificacin:identificador especial Buffering: S Unidireccional Sincronizacin:
bloqueante y no
bloqueante
-
7/23/2019 Cs Posix Ssoo2
56/79
Colas de mensajes POSIX
mqd_t mq_open(char *name, int flag, mode_tmode, mq_attr *attr);
Crea una cola de mensajes con nombre y
atributos attr: Nmero mximo de mensajes. Tamao mximo 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.
-
7/23/2019 Cs Posix Ssoo2
57/79
Colas de mensajes POSIX (II)
int mq_send(mqd_t mqdes, char *msg, size_t len, int prio);
Enva el mensaje msg de longitud len a la cola demensajes mqdes con prioridadprio;
Si la cola est llena el envo 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 demensajes mqdes (el de mayor prioridad). Almacena laprioridad del mensaje en el parmetroprio;
Recepcin bloqueante o no.
-
7/23/2019 Cs Posix Ssoo2
58/79
Secciones crticas con colasde mensajes
void main(void){ mqd_t mutex; /* cola de mensajes para sincronizar
acceso a la seccin crtica */ struct mq_attr attr; /*atributos cola de mensajes*/
char c; /* carcter para sincronizar */
attr.mq_maxmsg = 1; /* nmero mximo mensajes */ attr.mq_msgsize = 1; /* tamao mensaje */ mutex = mq_open(``MUTEX'', O_CREAT|O_RDWR, 0777,
&attr);
mq_send(mutex, &c, 1, 0); /* entrar en la seccin crtica la primera vez */
-
7/23/2019 Cs Posix Ssoo2
59/79
Secciones crticas con colasde mensajes (II)
if (fork() == 0) { /* proceso hijo */ for(;;){ mq_receive(mutex, &c, 1, NULL);/*entrada sec. crtica */ /* seccin crtica */ mq_send(mutex, &c, 1, 0); /* salida sec. critica */ } }else { /* proceso padre */ for(;;){ mq_receive(mutex, &c, 1, NULL);/*entrada sec. crtica */ /* seccin crtica */ mq_send(mutex, &c, 1, 0); /* salida sec. critica */ } } }
-
7/23/2019 Cs Posix Ssoo2
60/79
Productor-consumidor concolas de mensajes
#define MAX_BUFFER 1024 /* tamao del buffer */ #define DATOS_A_PRODUCIR 100000 /*datos a producir*/
mqd_t almacen; /* cola de mensaje para almacenamiento
de datos */ 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);
-
7/23/2019 Cs Posix Ssoo2
61/79
Productor-consumidor concolas de mensajes (II) if (almacen == -1) { perror("mq_open"); exit(1);
}
if (fork() == 0) /* proceso hijo */ Productor(); else /* proceso padre */ Consumidor();
exit(0);
}
-
7/23/2019 Cs Posix Ssoo2
62/79
Productor-consumidor concolas de mensajes (III)
void Productor(void) { int dato; int i;
for(i=0; i < DATOS_A_PRODUCIR;
i++ ){ /* producir dato */ dato = i; printf("Produce
%d \n", dato); mq_send(almacen,
&dato, sizeof(int),0);
} return;
}
void Consumidor(void){ int dato; int i;
for(i=0; i cola,O_RDWR);
pthread_mutex_lock(mutex); n_lectores ++; peticion.tipo = OK;
mq_send(cola_local, peticion,sizeof(peticion), 0);
mq_receive(cola_local, peticion,sizeof(peticion), NULL);
n_lectores --; if (n_lectores == 0)
pthread_cond_signal(&no_lectores)
; pthread mutex unlock(mutex);
void do_write(struct peticion_t*pet) {
mqd_t cola_local; struct peticion_t peticion;
/* abre la cola del proceso querealiza la peticion */
cola_local = mq_open(pet->cola,O_RDWR);
pthread_mutex_lock(mutex); while (n_lectores > 0)
pthread_cond_wait(&no_lectores,
&mutex);
peticion.tipo = OK; mq_send(cola_local, peticion,
sizeof(peticion), 0); mq_receive(cola_local, peticion,
sizeof(peticion), NULL); pthread_mutex_unlock(mutex); }
S id l i h d
-
7/23/2019 Cs Posix Ssoo2
67/79
Servidor multithread concolas de mensajes
P r o c e s o c l i e n t e
C o l a d e lc 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 lc l i e n t e
C o l a d e ls e r v i d o r
P r o c e s o s e r v i d o r
p e t i c i n
p e t i c i n
r e s p u e s t a
r e s p u e s t a
C r e a c i n d e lt h r e a d
C r e a c i n d e l
t h r e a d
T h r e a d q u es i r v e l a p e t i c i n
T h r e a d q u es i r v e l a p e t i c i n
S id ltith d
-
7/23/2019 Cs Posix Ssoo2
68/79
Servidor multithread concolas de mensajes (II)
/* estructura de un mensaje */ struct mensaje { char buffer[1024]; /* datos a enviar */ char cliente[256]; /* cola del cliente */ };
/* mutex y var. condicionales proteccin de 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 */ q_attr.mq_maxmsg = 20; q_attr.mq_msgsize = sizeof(struct mensaje);
S id ltith d
-
7/23/2019 Cs Posix Ssoo2
69/79
Servidor multithread concolas de mensajes (III) q_servidor = mq_open("SERVIDOR", O_CREAT|O_RDONLY, 0700,
&q_attr); pthread_mutex_init(&mutex_mensaje, NULL); pthread_cond_init(&cond, NULL); pthread_attr_init(&t_attr); pthread_attr_setscope(&t_attr,PTHREAD_SCOPE_SYSTEM); pthread_attr_setdetachstate(&t_attr, PTHREAD_CREATE_DETACHED); while (TRUE) { mq_receive(q_servidor, &mess, sizeof(struct mensaje), NULL);
pthread_create(&thid, &t_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); } }
S id ltith d
-
7/23/2019 Cs Posix Ssoo2
70/79
Servidor multithread concolas de mensajes (IV)
void tratar_mensaje(struct mensaje *mes){ struct mensaje mensaje_local; struct mqd_t q_cliente; /* cola del cliente */ struct mensaje respuesta; /* 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*/ mensaje_no_copiado = FALSE; pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex_mensaje);
/* ejecutar la peticin del cliente y preparar respuesta */
/* responder al cliente a su cola */ q_cliente = mq_open(mensaje_local.cliente, O_WRONLY); mqsend(q_cliente, (char *) &respuesta, sizeof(respuesta), 0); mq_close(q_cliente); pthread_exit(0); }
-
7/23/2019 Cs Posix Ssoo2
71/79
Ejemplo de cdigo cliente struct mensaje {/* estructura mensaje
*/ char buffer[1024]; /* datos envo
*/ char cliente[256]; /* cola cliente
*/
};
void main(void) { mqd_t q_servidor; /* cola servidor
*/ mqd_t q_cliente; /* cola cliente
*/ struct mq_attr attr; /* atr. cola
*/ struct mensaje peticion; /* peticion
al servidor*/
struct mensaje respuesta; /*respuesta delservidor */
q_cliente = mq_open("CLIENTE",O_CREAT|O_RDONLY, 0700,
0); q_servidor =
mq_open("SERVIDOR",O_WRONLY);
/* preparar peticion */ mq_send(q_servidor, &peticion,
sizeof(struct mensaje),0);
/* esperar respuesta */ mq_receive(q_cliente,
&respuesta,sizeof(struct mensaje), NULL);
mq_close(q_servidor); mq_close(q_cliente); mq_unlink("CLIENTE");
exit(0); }
-
7/23/2019 Cs Posix Ssoo2
72/79
Sockets
Permiten comunicar: Procesos del mismo computador Procesos conectados a travs de una red
Tipos de direcciones: Direcciones locales: dominio UNIX Direcciones de red (TCP/IP)
Direccin de red (direccin IP) Puerto
-
7/23/2019 Cs Posix Ssoo2
73/79
Sockets (II)
Red deinterconexin
-
7/23/2019 Cs Posix Ssoo2
74/79
Resumen Pipes:
Mecanismo decomunicacin ysincronizacin
Mecanismo denombrado: sinnombre
Identificacin: descriptorde fichero
Flujo de datos:unidireccional
Buffering: S Sincronizacin:
Si pipe vaco read() se bloquea
Si pipe lleno write() sebloquea
FIFOS: Mecanismo de
comunicacin ysincronizacin
Mecanismo denombrado: connombre local
Identificacin:descriptor de fichero
Flujo de datos:unidireccional
Buffering: S Sincronizacin:
Si FIFO vaco read() sebloquea
Si FIFO lleno write() se
-
7/23/2019 Cs Posix Ssoo2
75/79
Resumen (II) Semforos POSIX:
Mecanismo desincronizacin
Mecanismo de
nombrado: sinnombre y connombre local
Identificacin:variable de tiposemforo
Mutex y variablescondicionales: Mecanismo de
sincronizacinadecuado paraprocesos ligeros
Mecanismo denombrado: sin
Colas de mensajesPOSIX:
Mecanismo decomunicacin y
sincronizacin Mecanismo de
nombrado: connombre local
Identificacin:identificadorespecial
Buffering: S Unidireccional Sincronizacin:
bloqueante y no
bloqueante
-
7/23/2019 Cs Posix Ssoo2
76/79
Resumen (III)
Objetos de memoria compartida: Mecanismo de comunicacin Mecanismo de nombrado: con nombre local
Identificacin: identificador especial Sockets:
Mecanismo de comunicacin y sincronizacin Mecanismo de nombrado: con nombre de red
Identificacin: descriptor de fichero Buffering: S Sincronizacin: bloqueante y no bloqueante
-
7/23/2019 Cs Posix Ssoo2
77/79
Interbloqueos Bloqueo permanente de un
conjunto de procesos quecompiten por los recursosdel sistema o se comunican
entre s. Ejemplo: Si S y Q con
semforos con valor inicial P0 P1 s_espera(S)
s_espera(Q)
s_espera(Q)s_espera(S)
. .
s_abre(S)s_abre(Q)
s_abre(Q)s_abre(S)
Ejemplo: Si C1 y C2 son doscolas de mensajes
P0 P1
receive(C1, M)receive(C2, N)
. .
send(C2, M) send(C1,N)
Condiciones del
interbloqueo: Exclusin mutua Retencin y espera No apropiacin Espera circular
-
7/23/2019 Cs Posix Ssoo2
78/79
Ejemplo
Ejemplo: Si P y Q son semforos con valorinicial 1
A B
s_espera(P) s_espera(Q) s_espera(Q) s_espera(P)
Interbloqueo
Q
P
BA
Mtodos para tratar con los
-
7/23/2019 Cs Posix Ssoo2
79/79
Mtodos para tratar con losinterbloqueos
Ignorarlos UNIX
Solucionarlos: Mtodos para prevenir los interbloqueos Mtodos para evitar los interbloqueos Mtodos para detectar los interbloqueos