16.2.05

Acceso a un recurso compartido

Saludos.

El siguinte código crea cuatro procesos hijos. Cada hijo incrementará una variable compartida en 5 unidades. Para garantizar la exclusión mútua sobre la variable compartida se utiliza un grupo de un semáforo que funciona como semáforo binario.

Hay que cabiar todas las " de los includes por mayor y menor excepto el include de sv.h.


/**
Implementa un semáforo binario
utilizando directamente las funciones del sistema
**/

#include "sv.h"

#include "stdio.h"
#include "wait.h>
#include "unistd.h"
#include "sys/types.h"

#include "sys/stat.h"
#include "sys/ipc.h"
#include "sys/sem.h"


// Incrementa en 5 la variable compartida
#define INC 5

void inc(int);


// Esta unión hay que declararla
union semun {
int val;
struct semid_ds *buf;
ushort *array;
};

int main() {
int c;
int hijos = 4;
pid_t pid;

int semaforo;
union semun arg;
int r;
// { semaforo, valor, banderas }
struct sembuf arriba = {0, 1, 0};
struct sembuf abajo = {0, -1, 0};


sv_init();
printf("Valor de inicio: %i\n", sv_val());

// Crear e inicializar un semaforo binario
// para garantizar la exclusion mutua.
semaforo = semget(42, 1, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR);
if (semaforo == -1) {
perror ("Error en la creación del semáforo - ");
return -1;
}

arg.val = 1;
r = semctl(semaforo, 0, SETVAL, arg);
if (r == -1) {
perror ("Error inicializando semáforo - ");
// Hay que eliminarlo.
return -1;
}


for (c = 0; c < hijos; c++) {
pid = fork();
if (pid == -1) {
perror("Error en fork - ");
exit(-1);
}
if (pid == 0) {

// Decrementar semaforo
r = semop(semaforo, &abajo, 1);
if (r == -1) {
perror("Error decrementando semáforo - ");
// Eliminar el semáforo
return -1;
}

inc(c);

// Incrementar semaforo
r = semop(semaforo, &arriba, 1);
if (r == -1) {
perror("Error incrementando semáforo - ");
// Es necesario eliminarlo
return -1;
}

exit(0);
}
}

while ( wait(NULL)!=-1 );

printf("-------------------------------\n");
printf("Valor esperado: %i\n", hijos * INC);
printf("Valor real: %i", sv_val());

// Borrar semaforo
r = semctl(semaforo, 0, IPC_RMID);
if (r == -1)
{
perror("Error elminando semáforo - ");
return -1;
}

sv_finish();
printf("\n");
}


//----------------------------
void inc(int id) {
int c;
int tmp;
for(c=0; c < INC; c++) {
tmp = sv_get();
if ( (id == 0) && (c < 2)) sleep(1);
tmp++;
sv_set(tmp);
}
}

No comments: