8x1 - Escuela Superior de Informática - Universidad de Castilla

Anuncio
Programación Concurrente y
Tiempo Real
Tema 2. Semáforos y Memoria Compartida
Escuela Superior de Informática
Universidad de Castilla-La Mancha
Curso 2011/2012
Grado en Ing. Informática
Conceptos | Implementación | Problemas | Patrones
Tema 2. Semáforos y Memoria Compartida
Semáforos. ¿Qué, cómo y por qué?
1. Conceptos básicos [Silber 6.5]
p1: proceso
p1: proceso
1
2. Implementación
[Rochk 7.10, 7.14] [Robb 8.3]
3. Problemas clásicos de sincronización
wait
[p1 bloqueado]
sem (1)
[Downey 4, 5]
sem (0)
2
wa it
[decremento]
4. Patrones de sincronización básicos
p1: proceso
[p1 desbloqueado]
sem (-1)
sem (0)
4
signa l
[incremento]
p2: proceso
[Downey 3]
5
3
cr eación
[inicialización]
p2: proceso
* Downey, A.B., The Little Book of Semaphores
Curso 2011/2012
Grado en Ing. Informática
Curso 2011/2012
Conceptos | Implementación | Problemas | Patrones
Ejemplo de sincronización
P2
P3
P1
P2
P3
r1
s1
t1
r1
s1
t1
r2
S(a)
t2
W(a)
s2
S(c)
r3
W(c)
t3
S(b)
s3
S(d)
r4
W(b)
t4
r5
W(d)
t5
r2
r3
s2
b
s3
c
d
t2
t3
r4
s4
t4
r5
s5
t5
Conceptos | Implementación | Problemas | Patrones
Semáforos nombrados en POSIX
P1
a
Trp 3 de 24
s4
Manipulación de semáforos
#include <semaphore.h>
// Devuelve un puntero al semáforo o SEM FAILED.
sem_t *sem_open(
const char *name, // Nombre del semáforo.
int oflag,
// Flags.
mode_t mode,
// Permisos.
unsigned int value // Valor inicial.
);
int sem_close (sem_t *sem);
int sem_unlink (const char *name);
int sem_wait (sem_t *sem);
int sem_post (sem_t *sem);
s5
Curso 2011/2012
Trp 4 de 24
Curso 2011/2012
Trp 5 de 24
Conceptos | Implementación | Problemas | Patrones
Semáforos nombrados en POSIX
Conceptos | Implementación | Problemas | Patrones
Semáforos nombrados en POSIX
TAD semáforo
crear_sem
#ifndef __SEMAFOROI_H__
#define __SEMAFOROI_H__
#include <semaforoI.h>
sem_t *crear_sem (const char *name,
unsigned int valor) {
sem_t *sem;
#include <semaphore.h>
// Crea un semáforo POSIX.
sem_t *crear_sem (const char *name, unsigned int valor);
// Obtener un semáforo POSIX (ya existente).
sem_t *get_sem (const char *name);
// Cierra un semáforo POSIX.
void destruir_sem (const char *name);
// Incrementa el semáforo.
void signal_sem (sem_t *sem);
// Decrementa el semáforo.
void wait_sem (sem_t *sem);
sem = sem_open(name, O_CREAT, 0644, valor);
if (sem == SEM_FAILED) {
fprintf(stderr, "Error al crear el semáforo: %s\n",
strerror(errno));
exit(1);
}
return sem;
}
#endif
Curso 2011/2012
Trp 6 de 24
Curso 2011/2012
Trp 7 de 24
Conceptos | Implementación | Problemas | Patrones
Memoria compartida en POSIX
Conceptos | Implementación | Problemas | Patrones
Memoria compartida en POSIX
Gestión de segmentos de memoria
Mapping
#include <mman.h>
#include <unistd.h>
#include <sys/mman.h>
void *mmap(
void *addr,
size_t length,
int prot,
int flags,
int fd,
off_t offset
);
// Devuelve el descriptor de archivo o -1 si error.
int shm_open(
const char *name, // Nombre del segmento.
int oflag,
// Flags.
mode_t mode
// Permisos.
);
int shm_unlink (const char *name);
int close
(int fd);
int ftruncate (int fd, off_t length);
//
//
//
//
//
//
Dirección de memoria.
Longitud del segmento.
Protección.
Flags.
Descriptor de archivo.
Desplazamiento.
int munmap(
void *addr,
// Dirección de memoria.
size_t length // Longitud del segmento.
);
Curso 2011/2012
Trp 8 de 24
Curso 2011/2012
Trp 9 de 24
Conceptos | Implementación | Problemas | Patrones
Variable entera compartida
Conceptos | Implementación | Problemas | Patrones
Variable entera compartida
TAD Variable
crear_var
#ifndef __VARIABLEI_H__
#define __VARIABLEI_H__
int crear_var (const char *name, int valor) {
int shm_fd;
int *p;
// Crea un objeto de memoria compartida.
// Devuelve el descriptor de archivo.
int crear_var (const char *name, int valor);
// Obtiene el descriptor asociado a la variable.
int obtener_var (const char *name);
// Destruye el objeto de memoria compartida.
void destruir_var (const char *name);
// Modifica el valor del objeto de memoria compartida.
void modificar_var (int shm_fd, int valor);
// Consulta el valor del objeto de memoria compartida.
void consultar_var (int shm_fd, int *valor);
#endif
Curso 2011/2012
Trp 10 de 24
2
// Establecer el tamaño.
if (ftruncate(shm_fd, sizeof(int)) == -1) {
fprintf(stderr, "...", strerror(errno));
exit(1);
}
Curso 2011/2012
Trp 11 de 24
Conceptos | Implementación | Problemas | Patrones
Variable entera compartida
1
// Abre el objeto de memoria compartida.
shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);
if (shm_fd == -1) {
fprintf(stderr, "Error al crear la variable: %s\n",
strerror(errno));
exit(1);
}
Conceptos | Implementación | Problemas | Patrones
El buffer limitado
crear_var
int crear_var (const char *name, int valor) {
int shm_fd;
int *p;
3
// ...
// Mapeo del objeto de memoria compartida.
p = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE,
MAP_SHARED, shm_fd, 0);
if (p == MAP_FAILED) {
fprintf(stderr, "...", strerror(errno));
exit(1);
}
*p = valor;
munmap(p, sizeof(int)); // Unmapping.
return shm_fd;
while (1) {
// Produce en nextP.
wait (empty);
wait (mutex);
// Guarda nextP en buffer.
signal (mutex);
signal (full);
while (1) {
}
wait (full);
wait (mutex);
// Rellenar nextC.
signal (mutex);
signal (empty);
// Consume nextC.
4
}
}
Curso 2011/2012
Trp 12 de 24
Curso 2011/2012
Trp 13 de 24
Conceptos | Implementación | Problemas | Patrones
Lectores y escritores
Conceptos | Implementación | Problemas | Patrones
El puente de un solo carril
Proceso lector
Proceso escritor
wait(mutex);
num_lectores++;
if num_lectores == 1 then
wait(acceso_esc);
signal(mutex);
// SC: Lectura
// ...
wait(mutex);
num_lectores--;
if num_lectores == 0 then
signal(acceso_esc);
signal(mutex);
wait(acceso_esc);
// SC: Escritura
// ...
signal(acceso_esc);
Norte
Sur
Curso 2011/2012
Trp 14 de 24
Curso 2011/2012
Trp 15 de 24
Conceptos | Implementación | Problemas | Patrones
Filósofos comensales
Conceptos | Implementación | Problemas | Patrones
Filósofos comensales (sin deadlock)
Proceso filósofo i
#define N 5
#define IZQ (i-1) % 5
#define DER (i+1) % 5
Proceso filósofo
while (1) {
// Pensar...
wait(palillos[i]);
wait(palillos[(i+1) % 5]);
// Comer...
signal(palillos[i]);
signal(palillos[(i+1) % 5]);
}
void coger_palillos (int i) {
wait(mutex);
estado[i] = HAMBRIENTO;
prueba(i);
signal(mutex);
wait(sem[i]);
}
int estado[N];
sem_t mutex;
sem_t sem[N];
void filosofo (int i) {
while (1) {
pensar();
coger_palillos(i);
comer();
dejar_palillos(i);
}
}
Curso 2011/2012
Trp 16 de 24
void dejar_palillos (int i) {
wait(mutex);
estado[i] = PENSANDO;
prueba(i - 1);
prueba(i + 1);
signal(mutex)
}
Curso 2011/2012
Trp 17 de 24
Conceptos | Implementación | Problemas | Patrones
El barbero dormilón
Consejos útiles
Proceso cliente
Proceso barbero
1. si
1.1
2. si
2.1
2.2
2.3
2.4
2.5
2.6
2.7
1.
2.
3.
4.
5.
no sillas libres,
marcharse
hay sillas libres,
sentarse
esperar sillón
levantarse silla
ocupar sillón
despertar barbero
esperar fin
levantarse sillón
Conceptos | Implementación | Problemas | Patrones
dormir
despertar
cortar
notificar fin
volver a 1
1
Identificación
de procesos
2
3
Identificación
de clases
Identificación de
recursos compartidos
4
Identificación de
eventos de sincronización
Curso 2011/2012
Trp 18 de 24
Curso 2011/2012
Conceptos | Implementación | Problemas | Patrones
El problema de los caníbales
?
5
Implementación
Trp 19 de 24
Conceptos | Implementación | Problemas | Patrones
La Navidad y Santa Claus
?
?
?
?
Curso 2011/2012
Trp 20 de 24
Curso 2011/2012
Trp 21 de 24
Conceptos | Implementación | Problemas | Patrones
Reutilizando conocimiento...
Reutilizando conocimiento...
Señalización (signaling)
Mutex
Proceso A
Proceso B
sentencia a1
signal(sem);
wait(sem);
sentencia b1;
Rendezvous
Proceso A
Proceso B
wait(mutex);
// Sección crítica
cont = cont + 1;
signal(mutex);
wait(mutex);
// Sección crítica
cont = cont + 1;
signal(mutex);
Multiplex
Proceso A
Proceso B
sentencia a1
sentencia a2
sentencia b1;
sentencia b2;
Curso 2011/2012
Trp 22 de 24
Conceptos | Implementación | Problemas | Patrones
Reutilizando conocimiento...
Exclusión mutua categórica
Marcador (scoreboard)
Interruptor (lightswicht)
Barrera (barrier)
Cola FIFO (FIFO queue)
Curso 2011/2012
Conceptos | Implementación | Problemas | Patrones
Trp 24 de 24
wait(multiplex);
// Sección crítica
signal(multiplex);
Curso 2011/2012
Trp 23 de 24
Descargar