💾 Archived View for snowcode.ovh › fr › cours › os › processus › synchronisation.gmi captured on 2024-05-10 at 10:55:22. Gemini links have been rewritten to link to archived content
-=-=-=-=-=-=-
Lorsque plusieurs processus coopèrent, ils doivent souvent intéragir entre eux, ils doivent parfois attendre qu'une opération soit effectuée par un autre processus pour travailler.
Il faut donc avoir des mécanismes qui permettent d'envoyer des événements aux processus (un processus doit pouvoir attendre l'évènement).
Sous UNIX, les mécanismes suivants sont mis en oeuvre pour la synchronisation, les signaux et les sémaphores. On parlera de "point de synchronisation" lorsqu'un processus attend un autre.
Un SIGNAL est un événement capturé par un processus, c'est aussi un mécanisme simple utilisé par le système d'exploitation pour signaler aux processus une erreur (SIGILL, SIGFPE, SIGUSR1, SIGUSR2, etc).
Voici par exemple un programme dont la fonction "sighandler" est appellée lorsque le signal SIGUSR1 est déclenché :
#include <stdio.h> #include <signal.h> #include <unistd.h> #include <stdlib.h> void sighandler(int signum); /* Ce programme va lier la fonction sighandler au signal SIGUSR1 Ce qui signifie que lorsque l'on lance le programme (qui contient une boucle infinie), lorsque l'on lance le signal via "pkill -SIGUSR1 a.out" (par exemple) La fonction sighandler va être appellée et "SIGUSR1 reçu" va donc s'afficher à l'écran.
Il existe plusieurs opérations différentes sur les signaux :
Un sémaphore est une variable entière en mémoire qui, excepté pour son initialisation, est accédée uniquement au moyen de fonction atomiques (ne pouvant pas être décomposée) "p()" et "v()".
La fonction "p(sem)" va vérifier que la valeur est plus grande que zero, si c'est le cas, la variable est décrementée et l'exécution continue, si ce n'est pas le cas, alors il attend que ce soit le cas.
La fonction "v(sem)" va simplement incrémenter la variable de 1, et va ainsi réveiller tous les processus qui attendrait ce sémaphore.
Ces foncitons ne sont pas présente dans C de base il faut importer les fichiers "semadd.h" et "semadd.c" depuis l'espace de cours.
Représentation graphique d'une synchronisation par sémaphore
Voici un exemple d'un programme qui communique avec un processus fils via 2 sémaphores. Il est intéressant de noter que généralement un processus ne va faire qu'une seule opération par sémaphore (par exemple que des "p()" sur sem1 et que des "v()" sur sem2 ou inversément)
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include "semadd.h" #define SEM1 12345 #define SEM2 23456 /* Ce programme va créer 2 sémaphores et 2 processus (un père et un fils). Le fils et le père vont tous les deux exécuter une boucle sauf qu'a chaque itération ils vont s'attendre l'un l'autre. Ainsi le père attends le sémaphore du fils (sem2) qui est émit lorsque le fils a fini son itération De même le fils va ensuite attendre le sémaphore du père (sem1) qui est émit lorsque le père a fini son itération Si on exécute ipcs -s lors de l'exécution du programme, on peut voir la liste des sémaphores créés. Contrairement aux signaux, on peut créer nos propres sémaphores tandis que les signaux eux sont défini par le système d'exploitation.
L'allocation se fait via "int semget(int key, int nb, int flag)", oĂą
On peut aussi simplifier l'allocation à partir d'une clé en utilisant "int sem_transf(int key)", cette fonction n'est PAS OFFICIELLE mais le fichier est disponible sur HELMo Learn.
On peut gérer les sémaphores (nottament pour libérer la mémoire) en utilisant "int semctl(int semid, int semnum, int cmd, union semun attr)" où
"int semop(int semid, struct sembuf* sops, unsigned nsops)" est la fonction qui est derrière les fonctions "p()" et "v()".