Comunicaci - PowerPoint PPT Presentation

About This Presentation
Title:

Comunicaci

Description:

Comunicaci n y sincronizaci n entre procesos Mar a de los Santos P rez Hern ndez mperez_at_fi.upm.es ndice Procesos concurrentes. El problema de la secci n cr tica. – PowerPoint PPT presentation

Number of Views:94
Avg rating:3.0/5.0
Slides: 80
Provided by: mpe103
Category:
Tags: comunicaci | conan

less

Transcript and Presenter's Notes

Title: Comunicaci


1
Comunicación y sincronización entre procesos
  • María de los Santos Pérez Hernández
  • mperez_at_fi.upm.es

2
Índice
  • Procesos concurrentes.
  • El problema de la sección crítica.
  • Problemas clásicos de comunicación y
    sincronización.
  • Mecanismos de comunicación y sincronización.
  • Interbloqueos.

3
Referencias bibliográficas
  • Sistemas Operativos una visión aplicada
  • Jesús 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

4
Procesos concurrentes (I)
  • 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

5
Procesos concurrentes (II)
  • Tipos de procesos
  • Independientes
  • Cooperantes
  • Interacción entre procesos
  • Compiten por recursos
  • Comparten recursos

6
Problema de la interacción entre procesos
(procesos ligeros)
  • 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 lt 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

7
Ejemplo con sección crítica(procesos ligeros)
  • void suma_parcial(int ni, int nf)
  • int j 0
  • int suma_parcial 0
  • for (j ni j lt 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)
  • Requisitos para ofrecer secciones críticas
  • Exclusión mutua
  • Progreso
  • Espera limitada

8
Problema de la interacción 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 procesos ejecutan concurrentemente este
    código se puede perder algún ingreso.
  • Solución secciones críticas

9
Ejemplo 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
  • Requisitos para ofrecer secciones críticas
  • Exclusión mutua
  • Progreso
  • Espera limitada

10
Mecanismos de comunicación
  • Ficheros
  • Pipes
  • FIFOS
  • Variables en memoria compartida
  • Paso de mensajes
  • Sockets

11
Mecanismos de Sincronización
  • Construcciones de los lenguajes concurrentes
    (procesos ligeros)
  • Servicios del sistema operativo
  • Señales (asincronismo)
  • Pipes
  • FIFOS
  • Semáforos
  • Mutex y variables condicionales
  • Paso de mensajes
  • Las operaciones de sincronización deben ser
    atómicas

12
Características de los mecanismos de comunicación
  • Identificación
  • Mecanismos de nombrado
  • Sin nombre
  • Con nombre local
  • Con nombre de red
  • Identificador interno
  • Identificador propio
  • Descriptor de fichero
  • Flujo de datos
  • Unidireccional
  • Bidireccional
  • Buffering
  • Sin buffering
  • Con buffering
  • Sincronización
  • Síncrono (bloqueante)
  • Asíncrono (no bloqueante)

13
Problemas clásicos de comunicación y
sincronización
  • Productor-consumidor
  • Lectores-escritores

14
Problemas clásicos de comunicación y
sincronización (II)
  • Comunicación cliente-servidor

Computadora
Computadora
Petición
Proceso
Proceso
cliente
servidor
S.O.
Respuesta
15
Pipes
  • read(fildes0,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(fildes1, 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)
  • Mecanismo de comunicación y sincronización sin
    nombre
  • Sólo puede utilizarse entre los procesos hijos
    del proceso que creó el pipe
  • int pipe(int fildes2)
  • Identificación dos descriptores de fichero
  • Flujo de datos unidireccional
  • Con buffering

16
Secciones críticas con pipes
  • void main(void)
  • int fildes2 / pipe sincronización /
  • char c / carácter sincronización /
  • pipe(fildes)
  • write(fildes1, c, 1)
  • / necesario para entrar en la seccion
  • crítica la primera vez /
  • if (fork() 0) / proceso hijo /
  • for()
  • read(fildes0, c, 1)
  • / entrada sección crítica /
  • / sección crítica /
  • write(fildes1, c, 1)
  • / salida seccion crítica /
  • else / proceso padre /
  • for()
  • read(fildes0, c, 1) / entrada
    sección crítica/
  • / sección crítica /
  • write(fildes1, c, 1) / salida
    sección crítica /

17
Productor-consumidor con pipes
  • void main(void)
  • int fildes2 / pipe para comunicar y
    sincronizar /
  • int dato_p4 / datos a producir /
  • int dato_c / dato a consumir /
  • pipe(fildes)
  • if (fork() 0) / productor /
  • for()
  • / producir dato_p /
  • write(fildes1, dato_p,
  • 4sizeof(int))
  • else / consumidor /
  • for()
  • read(fildes0, dato_c,
    sizeof(int))
  • / consumir dato /

18
Ejecución de mandatos con pipes
  • / programa que ejecuta el mandato ls wc /
  • void main(void)
  • int fd2
  • pid_t pid
  • if (pipe(fd) lt 0)
  • perror(pipe'')
  • exit(1)
  • pid fork()
  • switch(pid)
  • case -1 / error /
  • perror(fork'')
  • exit(1)
  • case 0 / proceso hijo ejecuta ls /
  • close(fd0) / cierra el pipe de lectura /
  • close(STDOUT_FILENO) / cierra la salida
    estandar /
  • dup(fd1)
  • close(fd1)
  • execlp(ls'',ls'',NULL)
  • perror(execlp'')
  • exit(1)
  • default / proceso padre ejecuta wc /
  • close(fd1) / cierra el pipe de
    escritura /
  • close(STDIN_FILENO) / cierra la entrada
    estandar /
  • dup(fd0)
  • close(fd0)
  • execlp(wc'',wc'',NULL)
  • perror(execlp'')

19
Ejecución de mandatos con pipes (II)
20
FIFOS
  • Igual que los pipes
  • Mecanismo de comunicación y sincronización con
    nombre
  • Misma máquina
  • Servicios
  • mkfifo(char name,mode_t mode)
  • Crea un FIFO con nombre name
  • 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()

21
Semáforos
  • Mecanismo de sincronización
  • Misma máquina
  • Objeto con un valor entero
  • Dos operaciones atómicas
  • s_espera(s)
  • s s - 1
  • if (s lt 0)
  • Bloquear al proceso
  • s_abre(s)
  • s s 1
  • if (s lt 0)
  • Desbloquear a un
  • proceso bloqueado
  • Secciones críticas con semáforos
  • s_espera(s) / entrada en la seccion
    critica /
  • / seccion critica /
  • s_abre(s) / salida de la
  • seccion critica /
  • El semáforo debe tener valor inicial 1

22
Semáforos POSIX
  • 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 s_espera sobre un semáforo.
  • int sem_post(sem_t sem)
  • Realiza la operación s_abre sobre un semáforo.

23
Productor-consumidor con semáforos (buffer
acotado y circular)
24
Productor-consumidor con semáforos (II)
  • / 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)
  • sem_destroy(mutex)
  • exit(0)
  • 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 bufferMAX_BUFFER/buffer común/
  • 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)

25
Productor-consumidor con semáforos (III)
  • void Productor(void) / código del productor /
  • int pos 0 / posición dentro del buffer /
  • int dato / dato a producir /
  • int i
  • for(i0 i lt DATOS_A_PRODUCIR i )
  • dato i / producir dato /
  • sem_wait(huecos) / un hueco menos /
  • sem_wait(mutex) / entra en la sección
    crítica /
  • bufferpos dato
  • pos (pos 1) MAX_BUFFER
  • sem_post(mutex) / deja la sección
    crítica /
  • sem_post(elementos) / un elemento más
    /
  • pthread_exit(0)

26
Productor-consumidor con semáforos (IV)
  • void Consumidor(void) / código del Consumidor
    /
  • int pos 0
  • int dato
  • int i
  • for(i0 i lt DATOS_A_PRODUCIR i )
  • sem_wait(elementos) / un elemento
    menos /
  • sem_wait(mutex) / entra en la sección
    crítica /
  • dato bufferpos
  • pos (pos 1) MAX_BUFFER
  • sem_post(mutex) / deja la sección
    crítica /
  • sem_post(huecos) / un hueco más /
  • / consumir dato /
  • pthread_exit(0)

27
Lectores-escritores con semáforos
  • 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)

28
Lectores-escritores con semáforos (II)
  • void Lector(void) / código 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)

29
Lectores-escritores con semáforos (III)
  • void Escritor(void) / código del escritor /
  • sem_wait(mutex)
  • dato dato 2 / modificar el recurso
    /
  • sem_post(mutex)
  • pthread_exit(0)

30
Objetos de memoria compartida
  • Permiten crear un segmento de memoria compartido
    entre procesos de la misma máquina.
  • Declaración independiente de variables

31
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)
  • Sólo apertura
  • int close(int fd)
  • Cierre. El objeto persiste hasta que es cerrado
    por el último proceso.
  • 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 proyección entre el espacio de
    direcciones de un proceso y un descriptor de
    fichero u objeto de memoria compartida.

32
Servicios (II)
  • len especifica el número de bytes a proyectar.
  • prot el tipo de acceso (lectura, escritura o
    ejecución).
  • PROT_READ, PROT_WRITE, PROT_EXEC o PROT_NONE.
  • flags especifica información 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 a
    proyectar.
  • off desplazamiento dentro del fichero a partir de
    cual se realiza la proyección.
  • void munmap(void addr, size_t len)
  • Desproyecta parte del espacio de direcciones de
    un proceso comenzando en la dirección addr. El
    tamaño de la región a desproyectar es len.

33
Productor-consumidor con objetos de memoria
compartida
  • 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 memoria compartida

34
Productor-consumidor con objetos 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

35
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 /
  • sem_t mutex / acceso al buffer /
  • void main(int argc, char argv)
  • int shd
  • int buffer / buffer común /
  • / el productor crea el segmento de memoria
    compartida /
  • shd shm_open("BUFFER", O_CREATO_WRONLY,
    0700)
  • ftruncate(shd, MAX_BUFFER sizeof(int))
  • / proyectar el objeto de memoria compartida en
    el espacio
  • de direcciones del productor /

36
Código del productor (II)
  • buffer (int ) mmap(NULL, MAX_BUFFER
    sizeof(int),
  • PROT_WRITE, MAP_SHARED,
    shd, 0)
  • / El productor crea los semáforos /
  • 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")

37
Código del productor (III)
  • void Productor(int buffer) / código del
    productor /
  • int pos 0 / posición dentro del buffer /
  • int dato / dato a producir /
  • int i
  • for(i0 i lt DATOS_A_PRODUCIR i )
  • dato i / producir dato /
  • sem_wait(huecos) / un hueco menos /
  • sem_wait(mutex)
  • bufferpos dato
  • pos (pos 1) MAX_BUFFER
  • sem_post(mutex)
  • sem_post(elementos) / un elemento más /
  • return

38
Código del consumidor
  • 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 /
  • sem_t mutex / acceso al buffer /
  • void main(int argc, char argv)
  • int shd
  • int buffer / buffer común /
  • / 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 /

39
Código del consumidor (II)
  • buffer (int ) mmap(NULL, MAX_BUFFER
    sizeof(int),
  • PROT_READ, MAP_SHARED,
    shd, 0)
  • / El consumidor abre los semáforos /
  • 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 semáforos /
  • sem_close(elementos) sem_close(huecos)
    sem_close(mutex)

40
Código del consumidor (III)
  • void Consumidor(char buffer) /código del
    Consumidor/
  • int pos 0
  • int i, dato
  • for(i0 i lt DATOS_A_PRODUCIR i )
  • sem_wait(elementos) / un elemento
    menos /
  • sem_wait(mutex)
  • dato bufferpos
  • pos (pos 1) MAX_BUFFER
  • sem_post(mutex)
  • sem_post(huecos) / un hueco mas /
  • printf("Consume d \n", dato) / consumir
    dato /
  • return

