51
26/01/2010 1 Tema Tema 5: 5: Tema Tema 5: 5: Comunicación Comunicación y sincronización sincronización de de procesos procesos Tema 5: Tema 5: Comunicación Comunicación y sincronización y sincronización de de procesos procesos Comunicación y sincronización Espera activa Semáforos Problemas clásicos de com. y sin. Mecanismos de com y sin Mecanismos de com. y sin. Servicios POSIX

Tema 5: ComunicaciónComunicación y y …dsa-research.org/teresa/SO/Clases/COM y SIM.pdf26/01/2010 6 ¿Cómosolucionar el problema planteado? 1. Atomicidad‐Una operación se dice

  • Upload
    others

  • View
    3

  • Download
    0

Embed Size (px)

Citation preview

26/01/2010

1

TemaTema 5:5:TemaTema 5:5:ComunicaciónComunicación y y sincronizaciónsincronización

de de procesosprocesos

Tema 5:Tema 5:Comunicación Comunicación y sincronización y sincronización de de procesosprocesos

• Comunicación y sincronizaciónCo u cac ó y s c o ac ó

• Espera activa

• Semáforos

• Problemas clásicos de com. y sin.

• Mecanismos de com y sinMecanismos de com. y sin.

• Servicios POSIX

26/01/2010

2

EscenarioEscenario

Un sistema operativo multiprogramado permite:ejecución concurrente y

Procesos independientes• Su estado no es compartido 

• Son deterministas 

S d ibl

Procesos cooperantes• Su estado es compartido

• Su funcionamiento no es determinista

compartición de recursos entre varios procesos activosTipos de procesos:

• Son reproducibles 

• Pueden ser detenidos y rearrancados sin ningún efecto negativo

determinista

• Su funcionamiento puede ser irreproducible

• Si son detenidos y posteriormente rearrancadospuede que se produzcan efectos negativos

EscenarioEscenario

Los procesos cooperantes pueden acceder simultáneamente a recursos compartidos

•Deben comunicarse para lograr un objetivo común => Mecanismos de comunicación•Pueden producirse secuenciaciones incorrectas => Mecanismos de sincronización

Problemas clásicos:•Problema del productor consumidor•Problema del productor‐consumidor•Problema de la sección crítica•Problema de lectores‐escritores•Problema del puente estrecho•etc. 

26/01/2010

3

Comunicación Comunicación y y sincronizaciónsincronización

• Problema del productor‐consumidor

• Condiciones de carrera• Condiciones de carrera

• Sección crítica

• Productor‐consumidor

• El problema de los lectores y escritores

• Comunicación cliente‐servidorComunicación cliente servidor

• Acceso concurrente a datos compartidos puede dar comoresultado datos inconsistentes

Comunicación Comunicación y y sincronizaciónsincronización

• El mantenimiento de la consistecia de los datos requieremecanismos para asegurar el orden en la ejecución de los procesos cooperates

• Como ejemplo usamos el problema del consumidor‐productor. 

Un proceso produce datos que son posteriormente procesados por otro proceso Ej: el manejador de teclado y el programa que recoge los caracteres de un

buffer Lo más cómodo es emplear un buffer circular

26/01/2010

4

• El entero cuenta lleva la cuenta de elementos del buffer llenos

– Inicialmente cuenta está a 0

Se incrementa cuando el productor produce un nuevo elemento

Comunicación Comunicación y y sincronizaciónsincronización

– Se incrementa cuando el productor produce un nuevo elemento

– Se decrementa cuando el consumidor consume un elemento

EscribeLee

ConsumidorProductor

while (true) {

ProductorProductor

/* produce un elemento en la variable nuevoElto */

while (cuenta == BUFFER_SIZE); // no hace nada

buffer [in] = nuevoElto;

i (i 1) % BUFFER SIZEin = (in + 1) % BUFFER_SIZE;

cuenta++;

}   

26/01/2010

5

