You are on page 1of 11

Laboratorio de Sistemas Operativos

SESIN N 14 Pgina: 1

P S M
ROGRAMACIN DE EMAFOROS Y UTEX

EN C

I
OBJETIVOS

Conocer y aplicarforlos conceptosymutexendeLinuxmecanismos de sincronizacin para hilos.

Programar sem
Realizar ejercicios.
II
TEMAS A TRATAR
Semforos

Mutex n Ejemplos de
programaci
III
MARCO TEORICO

Semforos
Los semforos es un mecanismo de los sistemas operativos cuyo objetivo es evitar los
interbloqueos y abrazos mortales de los procesos. Tambin son utilizados para resolver
problemas de sincronizacin.
Para utilizar los semforos en un programa, deben seguirse los siguientes pasos:
Obtener una clave de semforo. Esta clave se trata de una clave para un recurso
compartido, y se utiliza la funcin ftok para este propsito. Esta funcin tambin
se utiliza para la memoria compartida y las colas de mensajes. Su sintaxis
es: key_t ftok(char *, int)
metro es el nombre y la ruta de un archivo cualquiera.
El primermetro pares un n Y el segundo par mero cualquiera. Todos los procesos quemeroquieran.
compartir el
sem foro deben suministrar el mismo archivo y el mismo n

Obtener un arreglo de semforos. Lo hacemos con la funcin.


int semget(key_ t, int, int)

El primer parmetro es la clave obtenida en el paso anterior, el segundo parmetro


es el nmero de semforos que contendr el arreglo y el tercer parmetro son
algunos flags los cuales permiten poner permisos de acceso al semforo (es
similar a los ficheros) de lectura, escritura para el usuario, grupo y otros. As
mismo, lleva unos modificadores para la obtencin de los semforos.
Ms.Sc. Karim Guevara Puente de la Vega Sesin 14
Laboratorio de Sistemas Operativos Pgina: 2

Por ejemplo, nosotros pondremos 0600 | IPC_CREATEforos sequecrearnindica


sinopermisoexistende lectura y escritura para el propisegmetarion(). y que los sem
al momento de invocar a Es importante meroen colocarunformatoel0octaldelante. del 600 para que el compilador
del C interprete el n
La funcin semget() nos devuelve un identificador al arreglo de semforos.

Inicializacin del semforo. Uno de losnprocesos. que compartan el


semforo debe inicializarlo. Para esto utiliza la funci
int semctl(int, int, int, int)
metro foros
en el
donde el primer par es el identificador ndice deldel semforoarreglodeensemel arregloobtenidoelcual
paso anterior, el segundo esel queremos
lohemos pedido uno, este parmetro es 0). El tercer metro
i icializar (si s par
in dicaqu queremos hacer con el semforo. Por ejemplo, si ponemos metro podra ser un
SETVAL
entero, significa
pero que en queremos inicializarlo
r alidad un .Entonces,
es n. t po de Elcuartosipar
unieste parmetro es 1
foroel sem
estar en verde y s i le ponemos 0 es que queremos un
semforo en rojo.
n, est se debe de definir de forma expl
Si vamos a trabajar con la uni man s detalle). cita en los programas que vayamos a hacer
(ver el para m

Utilizar el semforo. Hasta este punto ya est todo preparado, solo falta que los
procesos lo consuman. El oc s que qui ra acced r al recurso comn (puede ser
una seccin crtica) debe primero decrementar el semforo. Para esto se utilizar
la funcin:
int semop(int, struct sembuf *, size_ t)
el primer parmetro es el identificador del arreglo de semforos, el segundo
ndica las operaciones que se realizarn en el semforo. El tercer parmetro es el
nmero de elementos del arreglo, en nuestro ejemplo ser 1.
La estructura del segundo parmetro struct sembuf contiene los siguientes
campos:
o short sem_num que es el ndice del arreglo de semforos sobre el cual
queremos hacer algo. Si es un solo semforo este valor ser 0.
o short sem_op es el valor en el que queremos decrementar el semforo (-1).
o short sem_flg son los flags que afectan a la operacin. Nosotros
pondremos 0.

Si al realizar esta operacin el semforo se vuelve negativo, el proceso se quedar


bloqueado hasta que algn otro proceso lo incremente y lo ponga como mnimo
en 0.
Cuando el procesforo. termineLafuncindeutilizarquese
valor del sem
elutilizarrecursoparacompartido,estaaccinestees ladebemismadeincrementarsemop, el
con la
1 en el campo sem_op diferencia que se pondr de la estructura vista anteriormente.

Para trabajar conas semforos es necesario que en nuestros programas incluyamos las
siguientes librer :

Ms.Sc. Karim Guevara Puente de la Vega Sesin 14


Laboratorio de Sistemas Operativos Pgina: 3

sys/ipc.h
sys/sem.h

Ejemplo: a continuacin se tienen dos programas semforo_1.c y semforo_2.c. Cada

uno de estos programas debe ser ejecutado en un terminalforodiferente. para ver como sus
ejecuciones son sincronizadas a partir del uso de un sem
/*Nombre: semaforo_1.c*/

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdlib.h>
union semun
{
int val;
struct semid_ds *buf;
unsigned short int *array;
struct seminfo *_buf;
};
main()
{
key_t clave; int
idSemaforo;

struct sembuf operacion;


union semun arg;
int i=0;

clave = ftok(/bin/ls,33);
if (clave == (key_t)-1)
{
printf(No puedo conseguir la clave de semaforo\n);
exit(0);
}
idSemaforo=semget(clave,10,0600|IPC_CREATE);
if (idSemaforo == -1)
{
printf(No puedo crear el

semaforo\n); } exit(0);
arg.val = 0;
semctl(idSemaforo,0,SETVAL,&arg);
operacion.sem_num = 0;
operacion.sem_op = -1;
operacion.sem_flg = 0;
while(1)
{
printf(Esperando semaforo %d\n,i);
semop(idSemaforo,&operacion,1);
printf(Salgo del semaforo

%d\n,i); } } i++;

Ms.Sc. Karim Guevara Puente de la Vega Sesin 14


Laboratorio de Sistemas Operativos Pgina: 4

/*Nombre: semaforo_2.c*/

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdlib.h>
union semun
{
int val;
struct semid_ds *buf;
unsigned short int *array;
struct seminfo *_buf;
};
main()
{
key_t clave; int
idSemaforo;

struct sembuf operacion;


union semun arg;
int i=0;

clave = ftok(/bin/ls,33);
if (clave == (key_t)-1)
{
printf(No puedo conseguir la clave de
semaforo\n); } exit(0);
idSemaforo=semget(clave,10,0600|IPC_CREATE);
if (idSemaforo == -1)
{
printf(No puedo crear el

semaforo\n); } exit(0);
operacion.sem_num = 0;
operacion.sem_op = 1;
operacion.sem_flg = 0;
for(i=0; i<10; i++)
{
printf(Levanto semaforo\n);
semop(idSemaforo,&operacion,1);

} } sleep(1);

Mutex
Los semforos vistos en la primera parte d esta sesin nos permiten comunicar proc sos.
Los mutex son un tipo de semforos que permite la comunicacin entre hilos de un
proceso.
Un mutex (EXclusin MUTua) consiste en una especie de semforo binario con dos
estados, cerrado y no cerrado. Un mutex es un objeto que permite a los hilos asegurar la
integridad de un recurso compartido al que tienen acceso. Tiene dos dos estados:
bloqueado y desbloqueado.
Sobre un mutex se pueden realizar las siguientes operaciones:

Ms.Sc. Karim Guevara Puente de la Vega Sesin 14


Laboratorio de Sistemas Operativos Pgina: 5

lock: inte ta cerrar el mutex. Si el mutex no est cerrado, se cierra, todo ello en
una accin atmica. Si el mutex est cerrado, el hilo se bloquea. Si dos hilos
intentan cerrar el mutex al mismo tiempo, cosa que slo puede pasar en un
multiprocesador real, uno de ellos lo consigue y el otro no, bloquendose. La
forma de regular esto depende de la implementacin.
Unlock: elimina o libera el cierre del mutex. Si existe uno o ms hilos esperando
por el mutex, se desbloquea exactamente uno, y el resto permanece bloqueado a
la espera.
Antes de que un hilo desee acceder a un recurso compartido, el hilo debe bloquear un
mutex. Si el mutex no ha sido bloqueado antes por otro hilo, el bloqueo es realizado. Si el
mutex ha sido bloqueado antes, el hilo es puesto a la espera. Tan pronto como el mutex
es liberado, unoedesulosejecucihilosen, esperaadquiriendoacausael debloqueounbloqueo. en el mutex es
seleccionado para que contin
Un ejemplo de utilizaci
n de un mutex es aqul en el que un hilo A y otro B estn
pico, como puede ser una variable global
compartiendo un recurso t . El hilo A bloquea el mutex, con lo que obtiene el acceso a
la variable. Cuando el hilo B intenta bloquear el mutex, el hilo B es puesto a la espera
ya que el mutex ya ha sido bloqueado antes.
Cuando el hilo A finaliza el acceso laejecucinalavariabledquiriendoglobal, eldesbloqueabloqueo,
pudiendoelmutex.entoncesCuando esto sucede, el hilo B continuar
acceder a la variable.
Hilo A: Hilo B:
lock(mutex) lock(mutex)
acceso al recurso acceso al recurso
unlock(mutex) unlock(mutex)

n mutua entre
Un hilo puede adquirir un mutex nogarantizada,bloqueado. hastaDeestaqueforma,el mutexlaexclusies
hilos del mismo proceso est
desbloqueado ticas con el mismo mutex. Si un hilo permitiendo que otros hilos
intenta bloquear un mutex que ya est
protejan seccionesbloqueado,cr el hilo se suspende. Si un hilo n
esperando por el mutex, el hilo en espera con desbloquea un mutex y otroselmutexhilos. est
mayor prioridad obtendr
La siguientes son algunas funciones que nos van a permitir gestionar los mutex.
int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexaddr_t *attr);

Descripcin: permite inicial una variable de tipo mutex.


Donde. mutex: variable de tipo mutex.
attr:

especifica los atributos con los que se crear el mutex inicialmente, en caso
de que este argumento sea NULL, se tomaran los atributos por defecto.

int pthread_mutex_destroy(pthread_mutex_t *mutex);

Descripcin: permite destruir un objeto de tipo mutex

int pthread_mutex_lock(pthread_mutex_t *mutex);

Descripcin: corresponde con la operacin lock. Intenta obtener el mutex. Si el mutex ya


se encuentra adquirido por otro hilo, el proceso ligero que ejecuta la llamada se bloquea.

Ms.Sc. Karim Guevara Puente de la Vega Sesin 14


Laboratorio de Sistemas Operativos Pgina: 6

int pthread_mutex_unlock(pthread_mutex_t *mutex);

Descripcin: corresponde con la operacin unlock y permite el proceso ligero que la


ejecuta liberar el mutex.
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *attr);

Descripcin: esta funcin inicia una variable de tipo condicional.

attr especifica los atributos con los que se crear inicialmente la variable
condicional, en caso de que este argumento sea NULL, se tomar n los
atributos por defecto.
int pthread_cond_destroy(pthread_cond_t *cond, pthread_condattr_t *attr);

Descripcin: permite destruir una variable de tipo condicional.

int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);

Descripcin: n c_signal suspende al proceso ligero hasta que otro proceso ejecute

una operacimica sobre la variable condicional pasada como primer argumento. De forma at a
se libera el mutex pasado como argumento. Cuando el proceso se despierta volver
competir por el mutex.
int pthread_cond_signal(pthread_cond_t *cond);

Descripcin: desbloquea a nun. Estaprocesofuncinsuspendidonotiene


enfectola.variable condicional pasada como argumento a esta funci
int pthread_cond_broadcast(pthread_cond_t *cond);

Descripcin: esta funcin desbloquea a todos los procesos ligeros suspendidos en una
variable condicional.

Ejemplo:
Vamos a hacer un programa en el que dos hilos esperan uno al temsotro paradel
arregloaccederconalosel datos de un arreglo de enteros. Uno de los hilos pone s ctodosn2 ylosas
sucesivamente. El otro valor 0, luego los rellena todos con el valor 1, despu n 0, es decir que
todos sean hilo verifica que todos los valoresunseanerroriguales. al de la posici
iguales, de lo contrario mostrar
Si no n tipo de sincronizacin en cuanto al acceso a la estructura compartida, es
hayning
cil notar que el hilo que escribe no haya terminado y em
f piece a leer el otro hilo, dando errores ya que no todos los valores del arreglo son
iguales.
La versin del programa sin mecanismo de sincronizacin sera:

//Programa hilos3.c
#include <pthread.h>
void *funcionThread(void *parametro)

#define TAMANO_BUFFER 1000


int bufer[TAMANO_BUFFER];
//pthread_mutex_t mutexBuffer;

Ms.Sc. Karim Guevara Puente de la Vega Sesin 14


Laboratorio de Sistemas Operativos Pgina: 7

printf(Hijo: Correcto\n);