41
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.

42
Secciones críticas con mutex
  • lock(m) / entrada en la sección crítica /
  • / sección crítica /
  • unlock(s) / salida de la sección crítica /
  • La operación unlock debe realizarla el proceso
    ligero que ejecutó lock

43
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

44
Uso de mutex y variables condicionales
  • Proceso ligero A
  • lock(mutex) / acceso al recurso /
  • / codigo de la sección
  • crítica /
  • while (condicion FALSE)
  • wait(condition, mutex)
  • / resto de la sección crítica /
  • unlock(mutex)
  • Proceso ligero B
  • lock(mutex) / acceso al recurso /
  • / código de la sección crítica /
  • / se modifica la condicción y ésta se hace TRUE
    /
  • condicion true
  • signal(condition, mutex)
  • unlock(mutex)
  • Importante utilizar while

45
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 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.
  • int pthread_cond_destroy(pthread_cond_t cond)
  • Destruye una variable condicional.

46
Servicios (II)
  • 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.

47
Productor-consumidor con mutex
  • define MAX_BUFFER 1024 / tamaño 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 bufferMAX_BUFFER / buffer común /
  • main(int argc, char argv)
  • pthread_t th1, th2
  • pthread_mutex_init(mutex, NULL)

48
Productor-consumidor con mutex (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)

49
Productor-consumidor con mutex (III)
  • void Productor(void) / código del productor
    /
  • int dato, i ,pos 0
  • for(i0 i lt DATOS_A_PRODUCIR i )
  • dato i / producir dato /
  • pthread_mutex_lock(mutex) / acceder
    al buffer /
  • while (n_elementosMAX_BUFFER)/ si
    buffer lleno /
  • pthread_cond_wait(no_lleno,
    mutex)/ bloqueo /
  • bufferpos dato
  • pos (pos 1) MAX_BUFFER
  • n_elementos
  • pthread_cond_signal(no_vacio)/ buffer
    no vacío /
  • pthread_mutex_unlock(mutex)
  • pthread_exit(0)

50
Productor-consumidor con mutex (IV)
  • void Consumidor(void) / código del consumidor
    /
  • int dato, i ,pos 0
  • for(i0 i lt DATOS_A_PRODUCIR i )
  • pthread_mutex_lock(mutex) / acceder al
    buffer /
  • while (n_elementos 0) / si buffer
    vacío /
  • pthread_cond_wait(no_vacio,
    mutex)/ bloqueo /
  • dato bufferpos
  • 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)

51
Lectores-escritores con mutex
  • 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)

52
Lectores-escritores con mutex (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)

53
Lectores-escritores con mutex (III)
  • void Lector(void) / código 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)

54
Lectores-escritores con mutex (IV)
  • void Escritor(void) / código del escritor /
  • pthread_mutex_lock(mutex)
  • dato dato 2 / modificar el recurso /
  • pthread_mutex_unlock(mutex)
  • pthread_exit(0)

55
Paso de mensajes
  • Múltiples soluciones
  • Paso de mensajes en POSIX (colas de mensajes)
  • Misma máquina (uniprocesador, multiprocesador o
    multicomputador)
  • Mecanismo de nombrado con nombre local
  • Identificación identificador especial
  • Buffering Sí
  • Unidireccional
  • Sincronización bloqueante y no bloqueante
  • 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(origen, mensaje) recibe un mensaje del
    proceso origen

56
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.

57
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 (el de mayor prioridad).
    Almacena la prioridad del mensaje en el parámetro
    prio
  • Recepción bloqueante o no.

58
Secciones críticas con colas de mensajes
  • void main(void)
  • mqd_t mutex / cola de mensajes para
    sincronizar acceso a la sección crítica /
  • struct mq_attr attr /atributos cola de
    mensajes/
  • char c / carácter para sincronizar /
  • attr.mq_maxmsg 1 / número máximo mensajes
    /
  • attr.mq_msgsize 1 / tamaño mensaje /
  • mutex mq_open(MUTEX'', O_CREATO_RDWR,
    0777, attr)
  • mq_send(mutex, c, 1, 0) / entrar en la
    sección
  • crítica la primera
    vez /