while (true)  {

while (cuenta == 0); // no hace nada

CConsumidoronsumidor

while (cuenta  0); // no hace nada

sigConsumido =  buffer[out];

out = (out + 1) % BUFFER_SIZE;

cuenta‐‐;

/*  consume el elemento en sigConsumido

}

Condiciones de carrera ICondiciones de carrera I cuenta++ se puede implementar como:

registro1 = cuentaregistro1 = registro1 + 1registro1 = registro1 + 1cuenta = registro1

cuenta-- se puede implementar como:

registro2 = cuentaregistro2 = registro2 - 1cuenta = registro2

Considerar la ejecución intercalada con “cuenta = 5” :

S0: productor ejecuta registro1 = cuenta {registro1 = 5}S1: productor ejecuta registro1 = registro1 + 1 {registro1 = 6} S2: consumidor ejecuta registro2 = cuenta {registro2 = 5} S3: consumidor ejecuta registro2 = registro2 - 1 {registro2 = 4} S4: productor ejecuta cuenta = registro1 {cuenta = 6 } S5: consumidor ejecuta cuenta = registro2 {cuenta = 4}

26/01/2010

6

¿Cómo solucionar el problema planteado?

1. Atomicidad‐ Una operación se dice que es atómica (en un sistema uniprocesador) cuando se ejecuta con las interrupciones deshabilitadas

Condiciones de carrera IICondiciones de carrera II

uniprocesador) cuando se ejecuta con las interrupciones deshabilitadas Las referencias y las asignaciones son atómicas en a mayoría de los 

sistemas. Esto no es siempre cierto para matrices, estructuras o números en coma flotante

Si el HW no proporciona operaciones atómicas, éstas no pueden construirse por SW

2. Exclusión mutua ‐ Es el mecanismo que asegura que sólo una persona o proceso está haciendo algo en un instante determinado (los otros están excluidos)excluidos).

3. Sección crítica ‐ es la sección de código, o colección de operaciones, en el que se actualizan variables comunes. Cuando un proceso está ejecutando código de su SC, ningún otro proceso puede estar en su SC.

Toda solución debe cumplir tres condiciones:

Sección crítica Sección crítica II

1. Exclusión mútua‐ No puede haber dos procesos simultánamante en la región crítica. Si un proceso Pi está ejecutando en su región crítica, ningún otro proceso se puede ejecutar en dicha región crítica.

2. Progreso ‐ Ningún proceso fuera de la región crítica puede bloquear a otros procesos. 

3. Espera acotada ‐ Ningún proceso debe esperar infinitamente paraentrar en su región crítica. 

26/01/2010

7

Sección crítica IISección crítica II

Exclusión mútua usando regiones críticas

Suposiciones:1. Los procesos se ejecutan a una velocidad <>02. Su velocidad relativa no influye

Tipos de solucionesTipos de soluciones

No se realiza ninguna asumpción sobre la velocidad de los procesos o sobre el número de CPUs

Soluciones:1. Basadas en variables de control – solución de Peterson

2. Basadas en instrucciones máquina – test‐and‐set, swap

3. Basadas en primitivas del SO – sin espera activa

4. Basadas en regiones críticas y monitores ‐ lenguajes de programación, Ada, Java

26/01/2010

8

Exclusión Exclusión mútuamútua con espera activacon espera activa

Mutual Exclusion with Busy Waiting (1)

PROBLEMA: Alternancía estricta‐> viola la condición 2 de sección crítica

Exclusión Exclusión mútuamútua con espera activacon espera activaSolución de Peterson ISolución de Peterson I

• Solución para dos  procesos

• Asume que las instrucciones LOAD y STORE son atómicas; estoes, no se pueden interrumpires, no se pueden interrumpir

• Los dos procesos comparten dos variabes:

– int turn; 

– boolean flag[2]

• La variable turn indica el turno de entrada en la región crítica.

El fl tili i di i tá li t• El array  flag se utiliza para indicar si un proceso está listo paraentrar en la región:

• flag[i] = true implica que el proceso Pi está listo!

26/01/2010

9

Algorithmo para el proceso Pihil (t ) {

Exclusión Exclusión mútuamútua con espera activacon espera activaSolución de Peterson IISolución de Peterson II

while (true) {

flag[i] = TRUE;

turn = j;

while ( flag[j] && turn == j);

REGIÓN CRÍTICA 

flag[i] = FALSE;

}

Exclusión Exclusión mútuamútua con espera activacon espera activaSolución de Peterson IIISolución de Peterson III

26/01/2010

10

• Muchos sistemas proporcionan soporte hardware parasecciones críticas

Exclusión Exclusión mútuamútua con espera activacon espera activaSincronización Hardware ISincronización Hardware I

• Uniprocesadores – se pueden deshabilitar las interrupciones

– El código se ejecuta sin expulsión: poco recomendable

– Generalmente muy ineficiente en multiprocesadores s

• Hace que el SO no escale bien

I t i h i l d j ió tó i• Instrucciones hw especiales de ejecución atómica: 

• Atómica = no‐interrumpible

– lee una palabra o bit y escribe un valor (TAS o TSL)

– Intercambia el contenido de dos posiciones de  memoria o una posición de memoria y un registro (SWAP)

Exclusión Exclusión mútuamútua con espera activacon espera activaSincronización Hardware IISincronización Hardware II

20

Entrar en la región crítica utilizando la instrucciónTest-and-Set-Lock: TSL

Test-And-Set: TAS

26/01/2010

11

• Operación atómicas:

Exclusión Exclusión mútuamútua con espera activacon espera activaSincronización Hardware IIISincronización Hardware III

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;

}

Exclusión Exclusión mútuamútua con espera activacon espera activaSincronización Hardware IVSincronización Hardware IV

• Sección crítica con test‐and‐set: 

• Los procesos comparten la variable lock con valor inicial FALSE

while ( test‐and‐set (&lock ) ;   /* nada

//    critical section

lock = FALSE;

• Sección crítica con swap: • Los procesos comparten la variable lock con valor inicial FALSE.• Cada proceso utiliza una variable local llave.Cada proceso utiliza una variable local llave.

llave = TRUE;while ( llave == TRUE)

swap (lock, llave );//    región crítica

lock = FALSE;

26/01/2010

12

SemáforosSemáforos II Herramienta de sincronización sin espera activa

Semáforo S – variable entera

Misma máquina Misma máquina

Dos operaciones atómicas modifican S: wait() y signal()

Originalmente llamadas P() y V()

wait(s); /* entrada en la seccion critica */

< seccion critica >

signal(s); /* salida de la seccion critica */

• El semáforo binario debe tener valor inicial 1 

• Semáforo contador – valor entero

• Semáforo binario – valor entero entre 0 y 1; puede ser másll l

SemáforosSemáforos IIII

sencillo de implementar

– También se conocen como mutex o locks– Proporciona exclusión mútua

Semaphore S;    //  initializado 1

wait (S);wait (S);

Critical Section

signal (S);

26/01/2010

13

SemáforosSemáforos IIIIIIP

0

Valor del

semáforo (s)

1

P1

P2

wait(s)

signal(s)

wait(s)

desbloquea

wait(s)

0

-1

-2

-1

signal(s)

signal(s)

desbloquea

1

0

Ejecutando código de la sección crítica

Proceso bloqueado en el semáforo

• Cada semáforo tiene asociada una cola de espera.

• Cada entrada en la cola tiene dos items:

SemáforosSemáforos IVIV

Cada e t ada e a co a t e e dos te s:– valor (un tipo entero)

– Puntero al siguiente elemento de la lista

• Dos operaciones:– block – coloca al proceso que invoca la operación en la p q pcola apropiada.

– wakeup – quita uno de los procesos de la cola y lo pone en la cola de preparados.

26/01/2010

14

SemáforosSemáforos VVwait(s){

s = s - 1;if (s < 0) {if (s < 0) {

<Bloquear al proceso>}

}

signal(s){

s s + 1s = s + 1;if (s <= 0)

<Desbloquear a un proceso bloqueado por la operacion wait>

}}

• Interbloqueo – Dos o más procesos están esperandoinfinitamente por un evento que debe producir un proceso que está bloqueado

InterbloqueoInterbloqueo e e InaniciónInanición

proceso que está bloqueado.

Sean S y Q dos semáforos inicializados a 1P0 P1wait (S);  wait (Q);

wait (Q);  wait (S);.  ..  ..  .

signal  (S);  signal (Q);signal (Q);  signal (S);

• Inanición – Bloqueo indefinido.  Un proceso puedeestar en indefinidamente en la cola del semáforo. 

26/01/2010

15

•• ProductorProductor‐‐consumidorconsumidor:  :  Problema del buffer li it d

ProblemasProblemas ClásicosClásicosde de ComunicaciónComunicación y y SincronizaciónSincronización

limitado

•• LectoresLectores‐‐escritoresescritores: : Problema acceso exclusivodel escritor y acceso compartido de lectores

•• El El barberobarbero dormilóndormilón : : Problema con procesosno cíclicosno cíclicos

•• CenaCena de los de los filósofosfilósofos: : Problema de númerorecursos limitados

ProductorProductor--ConsumdorConsumdor..CondicionesCondiciones de de carreracarrera

#define BUFFER_SIZE  100int cuenta 0;void productor(void)

{int elto;int elto;

while (true) {/* produce un elemento en la variable elto */while (cuenta == BUFFER_SIZE); // no hace nadainsertarElemento(elto);cuenta++;

} }

void consumidor(void){

int elto;int elto;

while (true)  {while (cuenta == 0); // no hace nadaelto =consumeElto();cuenta‐‐;/*  consume el elemento en sigConsumido

}}  

26/01/2010

16

ProductorProductor--ConsumdorConsumdor::ProblemaProblema del buffer del buffer limitadolimitado

• N buffers, cada uno puede contener un elemento

• Semáforo mutex inicializado a 1

• Semáforo full inicializado a 0

S áf i i i li d N• Semáforo empty inicializado a N

• Estructura del proceso productor

while (true)  {

ProductorProductor--ConsumdorConsumdorCon Con semáforossemáforos II

//   produce an item

wait (empty);

wait (mutex);

//  add the item to the  buffer

i l ( t )signal (mutex);

signal (full);

}

26/01/2010

17

• Estructura del proceso consumidor

while (true) {

it (f ll)

ProductorProductor--ConsumdorConsumdorCon Con semáforossemáforos IIII

wait (full);

wait (mutex);

//  remove an item from  buffer

signal (mutex);

signal (empty);

//  consume the removed item

}

ProductorProductor--ConsumdorConsumdorCon Con semáforossemáforos IIIIII

26/01/2010

18

• Varios procesos concurrentes comparten una hojade datos:– Readers – leen la hoja de datos; no realizan

l

LectoresLectores--EscritoresEscritores. . DefiniciónDefinición del del ProblemaProblema

actualizaciones– Writers   – pueden leer leer y escribir

• Problema – se permiten varios lectores al mismotiempo y un único escritor con acceso exclusivo

• Variables compartidas– Hoja de datos– Semáforo mutex inicializado a to 1.– Semáforo wrt inicializado a 1.– Entero readcount inicializado a 0.

• Estructura de un proceso escritor

while (true) {

LectoresLectores--EscritoresEscritores. . Con Con semáforossemáforos II

while (true) {wait (wrt) ;

//    writing is performed

signal (wrt) ;}}

26/01/2010

19

• Estructura de un proceso lector

while (true) {wait (mutex) ;

LectoresLectores--EscritoresEscritores. . Con Con semáforossemáforos IIII

readcount ++ ;if (readcount == 1)  wait (wrt) ;signal (mutex)

// reading is performed

wait (mutex) ;readcount ‐ ‐ ;if (readcount == 0)  signal (wrt) ;signal (mutex) ;signal (mutex) ;

}

LectoresLectores--EscritoresEscritores. . Con Con semáforossemáforos IIIIII

26/01/2010

20

El El barberobarbero dormilóndormilón. . DefiniciónDefinición del del ProblemaProblema

Variables compartidasSemáforo clientes inicializado a 0 (num clientes esperando, no incluye al que se está atendiendo ). No se puede leer‐>

Espera: num clientes esperandoSemáforo barbero inicializado a 0 (dormido=0, activo=1) 

El El barberobarbero dormilóndormilón. . Con Con semáforossemáforos I I

26/01/2010

21

CenaCena de los de los filósofosfilósofos. . DefiniciónDefinición del del ProblemaProblema

• Variables compartidas– Plato de arroz (hoja de datos)– Semáforo tenedor [5] inicializado a 1

Estructura del filósofo I (con interbloqueos):

While (true) {

CenaCena de los de los filósofosfilósofos. . Con Con semáforossemáforos II

While (true)  { wait (tenedor[i]);wait (tenedor[ (i + 1) % 5]);

//  comer

signal (tenedor[i] );signal (tenedor[ (i + 1) % 5]);

//  pensar

}

26/01/2010

22

CenaCena de los de los filósofosfilósofos. . Con Con semáforossemáforos IIII

CenaCena de los de los filósofosfilósofos. . Con Con semáforossemáforos IIIIII

26/01/2010

23

• Uso correcto de las peraciones:

ProblemasProblemas con con SemáforosSemáforos

– signal (mutex)  ….  wait (mutex)

– wait (mutex)  …  wait (mutex)

O i ió d it ( t ) i l ( t )– Omisión de wait (mutex) o signal (mutex) (o ambos)

•• MonitoresMonitores

MecanismosMecanismosde de ComunicaciónComunicación y y SincronizaciónSincronización

•• Variables de Variables de condicióncondición

•• Paso de Paso de MensajesMensajes

•• BarrerasBarreras

•• TransaccionesTransacciones

26/01/2010

24

MonitoresMonitores

• Herramienta con alto nivel de abstracción que proporciona sinccronización entre procesos o threads.

• Lenguajes de alto nivel: Java: synchronize, Ada 95: protected

• Únicamente un proceso puede stas activo en le monitor en un momento dado.

monitor nombre‐ monitor

{

// decharación de variables compartidas

procedure P1 (…) { …. }

procedure Pn ( ) { }procedure Pn (…) {……}

código de inicialización ( ….) { … }

}

}

EsquemaEsquema de un monitorde un monitor

26/01/2010

25

• Variables de sincronización asociadas a un mutex– condition x, y;

Variables de Variables de condicióncondición

• Operationes sobre una variale de condición:

– wait (x)  – El proceos que invoca la operación se bloquea

– signal (x) – reanuda uno de los procesos bloqueados en la condición X (si hay alguno); sino la señal se pierde:

han invocado wait (x)

• Conveniente ejecutarlas dentro de una región crítica (ej. un monitor)

EsquemaEsquema de un monitor de un monitor con variables de con variables de condicióncondición

• Cuando un proceso reanuda a otro en una variable de condición: – Señalizar y esperar (Hoare, Hansen): la condición para el proceso que reanuda la ejecución se sigue

cumpliendo.– Señalizar y continuar (Lampson): Evita la inanición de los procesos bloqueados. El proceso reanudado

debe preguntar otra vez por la condición (while X).

26/01/2010

26

monitor DP{ 

enum { THINKING; HUNGRY, EATING) state [5] ;condition s[5]; // Un semáforo por cada filósfo

void take forks (int i) {

CenaCena de los de los filósofosfilósofos. . Con Con monitoresmonitores II

void take_forks (int i) { state[i] = HUNGRY;test(i);if (state[i] != EATING) wait(s[i]); // while (state[i] != EATING) s[i].wait; en 

Lampson}

void put_forks (int i) { state[i] = THINKING;test((i + 4) % 5);     // izquierdatest((i + 1) % 5);    // derecha

id t t (i t i) {void test (int i) { if ( (state[i] == HUNGRY) state[(i + 4) % 5] != EATING) &&( &&(state[(i + 1) % 5] != EATING) ) { 

state[i] = EATING ;signal(s[i]) ;

}}

initialization_code() { for (int i = 0; i < 5; i++)state[i] = THINKING;

}}

• Cada filósofo i invoca las operaciones take_forks() y put_forks()en la siguiente secuencia:

CenaCena de los de los filósofosfilósofos. . Con Con monitoresmonitores IIII

dp.take_forks(i);

EAT

dp.put_forks(i);

26/01/2010

27

ProductorProductor--consumidorconsumidorcon con monitoresmonitores

• Permite resolver: – Exclusión mutua

– Sincronización entre un proceso que recibe un mensaje y otro que lo í

Paso de Paso de mensajesmensajes

envía

– Comunicación de datos entre espacios de memoria diferentes• mismo computador

• diferentes computadores

• Primitivas básicas: – send(P, mensaje) envía un mensaje al proceso P

– receive(Q, mensaje) recibe un mensaje del proceso Q

– receive(ANY, mensaje) recibe un mensaje de cualquier proceso

26/01/2010

28

– Tamaño del mensaje: fijo o variable

– Flujo de datos: unidireccional o bidireccional

– Nombrado• Directo > proceso: pid o ANY

Paso de Paso de mensajesmensajes..AspectosAspectos de de diseñodiseño

• Directo‐> proceso: pid o ANY

– send(P, mensaje) envía un mensaje al proceso P

– receive(Q, mensaje) recibe un mensaje del proceso Q

• Indirecto (puerto, cola) ‐> buzón asociado a un proceso

– send(Q, mensaje) envía un mensaje a la cola o puerto Q

– receive(Q, mensaje) recibe un mensaje a la cola o puerto Q

– Sincronización (síncrono, asíncrono) • Envío y recepción bloqueante: síncrono ‐> cita o rendezvous (Ej. ADA)

• Envío no bloqueante y recepción bloqueante: es la más utilizadaq y p q

• Envío y recepción no bloqueante: asíncrono

– Almacenamiento• Sin (cita)

• Asícrono

– Ámbito• Local (tubería pipes)

• Remoto (sockets)

• Ejemplo: Si C1 y C2 son dos colas de mensajes: 

P1 P2

Paso de Paso de mensajesmensajes..InterbloqueosInterbloqueos

P1 P2receive(P2, M) receive(P1, N)... ...

send(P2, M) send(P1, N)

• Condiciones del interbloqueo: – Exclusión mutuaExclusión mutua

– Retención y espera

– No apropiación

– Espera circular 

26/01/2010

29

ProductorProductor--consumidorconsumidorcon con pasopaso de de mensajesmensajes

Mecanismos ofrecidos por el SOMecanismos ofrecidos por el SO

Mecanismo Comunicación Sincronización

ÍTuberías SÍ SÍ

Señales NO SÍ

Variables enmemoria compartida

SÍ SÍ

Semáforos NO SÍSemáforos NO SÍ

Mutex y variables condicionales

NO SÍ

Paso de mensajes SÍ SÍ

26/01/2010

30

•• TuberíasTuberías

ServiciosServicios POSIXPOSIX

–– Sin Sin nombrenombre

–– Con Con nombrenombre

•• SemáforosSemáforos

•• MutexMutex

V i blV i bl di i ldi i l•• Variables Variables condicionalescondicionales

•• Paso de Paso de mensajesmensajes

• Flujo unidireccional

• Con almacenamiento. El tamaño depende de

d SO

TuberíasTuberías

• cada SO

• Generalmente se implementa como una zona de memoria compartida entre los procesos que usan la tubería 

Proceso A Proceso BTubería

write() Read()

26/01/2010

31

• Flujo Bidireccional: dos tuberías

TuberíasTuberías IIII

Proceso A Proceso B

Tubería 1

write() Read()

Tubería 2

write()Read()

• Funcionamiento FIFO

TuberíasTuberías IIIIII

• Escritura• Si la tubería está llena o se

• Lectura• Sila tubería está vacía, seSi la tubería está llena o se 

llena durante esta operación, se bloquea el proceso escritor hasta que se pueda realizar la operación

Sila tubería está vacía, se bloquea la proceso lector hasta que se escriba en ella. Si no hay escritores, la operación devuelve fin de archivo y no hay bloqueo

• Si la tubería almacena M bytes y se quieren leer n bytes: si M>=n la operación

• Operación atómica

bytes: si M>=n, la operación devuelve n. Si M<n, la operación devuelkve M. En ambos casos, se eliminan los datos leídos de la tubería

• Operación atómica

26/01/2010

32

• Tipos de tuberías:– Tuberías sin nombre (pipe): 

• Sólo se pueden usar por el proceso que las crea y sus

TuberíasTuberías IVIV

Sólo se pueden usar por el proceso que las crea y sus procesos hijos.

– Tuberías con nombre (FIFO): • Tienen un nombre local (nombre del archivo FIFO)

• Se pueden usar para comunicar procesos independientes

• Principales servicios POSIX para gestionar tuberías:– Crear/Borrar

– Abrir/Cerrar

– Leer/Escribir

• Crear una tubería sin nombre– int pipe(int fildes[2]);

– Devuelve dos descriptores de archivos y cero si se ejecuta correctamente. En caso contrario -1

TuberíasTuberías POSIX IPOSIX I

En caso contrario, -1

• Crear una tuberías con nombre– int mkfifo(char *name, mode_t mode);– Devuelve cero si se ejecuta correctamente. En caso contrario, -1

• Abrir una tubería con nombreAbrir una tubería con nombre– int open(char *fifo, int flag);

– Bloquea al proceso que la ejecuta hasta que haya otro proceso en el otro extremo del FIFO

– Devuelve un descriptor de archivo que se puede usar para leer y escribir del FIFO y cero si se ejecuta correctamente. En otro caso –1

26/01/2010

33

• Cerrar una tubería

TuberíasTuberías POSIX IIPOSIX II

– int close(int fd);

– Tubería sin nombre: se destruye cuando se cierra el último de sus descriptores asociados

• Borrar una tubería con nombre– int unlink(char *fifo);

Destruye el FIFO si todos los procesos que lo están utilizando lo han– Destruye el FIFO si todos los procesos que lo están utilizando lo han cerrado con el servicio close

• Leer de una tubería– int read(fildes[0], buffer, n);– Busca el bloque o los bloques del archivo especificado por descriptor

TuberíasTuberías POSIX IIIPOSIX III

(descriptor de lectura del pipe o descriptor del FIFO), transfiere el número de datos n_bytes que se desean leer de la tubería al buffer de memoria buf y actualiza el puntero

– No bloquea al proceso si está vacía la tubería y sin escritores– En caso de éxito devuelve el número de datos leídos. Si no, -1

• Escribir en una tubería– int write(fildes[1], buffer, n);int write(fildes[1], buffer, n);– Busca el bloque o los bloques del archivo especificado por descriptor

(descriptor de escritura del pipe o descriptor del FIFO), transfiere el número de datos n_bytes que se desean escribir desde el buffer de memoria buf a la tubería y actualiza el puntero

– Si no hay lectores, el SO envía la señal SIGPIPE al proceso– En caso de éxito devuelve el número de datos escritos. Si no, -1

26/01/2010

34

EjemploEjemplo con con tuberíastuberías POSIX.POSIX.RegiónRegión críticacrítica

#include <stdio.h>#include <unistd.h>

void main(void) {int fildes[2]; /* pipe para sincronizar */h /* t i i */char paso; /* caracter para sincronizar */

pipe(fildes);write(fildes[1], &paso, 1); /* necesario para entrar en la

seccion critica la primera vez */if (fork() == 0) { /* proceso hijo */

for(;;) {read(fildes[0], &paso, 1); /* entrada seccion critica */< Seccion critica >write(fildes[1], &paso, 1); /* salida seccion critica */

} }}

else { /* proceso padre */for(;;) {read(fildes[0], &paso, 1); /* entrada seccion critica */< seccion critica >write(fildes[1], &pao, 1); /* salida seccion critica */

}}

}

EjemploEjemplo con con tuberíastuberías POSIX.POSIX.ProductorProductor--ConsumidorConsumidor

#include <stdio.h>#include <unistd.h>

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));

}}}

else { /* proceso padre: consumidor */

for(;;) { read(fildes[0], &dato_c, sizeof(int)); /* consumir dato, lee un entero */}

}}

26/01/2010

35

EjemploEjemplo con con tuberíastuberías POSIX.POSIX.MandatoMandato ````lsls | | wcwc” I” I

/* programa que ejecuta el mandato ``ls | wc'' */

void main(void) {

int fd[2];pid_t pid;

ls wciif (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 de lectura; no lo utiliza */close(STDOUT_FILENO); /* cierra la salida estandar; libera el descriptor 1*/dup(fd[1]); /* duplica el pipe de escritura, se le asigna el 1 */close(fd[1]); /* cierra el pipe de escritura de la tubería */

ls wcpipe

close(fd[1]); /* cierra el pipe de escritura de la tubería */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; libera el descrip. 0 */dup(fd[0]); /* duplica el pipe de lectura, se le asigna el 0 */close(fd[0]); /* cierra el pipe de lecture de la tubería */execlp(``wc'',``wc'',NULL);perror(``execlp'');}

}

EjemploEjemplo con con tuberíastuberías POSIX.POSIX.MandatoMandato ````lsls | | wcwc” II” II

STDINSTDOUT

pipe(fd)

26/01/2010

36

EjemploEjemplo con con tuberíastuberías POSIX.POSIX.MandatoMandato ````lsls | | wcwc” II” II

