Hemos estado viendo cómo compartir variables entre procesos hijos, y dejamos un poco en el tintero la implementación de mutex en ese caso, esta vez, para implementar el mutex vamos a utilizar semáforos. Estos semáforos también tienen que ser variables compartidas para funcionar correctamente.
Los semáforos tendrá un funcionamiento peculiar. En principio, pensemos en ellos con los valores 1 y 0. Por tanto, si el semáforo vale 1, el semáforo está abierto y lo haremos 0, pero si vale 0, nos esperaremos hasta que valga 1 (al contrario que un while (semaforo==0); utilizando semáforos, será el sistema operativo el que active nuestro proceso cuando el semáforo vale 1 por lo que podemos utilizar los recursos del sistema para otra cosa mientras).
Aunque podemos ir más allá, el valor del semáforo (numérico) podrá ser cualquiera, pero siempre que éste sea positivo, el proceso no se bloqueará, pero sí se decrementará el valor; aunque si el valor es negativo, o cero, el valor se decrementa, pero el proceso se queda esperando un valor positivo.
Al fin y al cabo un mutex es un semáforo que sólo vale 1 y 0 (aunque situado estratégicamente para proteger una sección crítica).
Para utilizar los semáforos tenemos que tener en cuenta tres funciones básicas (hay algunas más):
- sem_init(semaforo, pshared, value): Inicializamos el semáforo, y le damos el valor value. pshared deberá ser 0 si queremos el semáforo entre threads, u otro valor si queremos el semáforo compartido entre procesos. En este caso, será 1
- sem_post(semaforo): Incrementa el semáforo, es lo que utilizamos cuando se libera el recurso
- sem_wait(semaforo): Decrementa el semáforo, y si su valor es menor que cero, bloquea el proceso hasta tener un valor mayor o igual a cero. Lo usamos para comprobar si el recurso está ocupado.
En el siguiente ejemplo incrementaremos un número, aunque para complicarlo un poco, este número vendrá dado por una cadena de caracteres, cada incremento debe hacerlo un proceso hijo diferente por lo que tienen que estar todos perfectamente sincronizados para hacerlo bien. El valor final de x debe ser 20. Por otro lado, se han introducido esperas aleatorias para simular un proceso pesado que tarda un tiempo variable, y así provocar la condición de carrera.
Podemos modificar el valor de la constante SEMAPHORES De 1 a 0 para ver cómo se comporta el código en cada caso.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <stdint.h> #include <sys/mman.h> #include <semaphore.h> #include <string.h> #define SEMAPHORES 1 int main() { char *x = mmap(NULL, sizeof(char)*10, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); strcpy(x, "0"); int i; int child; sem_t *semaforo = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); int temp; sem_init (semaforo, 1, 1); for (i=0; i<10; ++i) { child = fork(); if (child==0) { usleep(rand()%20000); if (SEMAPHORES) sem_wait(semaforo); printf("[%d] Trying to access the resource\n", getpid()); temp=atoi(x); printf("[%d] Using the resource\n", getpid()); temp++; sprintf(x, "%d", temp); if (SEMAPHORES) sem_post(semaforo); printf("[%d] Just used the resource\n", getpid()); usleep(rand()%20000); if (SEMAPHORES) sem_wait(semaforo); printf("[%d] Trying to access the resource\n", getpid()); temp=atoi(x); printf("[%d] Using the resource\n", getpid()); temp++; sprintf(x, "%d", temp); if (SEMAPHORES) sem_post(semaforo); printf("[%d] Just used the resource\n", getpid()); printf("[%d] EXITING\n", getpid()); exit(1); } } while (wait(NULL)>=0); printf("x is: %s\n", x); munmap(x, sizeof(int)); munmap(semaforo, sizeof(sem_t)); return 0; } |
Cada vez que un proceso vaya a acceder a nuestra sección crítica, lo pondrá en pantalla junto con su pid, por lo que podemos ver claramente si un proceso está utilizando el recurso y otro proceso también entra a utilizarlo. Finalmente se dirá el valor de x, que debe ser 20 y que en el ejemplo sin semáforos no siempre vale 20. (Puede que alguna vez lo haga bien, pero será casualidad.
Nota: Debemos compilar con soporte para pthread:
$ gcc -o example example.c -lpthread
Foto: Paul Albertella (Flickr) CC-by
Pingback: BlogESfera.com /
This is such awesome content i got to read after lot of time. Its so interesting as well as informative. I am sure everyone who read it got a lot to learn from it.Miles Morales Hooded Bomber Jacket
This is excellent article, thank you for the share! This is what I am looking for, hope in future you will continue sharing such an superb work.
Coat Blade Runner 2049
This post you’re sharing is excellent. I really like and value what you’ve done. I really read your post, and I appreciate you providing the very useful points you raised. connections game
Actually, it’s pretty good to see! Tiler Adelaide
Thanks for sharing! Tiler Adelaide
Thanks for letting us know! Tiler Wollongong
Excellent post! Concreters in Wollongong
Thanks for sharing this to public! Adelaide Landscaping
I visited Your blog and got a massive number of informative articles. I read many articles carefully and got the information that I had been looking for for a long time. Hope you will write such a helpful article in future. Thanks for writing.Tilers in Hobart
Very useful and informative post! Tiling Townsville
Very informative post! tiler melbourne
To be honest, I generally don’t read. But, this article caught my attention.digital marketing adelaide
I am really impressed with your writing style. Keep it up! Landscapers Canberra
Many thanks for sharing this! Adelaide Coolroom Hire
Thanks for sharing! Sliding Doors Adelaide
It’s so kind of you! Solar Panels Adelaide
Many many thanks to you! Cleaning Services Adelaide
What a great piece of article! seo adelaide
Very informative content. Thanks. tow truck wollongong
Please keep up the good work! drum lessons adelaide
Thanks for letting us know. Tiler Adelaide
I thik this is very helpfull post Canberra landscapers
Great Post! I learned a lot from this, Thank you! Canberra landscapers
Really nice article and helpful me Canberra landscapers
Nice article, waiting for your another Canberra landscapers
This is awesome! Nice share. Best Cymbals on a Budget
Such a great post! Landscaping Henley Beach
Thats what I was looking for! adelaide air conditioning
Good to know about this! tilers wollongong Warilla
This is really very nice blog and so informative Sydney Tiler