59
Secciones críticas con colas de mensajes (II)
  • if (fork() 0) / proceso hijo /
  • for()
  • mq_receive(mutex, c, 1, NULL)/entrada
    sec. crítica /
  • / sección crítica /
  • mq_send(mutex, c, 1, 0) / salida
    sec. critica /
  • else / proceso padre /
  • for()
  • mq_receive(mutex, c, 1, NULL)/entrada
    sec. crítica /
  • / sección crítica /
  • mq_send(mutex, c, 1, 0) / salida
    sec. critica /

60
Productor-consumidor con colas de mensajes
  • define MAX_BUFFER 1024 / tamaño 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_CREATO_RDWR,
    0777, attr)

61
Productor-consumidor con colas de mensajes (II)
  • if (almacen -1)
  • perror("mq_open")
  • exit(1)
  • if (fork() 0) / proceso hijo /
  • Productor()
  • else / proceso padre /
  • Consumidor()
  • exit(0)

62
Productor-consumidor con colas de mensajes (III)
  • void Consumidor(void)
  • int dato
  • int i
  • for(i0
  • i lt DATOS_A_PRODUCIR i )
  • mq_receive(almacen, dato, sizeof(int),
    NULL)
  • / consumir dato /
  • printf("Consume d\n", dato)
  • return
  • void Productor(void)
  • int dato
  • int i
  • for(i0
  • i lt DATOS_A_PRODUCIR i )
  • / producir dato /
  • dato i
  • printf("Produce d \n", dato)
  • mq_send(almacen, dato, sizeof(int),
    0)
  • return

63
Lectores-escritores con colas de mensajes
  • struct peticion_t
  • int tipo
  • char cola100
  • void lector(char lector) / identificador
    lector /
  • mqd_t controlador / cola proceso
    controlador /
  • mqd_t cola_local / cola para el lector /
  • struct mq_attr attr
  • struct peticion_t peticion
  • attr.mq_maxmsg 1
  • attr.mq_msgsize sizeof(struct peticion_t)
  • controlador mq_open("CONTROLADOR", O_RDWR)
  • cola_local mq_open(lector, O_CREATO_RDWR,
    0777, attr)

64
Lectores-escritores con colas de mensajes (II)
  • peticion.tipo READ
  • strcpy(peticion.cola, lector)
  • / solicitud de lectura al controlador /
  • mq_send(controlador, peticion,
    sizeof(peticion), 0)
  • mq_receive(cola_local, peticion,
    sizeof(peticion), NULL)
  • / leer /
  • peticion.tipo OK / fin de lectura /
  • mq_send(cola_local, peticion,
    sizeof(peticion), 0)
  • mq_close(cola_local) mq_close(controlador)
    mq_unlink(lector)
  • El proceso escritor es similar.

65
Lectores-escritores con colas de mensajes (III)
  • void Controlador(void)
  • mqd_t controlador / cola del proceso
    controlador /
  • struct mq_attr attr
  • struct peticion_t peticion
  • attr.mq_maxmsg 1
  • attr.mq_msgsize sizeof(struct peticion_t)
  • controlador mq_open("CONTROLADOR",
    O_CREATO_RDWR, 0777, attr)
  • for ()
  • mq_receive(controlador, peticion,
    sizeof(peticion), 0)
  • if (peticion.tipo READ)
  • crear_thread(do_read, peticion)
  • else
  • crear_thread(do_write, peticion)

66
Lectores-escritores con colas de mensajes (IV)
  • void do_write(struct peticion_t pet)
  • mqd_t cola_local
  • struct peticion_t peticion
  • / abre la cola del proceso que realiza la
    peticion /
  • cola_local mq_open(pet-gtcola, O_RDWR)
  • pthread_mutex_lock(mutex)
  • while (n_lectores gt 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)
  • void do_read(struct peticion_t pet)
  • mqd_t cola_local
  • struct peticion_t peticion
  • / abre la cola del proceso que realiza la
    peticion /
  • cola_local mq_open(pet-gtcola, 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)