STDINSTDOUT

pipe(fd) fork()STDINSTDOUTfd(0)fd(1)

pipe

EjemploEjemplo con con tuberíastuberías POSIX.POSIX.MandatoMandato ````lsls | | wcwc” II” II

STDINSTDOUT

pipe(fd) fork()STDINSTDOUTfd(0)fd(1)

pipe

STDINSTDOUTfd(0)fd(1)

STDINSTDOUTfd(0)fd(1)

pipeclose(1); dup(fd[1]); close(fd[1]);

26/01/2010

37

EjemploEjemplo con con tuberíastuberías POSIX.POSIX.MandatoMandato ````lsls | | wcwc” II” II

STDINSTDOUT

pipe(fd) fork()STDINSTDOUTfd(0)fd(1)

pipe

STDINSTDOUTfd(0)fd(1)

STDINSTDOUTfd(0)fd(1)

pipeclose(1); dup(fd[1]); close(fd[1]);

STDINSTDOUTfd(0)fd(1)

STDINSTDOUTfd(0)fd(1)

pipeclose(fd[0]);

EjemploEjemplo con con tuberíastuberías POSIX.POSIX.MandatoMandato ````lsls | | wcwc” II” II

STDINSTDOUT

pipe(fd) fork()STDINSTDOUTfd(0)fd(1)