main()
{ pthread_t idHilo;

int error;
int contador;
int i;
// pthread_mutex_init(&mutexBuffer,NULL);
error=pthread_create(&idHilo,NULL,funcionThread,NULL);

if (error!=0)
{ perror(No puedo crear thread..);

} exit(-1);

while(1)
{ pthread_mutex_lock(&mutexBuffer);
//
for(i=0;i<TAMANO_BUFFER;i++)
buffer[i]=contador;
// pthread_mutex_unlock(&mutexBuffer);

}contador++;
}
void *funcionThread(void *parametro)
{
int i;
elementoDist=0;
while(1)
{
/ pthread_mutex_lock(&mutexBuffer);

for(i=0;i<TAMANO_BUFFER;i++)
{
if (buffer[0]!=buffer[i])
{
elementoDist=1;
break;

}
}

if (elementoDist)
printf(Hijo: Error. Elementos distintos en
el buffer\n);
else

//pthread_mutex_unlock(&mutexBuffer);
}
}

Ms.Sc. Karim Guevara Puente de la Vega Sesin 14


Laboratorio de Sistemas Operativos Pgina: 8

IV
ACTIVIDADES
Desarrollar en laboratorio los siguientes ejercicios
Realice la escritura, compilacin y ejecucin de los siguientes programas:
01. Modifiqunse mop()losprogramas semforo_1.c y semforo_2.c, ya que las llamadas a la funci
son bastanteespera_semaforo()"engorrosas" porelevaaquello_semaforo()derellenar la
escriba las funciones y
estructura, digo. a pasar el identificador del
querealicen est
semforo yelndic e c Sugerencia: se leforospodr.
dentro del arreglo de sem

02. Escriba el siguiente programa, y luego ejectelo. Describa que es lo que realiza.
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
void *funcion01(void *arg)
{ int i;

for(i=0;i<20;i++)
{ printf(.);

fflush(stdout);
} sleep(1);

} return NULL;

void *funcion02(void *arg)


{ int i;

for(i=0;i<20;i++)
{ printf(o);

fflush(stdout);
} sleep(1);

} return NULL;

void *funcion03(void *arg)


{ int i;

for(i=0;i<20;i++)
{ printf(+);

fflush(stdout);
} sleep(1);

} return NULL;

main()
{
pthread_t mihilo01, mihilo02, mihilo03;

int i;

Ms.Sc. Karim Guevara Puente de la Vega Sesin 14


Laboratorio de Sistemas Operativos Pgina: 9

if(pthread_create(&mihilo01,NULL,funcion01,NULL)
{
printf(Error creando el hilo.);

} abort();
if(pthread_create(&mihilo02,NULL,funcion02,NULL)
{
printf(Error creando el
hilo.); abort();
}
if(pthread_create(&mihilo03,NULL,funcion03,NULL)
{
printf(Error creando el

hilo.); } abort();

for(i=0;i<20;i++)
{
printf(x);
fflush(stdout);

} sleep(3);

} exit(0);

3. Modifiquenmain,elprogramapuedan anteriorimprimirparaen quepantcallda


procesolaserieligerode 20incluyendocaracteresla funci
correspondiente a cada uno de ellos sincronizadamente haciendo uso de Mutex.

04. Cul es la funcin del siguiente cdigo?. Explique.


#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
pthread_mutex_t sema1,sema2;
pthread_mutexattr_t semattr1,semattr2;
void *tarea1(void *arg){
while(1){
pthread_mutex_lock(&sema1);
printf(En tarea 1\n);
} pthread_mutex_unlock(&sema2);
}

void *tarea2(void *arg){


while(1){
pthread_mutex_lock(&sema2);
printf(En tarea 2\n);
} pthread_mutex_unlock(&sema1);
}

int main()
{
pthread_t tid1, tid2;
pthread_attr_t attr;
Ms.Sc. Karim Guevara Puente de la Vega Sesin 14
Laboratorio de Sistemas Operativos Pgina: 10

pthread_mutexattr_init(&semattr1);
pthread_mutexattr_init(&semattr2);
if(pthread_mutex_init(&sema1,&semattr1)==-1){
perror(El semaforo 1 no ha podido
inicializarse\n); } exit(1);
if(pthread_mutex_init(&sema2,&semattr2)==-1){
perror(El semaforo 2 no ha podido
inicializarse\n); } exit(1);
if(pthread_attr_init(&attr)==-1){

thread \n); perror(Error en inicializacion de los atributos de


un exit(1);
}

if(pthread_create(&tid1,&attr,tarea1,NULL)==-1)
{ perror(Error en la creacin del hilo 1 \n);

} exit(1);

if(pthread_create(&tid2,&attr,tarea2,NULL)==-1)
{ perror(Error en la creacin del hilo 2 \n);

} exit(1);

sleep(2);
printf(Salida del hilo

principal\n); } exit(0);

05. Elabore el programa del productor-consumidor con hilos.


06. Cierre el sistema

Ms.Sc. Karim Guevara Puente de la Vega Sesin 14

You might also like