67
Servidor multithread con colas de mensajes
68
Servidor multithread con colas de mensajes (II)
  • / estructura de un mensaje /
  • struct mensaje
  • char buffer1024 / datos a enviar /
  • char cliente256 / cola del cliente /
  • / mutex y var. condicionales protección 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)

69
Servidor multithread con colas de mensajes (III)
  • q_servidor mq_open("SERVIDOR",
    O_CREATO_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_SYS
    TEM)
  • 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)

70
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 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 petición 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)

71
Ejemplo de código cliente
  • struct mensaje / estructura mensaje /
  • char buffer1024 / datos envío /
  • char cliente256 / 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
    del servidor /
  • attr.mq_maxmsg 1
  • attr.mq_msgsize
  • sizeof(struct mensaje)
  • q_cliente mq_open("CLIENTE",
    O_CREATO_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)

72
Sockets
  • Permiten comunicar
  • Procesos del mismo computador
  • Procesos conectados a través de una red
  • Tipos de direcciones
  • Direcciones locales dominio UNIX
  • Direcciones de red (TCP/IP)
  • Dirección de red (dirección IP)
  • Puerto

73
Sockets (II)
74
Resumen
  • Pipes
  • Mecanismo de comunicación y sincronización
  • Mecanismo de nombrado sin nombre
  • Identificación descriptor de fichero
  • Flujo de datos unidireccional
  • Buffering Sí
  • Sincronización
  • Si pipe vacío ? read() se bloquea
  • Si pipe lleno ? write() se bloquea
  • FIFOS
  • Mecanismo de comunicación y sincronización
  • Mecanismo de nombrado con nombre local
  • Identificación descriptor de fichero
  • Flujo de datos unidireccional
  • Buffering Sí
  • Sincronización
  • Si FIFO vacío ? read() se bloquea
  • Si FIFO lleno ? write() se bloquea

75
Resumen (II)
  • Semáforos POSIX
  • Mecanismo de sincronización
  • Mecanismo de nombrado sin nombre y con nombre
    local
  • Identificación variable de tipo semáforo
  • Mutex y variables condicionales
  • Mecanismo de sincronización adecuado para
    procesos ligeros
  • Mecanismo de nombrado sin nombre
  • Identificación variables
  • Colas de mensajes POSIX
  • Mecanismo de comunicación y sincronización
  • Mecanismo de nombrado con nombre local
  • Identificación identificador especial
  • Buffering Sí
  • Unidireccional
  • Sincronización bloqueante y no bloqueante

76
Resumen (III)
  • Objetos de memoria compartida
  • Mecanismo de comunicación
  • Mecanismo de nombrado con nombre local
  • Identificación identificador especial
  • Sockets
  • Mecanismo de comunicación y sincronización
  • Mecanismo de nombrado con nombre de red
  • Identificación descriptor de fichero
  • Buffering Sí
  • Sincronización bloqueante y no bloqueante

77
Interbloqueos
  • Bloqueo permanente de un conjunto de procesos que
    compiten por los recursos del sistema o se
    comunican entre sí.
  • Ejemplo Si S y Q con semáforos 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 dos colas de mensajes
  • P0 P1
  • receive(C1, M) receive(C2, N)
  • . .
  • send(C2, M) send(C1, N)
  • Condiciones del interbloqueo
  • Exclusión mutua
  • Retención y espera
  • No apropiación
  • Espera circular

78
Ejemplo
  • Ejemplo Si P y Q son semáforos con valor inicial
    1
  • A B
  • s_espera(P) s_espera(Q)
  • s_espera(Q) s_espera(P)
  • Interbloqueo

79
Métodos para tratar con los interbloqueos
  • Ignorarlos ? UNIX
  • Solucionarlos
  • Métodos para prevenir los interbloqueos
  • Métodos para evitar los interbloqueos
  • Métodos para detectar los interbloqueos
Write a Comment
User Comments (0)
About PowerShow.com