pipe

STDINSTDOUTfd(0)fd(1)

STDINSTDOUTfd(0)fd(1)

pipeclose(1); dup(fd[1]); close(fd[1]);

STDINSTDOUTfd(0)fd(1)

STDINSTDOUTfd(0)fd(1)

pipeclose(fd[0]);

STDINSTDOUT

STDINSTDOUTi

close(0); dup(fd[0]); close(fd[0]);STDOUTfd(0)fd(1)

STDOUTfd(0)fd(1)

pipe

26/01/2010

38

EjemploEjemplo con con tuberíastuberías POSIX.POSIX.MandatoMandato ````lsls | | wcwc” II” II

STDINSTDOUT

pipe(fd) fork()STDINSTDOUTfd(0)fd(1)

pipe

STDINSTDOUTfd(0)fd(1)

STDINSTDOUTfd(0)fd(1)

pipeclose(1); dup(fd[1]); close(fd[1]);

STDINSTDOUTfd(0)fd(1)

STDINSTDOUTfd(0)fd(1)

pipeclose(fd[0]);

STDINSTDOUT

STDINSTDOUTi

close(0); dup(fd[0]); close(fd[0]);STDOUTfd(0)fd(1)

STDOUTfd(0)fd(1)

pipe

STDINSTDOUTfd(0)fd(1)

