Semaforo 1

Descargar como txt, pdf o txt
Descargar como txt, pdf o txt
Está en la página 1de 3

#include <stdio.

h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>

void semOp(int, int);


int semCreate(key_t, int);
int semOpen(key_t);
void semRm(int);
void semClose(int);
void semWait(int);
void semSignal(int);

#define BIGCOUNT 10000 /*Valor incial para el contador de procesos*/

/*Define los arrays de operaciones del semaforo para llamadas de semOp()*/

static struct sembuf op_lock[2]={


2,0,0, /*espera para [2] (bloqueo) sea igual a 0 despues incremente [2] en 1-
esto lo bloquea*/
2,1, SEM_UNDO /*UNDO para liberar el bloqueo si el proceso sale antes de
desbloquear explic�tamente*/
};

static struct sembuf op_endcreate[2]={


1,-1,SEM_UNDO, /*decrementa [1] (contador de procesos) con undo en caso de
finalizar*/

/*UNDO para ajustar el contador de procesos en caso de acabar antes de llamar


explicitamente a semClose()*/
2,-1, SEM_UNDO /*despu�s decrementa [2] (bloqueo) de vuelta a 0*/
};

static struct sembuf op_open[1]={


1,-1,SEM_UNDO /*decrementa [1] (contador de proceso) con undo en caso de
finalizar*/
};

static struct sembuf op_close[3]={


2,0,0, /*espera hasta que [2] (bloqueo) sea igual a 0*/
2,1, SEM_UNDO, /*despues incrementa [2] en 1 - esto lo bloquea*/
1,1, SEM_UNDO /*despu�s incrementa [1] (contador de procesos)*/
};

static struct sembuf op_unlock[1]={


2,-1, SEM_UNDO /*decrementa [2] (bloqueo) de vuelta a 0*/
};

static struct sembuf op_op[1]={


0,99, SEM_UNDO /*decrementa o incrementa [0] con undo en caso de finalizar*/
/*el 99 se sustituye con la cantidad real que hay que sustraer (positiva o
negativa)*/
};

/** Crea un semaforo con un valor inicial especificado


* Si el semaforo eiste, no se inicializa (por supues);
*Se devuelve la identidad del semaforo si todo va bien, sino -1
**/

int semCreate(key_t key, int initval){


register int id, semval;
union semun {
int val;
struct semid_ds *buf;
ushort *array;
}semctl_arg;

if(key == IPC_PRIVATE)
return(-1); /*no utilizable para semaforos privados*/
else if (key ==(key_t)-1)
return(-1); /*probablemente una llamada erronea anterior a ftok()*/

deNuevo:
if((id = semget(key, 3, 0666 | IPC_CREAT))<0)
return(-1); /*problemas de permisos o tablas llenas*/
/*Cuando se crea el semaforo, sabemos que el valor de todos los miembros es 0
* Bloquear el semaforo esperando a que [2] sea 0, e incrementarlo.
* Hay una condicion de carrera: Cabe la posibilidad que entre el semget() de
arriba y el sempo() de abajo, otro proceso puede llamar a semClose() que puede
borrar el semaforo si el ultimo lo esta usando
* Adem�s, se maneja la conidci�n de error sobre el identificador
* Si esto ocurre, se vuelete atras y se intenta crea de nuevo
*/

if(semop(id,&op_lock[0],2)<0){
if(errno==EINVAL)
goto deNuevo;
fprint(stderr, "semCreate: no puede bloquear \n");
}

/*Obtener el valor del contador de procesos. Si es igual a 0, entonces


nignuno ha inicializado el semaforo aun*/

if((semval = semctl(id,1,GETVAL,0))<0)
fprintf(stderr, "semCreate; no puedo realizar GETVAL\n");

if(semval ==0){
/*vPodriamos inicializar SETALL, pero podr�a borrar el ajuste del valor que
se realizo cuando se bloqueo el semaforo antes. En su lugar, se hacen dos llamadas
al sistema para inicializar [0] y [1]
*
*/

semctl_arg.val=initval;
if( semctl(id, 0, SETVAL, semctl_arg)<0 )
fprintf(stderr, "semCreate: puedo SETVAL[0]\n");

semctl_arg.val=BIGCOUNT;

if( semctl(id, 1, SETVAL, semctl_arg)<0 )


fprintf(stderr, "semCreate: puedo SETVAL[1]\n");

}
/*Decrementar el contador de procesos y desbloquer*/

if(semop(id, &op_endcreate[0], 2)<0)


fprintf(stderr, "semCreate: no puedo acabar semCreative()\n");

return(id);
}

/*abre un semaforo que debe existir ya


*esta funcion deberia usarse, envez de semCreate(), si en la llamada
*se sabe que el semaforo deberia ya existir. Por ejemplo un cliente
* de un par cliente-servidor podria utilizarla, si es responsabilidad del servidor
crear el semaforo
* se vuelve la identidad del semaforo si va bine, sino -1*/

int semOpen(key_t key){


register int id;

if(key == IPC_PRIVATE)
return(-1); /*no utilizable para semaforos privador*/

else if (key == (key_t)-1)


return(-1) /*probablemente una llamada erronea anterior a ftok()*/

if((id=semget(key,3,0))<0)
retunr(-1) /*no existe o las tablas est�n llenas*/

/*Decre,emta el contador de provesos. No necesitamos un bloque para esto*/


if(semop(id,&op_open[0],1)<0)
fprintf(stderr, "semOpem: no puedo abrir\n");

return(id);
}

También podría gustarte