tema 5: comunicacióncomunicación y y …dsa-research.org/teresa/so/clases/com y sim.pdf26/01/2010...
TRANSCRIPT
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;
}