STDINSTDOUTfd(0)fd(1)

pipe

close(fd[1])

exec(ls); exec(wc); 

EjemploEjemplo con con tuberíastuberías POSIX.POSIX.MandatoMandato ````lsls | | wcwc” II” II

STDINSTDOUT

pipe(fd) fork()STDINSTDOUTfd(0)fd(1)

pipe

STDINSTDOUTfd(0)fd(1)

STDINSTDOUTfd(0)fd(1)

pipeclose(1); dup(fd[1]); close(fd[1]);

STDINSTDOUTfd(0)fd(1)

STDINSTDOUTfd(0)fd(1)

pipeclose(fd[0]);

STDINSTDOUT

STDINSTDOUTi

close(1); dup(fd[1]); 

close(1); dup(fd[1]); close(fd[1]);

ls wcpipe

STDOUTfd(0)fd(1)

STDOUTfd(0)fd(1)

pipe

STDINSTDOUTfd(0)fd(1)

STDINSTDOUTfd(0)fd(1)

pipeclose(fd[1]);

26/01/2010

39

• Tipos de semáforos:– Semáforos sin nombre: 

• Permiten sinchronizar los threads dentro de un proceso.

SemáforosSemáforos POSIX IPOSIX I

• Se pueden usar parar sincronizar el proceso que los crea y los procesos que lo heredan (proceso hijos).

– Semáforos con nombre: • El semáro tiene un nombre; sigue la convención de nombres en ficheros.

• Los procesos que se sincronizan no tienen que estar sincronizados.

P i i l i i POSIX ti• Principales servicios POSIX para gestionar semáforos:– Inicializar/destruir– Abrir/cerrar– Wait/signal

• Inicializa un semáforo sin nombre – int sem_init(sem_t *sem, int shared, int val);– Crea e inicializa un semáforo sin nombre. Todos los semáforos deben inicializarse antes de usarse.– El parámetro shrared indica si el semáforo sicncroniza threads (shared =0) o procesos emparentados

(shared<>0).

• Destruye un semáforo sin nombre – int sem_destroy(sem_t *sem);

D t áf i b i t d i it

SemáforosSemáforos POSIX II POSIX II

– Destruye un semáforo sin nombre, previamente creado con sem_init.

• Abre (crea) un semáforo con nombre. – sem_t *sem_open(char *name, int flag);– sem_t *sem_open(char *name, int flag, mode_t mode,int val);– Abre un semáforo con nombre; si no existe, lo crea.– El parámetro flag indica si se accede a un semáforo previamente creado (flag=0) . – Si el semáfor se crea, se especifícan los permisos (parám mode) y el valor inicial (parám val).

• Cierra un semáforo con nombre – int sem_close(sem_t *sem);– Cierra un semáforo con nombre, rompiendo la asociación que tenía un proceso con un semáforo.

• Destruye un semáforo sin nombreDestruye un semáforo sin nombre – int sem_unlink(char *name);– Elimina del sistema un semáforo con nombre, se postpone la destrucción del semáforo hasta que

todos los procesos que lo estén utilizando lo hayan cerrado con sem_close.

• Realiza la operación wait sobre un semáforo– int sem_wait(sem_t *sem);

• Realiza la operación signal sobre un semáforo– int sem_post(sem_t *sem);

26/01/2010

40

SemáforosSemáforos POSIX.POSIX.ProductorProductor--ConsumidorConsumidor II

#include <pthread.h>#include <semaphore.h>

#define MAX_BUFFER 1024 /* tamanio del buffer */#define DATOS_A_PRODUCIR 100000 /* datos a producir */

t l t /* l t l b ff */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); /* crear los procesos ligeros */th d t (&th1 NULL P d t NULL)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);

}

SemáforosSemáforos POSIX.POSIX.ProductorProductor--ConsumidorConsumidor IIII

void Productor(void) {

int pos = 0; /* posicion dentro del buffer */int i; /* dato a producir */

for(i=0; i < DATOS_A_PRODUCIR; i++ ) {sem_wait(&huecos); /* un hueco menos */buffer[pos] = i;pos = (pos + 1) % MAX_BUFFER;sem_post(&elementos); /* un elemento mas */

}pthread_exit(0);

}

void Consumidor(void){

int pos = 0;int dato;int i;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);

}

26/01/2010

41

SemáforosSemáforos POSIX.POSIX.LectoresLectores--escritoresescritores II

#include <pthread.h>#include <semaphore.h>

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 */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); h d j i ( h1 )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);}

SemáforosSemáforos POSIX.POSIX.LectoresLectores--escritoresescritores IIII

void Lector(void) {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);

}}

void Escritor(void) { sem_wait(&mutex);

dato = dato + 2; /* modificar el recurso */sem_post(&mutex);

pthread_exit(0);}

26/01/2010

42

• Mecanismo de sincronización de hilos

• Permite acceso exclusivo a recursos compartidos

MutexMutex POSIX IPOSIX I

• Se pueden realizar dos operaciones atómicas– lock: 

• Intenta obtener el mutex. Si ya está adquirido, se bloquea.

– unlock: • Desbloquea el mutex. Si hay threads bloqueados el, desbloquea uno.

• Principales servicios POSIX para gestionar semáforos:– Inicializar/destruir– Abrir/cerrar– lock/unlock

• int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *attr);

MutexMutex POSIX IIPOSIX II

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

26/01/2010

43

MutexMutex POSIX.POSIX.LectoresLectores--escritoresescritores II

#include <pthread.h>

int dato = 5; /* recurso */int n_lectores = 0; /* numero de lectores */pthread_mutex_t mutex_lec; /* controlar el acceso n_lectores */pthread_mutex_t mutex; /* controlar el acceso a dato */

void main(void){

pthread_t th1, th2, th3, th4;

pthread_mutex_init(&mutex, NULL);pthread_mutex_init(&mutex_lec, 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); pthread_join(th1, NULL);pthread_join(th2, NULL);pthread_join(th3, NULL);pthread_join(th4, NULL);

/* cerrar todos los semaforos */pthread_mutex_destroy(&mutex);pthread_mutex_destroy(&mutex_lec);

exit(0);}

MutexMutex POSIX.POSIX.LectoresLectores--escritoresescritores IIII

void Lector(void) {pthread_mutex_lock(&mutex_lec);n_lectores = n_lectores + 1;if (n_lectores == 1)

pthread_mutex_lock(&mutex);pthread_mutex_unlock(&mutex_lec);

printf(``%d\n'', dato); /* leer dato */

pthread_mutex_lock(&mutex_lec);n_lectores = n_lectores - 1;

if (n_lectores == 0)pthread_mutex_ulock(&mutex);

pthread_mutex_unlock(&mutex_lec);pthread_exit(0);

}}

void Escritor(void) { pthread_mutex_lock(&mutex);

dato = dato + 2; /* modificar el recurso */pthread_mutex_unlock(&mutex);

pthread_exit(0);}

26/01/2010

44

Variables Variables condicionalescondicionales POSIX IPOSIX I

• Variables de sincronización asociadas a un mutex (se utiliza como monitor)mutex (se utiliza como monitor)

• Conveniente ejecutarlas entre lock y unlock

• Dos operaciones atómicas: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

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

Variables Variables condicionalescondicionales POSIX IIPOSIX II

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 esperandoNo 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 condicionalcond.

– Automáticamente se libera el mutex. Cuando se despierta el proceso ligerovuelve a competir por el mutex. 

26/01/2010

45

• Thread Alock(mutex); /* acceso al recurso */comprobar las estructuras de datos;

Variables Variables condicionalescondicionales POSIX IIIPOSIX III

while (recurso ocupado)wait(condition, mutex); /* recurso como ocupado*/

unlock(mutex);

• Thread B lock(mutex); /* acceso al recurso */

…signal(condition, mutex); /* liberar recurso */ unlock(mutex);

• Importante utilizar while

#include <pthread.h>#include <mutex.h>

#define MAX_BUFFER 1024 /* tamanio del buffer */

Variables Variables condicionalescondicionales POSIX.POSIX.ProductorProductor--consumidorconsumidor II

_#define DATOS_A_PRODUCIR 100000 /* datos a producir */

int buffer[MAX_BUFFER]; /* buffer comun */pthread_mutex_t mutex; /* mutex para controlar el monitor */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 */

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);

26/01/2010

46

pthread_create(&th1, NULL, Productor, NULL);pthread_create(&th2, NULL, Consumidor, NULL);

Variables Variables condicionalescondicionales POSIX.POSIX.ProductorProductor--consumidorconsumidor IIII

pthread_join(th1, NULL);pthread_join(th2, NULL);

pthread_mutex_destroy(&mutex);pthread_cond_destroy(&no_lleno);pthread_cond_destroy(&no_vacio);

exit(0);}

void Productor(void) { /* codigo del productor */int dato, i ,pos = 0;

Variables Variables condicionalescondicionales POSIX.POSIX.ProductorProductor--consumidorconsumidor IIIIII

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 ++;th d d i l( i ) /* b ff i */pthread_cond_signal(&no_vacio); /* buffer no vacio */

pthread_mutex_unlock(&mutex);}pthread_exit(0);

}

26/01/2010

47

void Consumidor(void) { /* codigo del sonsumidor */int dato, i ,pos = 0;

for(i=0; i < DATOS A PRODUCIR; i++ ) {

Variables Variables condicionalescondicionales POSIX.POSIX.ProductorProductor--consumidorconsumidor IVIV

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);pthread_mutex_unlock(&mutex);printf("Consume %d \n", dato); /* consume dato */

}pthread_exit(0);

}

#include <pthread.h>#include <mutex.h>

int dato = 5; /* recurso */

Variables Variables condicionalescondicionales POSIX.POSIX.LectoresLectores--escritoresescritores II

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);

26/01/2010

48

pthread_join(th1, NULL);pthread_join(th2, NULL);pthread_join(th3, NULL);pthread_join(th4, NULL);

Variables Variables condicionalescondicionales POSIX.POSIX.LectoresLectores--escritoresescritores IIII

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);

}

void Lector(void) { /* codigo del lector */pthread_mutex_lock(&mutex_lectores);n_lectores++;if (n lectores == 1)

Variables Variables condicionalescondicionales POSIX.POSIX.LectoresLectores--escritoresescritores IIIIII

( _ )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);}

26/01/2010

49

• mqd_t mq_open(char *name, int flag, mode_t mode, mq_attr *attr);

Crea una cola de mensajes con nombre y atributos attr:

Colas de Colas de mensajesmensajes POSIX IPOSIX I

– 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.Cierra una cola de mensajes. 

• int mq_unlink(char *name);

– Borra una cola de mensajes. 

• int mq_send(mqd_t mqdes, char *msg, size_t len, int prio);

E í l j d l i d l l l d

Colas de Colas de mensajesmensajes POSIX IIPOSIX II

– 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);p

– Recibe un mensaje msg de longitud len de la cola de mensajes mqdes con prioridad prio; 

– Recepción bloqueante o no. 

26/01/2010

50

void main(void){

mqd_t mutex; /* para sincronizar la seccion critica */

Colas de Colas de mensajesmensajes POSIX.POSIX.RegiónRegión críticacrítica II

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); /* entrar en la seccioncritica la primera vez */

if (fork() == 0) { /* proceso hijo */for(;;) {

mq receive(mutex, &c, 1, 0); /* entrada seccion critica */

Colas de Colas de mensajesmensajes POSIX.POSIX.RegiónRegión críticacrítica IIII

q_/* 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 */

}}

}

26/01/2010

51

#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 */oid main( oid)

Colas de Colas de mensajesmensajes POSIX.POSIX.ProductorProductor--consumidorconsumidor II

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);

}}

if (fork() == 0) /* proceso hijo */Productor();

else /* proceso padre */Consumidor();

exit(0);}

void Productor(void) {

int dato, i;i 0 i i

Colas de Colas de mensajesmensajes POSIX.POSIX.ProductorProductor--consumidorconsumidor IIII

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;

}

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;

}