Université Pierre et Marie Curie

Systèmes d'exploitation des ordinateurs

Chapitre 1. Les systèmes d'exploitation
Chapitre 2. Mécanismes d'exécution et de communication
Chapitre 3. Gestion des activités parallèles
3.1. Activités simultanées : pseudo parallèlisme
3.2. Mécanismes de synchronisation
3.2.1. Synchronisation par moniteur et sémaphores
3.2.2. Synchronisation par messages
3.2.3. Les pipes sous Unix
3.2.4. Etats d'un processus
Chapitre 4. Gestion des fichiers
Chapitre 5. Partage des ressources
Chapitre 6. Au-dessus du système d'exploitation
Chapitre 7. Notions sur les communications
Chapitre 8. Notions sur la sécurité
Bibliographie
Chapitre 9. Exercices et TPs
Examens
Page d'accueilTable des matièresNiveau supérieurPage précédenteBas de la pagePage suivante

3.2.1. Synchronisation par moniteur et sémaphores

Synchronisation par moniteur

Le moniteur est le cœur du système d'exploitation. Il est constitué d'un ensemble de procédures et de variables d'état utilisées par ces procédures. Le moniteur représente le coeur du système d'exploitation. Il échappe aux règles habituelles des processus car il est toujours présent et son rôle est d'ordonnancer leur fonctionnement.

Certaines de ses variables sont accessibles à l'utilisateur grâce à des bibliothèques de fonctions spéciales au travers de points d'entrée du moniteur. Les procéssus externes au moniteur peuvent interroger et utiliser ces variables mais elles ne peuvent pas les modifier car il est fort probable que cela perturberait le fonctionnement du moniteur donc de l'ordinateur.

Parmi ces fonctions il en existe qui permettent de bloquer ou de réveiller les processus écrits par les utilisateurs. Le blocage et le réveil s'effectuent au moyen d'une condition c utilisable dans les trois opérations suivantes:

  • attendre(c): bloque le processus p qui l'utilise et le place en attente de l'événement c.
  • vide(c) retourne vrai si il n'existe pas de processus en attente de c, faux sinon.
  • activer(c) réveille le premier processus en attente de l'événement c.

On notera que la fonction attendre(c) suppose l'existence d'une file d'attente associée. Ce concept sera évoqué dans la section V.2. Le processus réveillé reprend son activité à l'instruction qui suit le point d'arrêt.

Insistons sur une caractéristique essentielle de la synchronisation par moniteur : les processus consultent l'état de variables qu'ils ne peuvent modifier en aucun cas. C'est donc un moyen assez frustre car les communications sont réduites au minimum mais simple à réaliser. Ces mécanismes existent à des degrés divers dans tous les systèmes d'exploitation. Nous les avons déjà rencontré lorsque nous avons expliqué la création de processus sous Unix et que nous avons expliqué qu'il était possible de bloquer le père au moyen d'un apple à une fonction wait().

Synchronisation par sémaphore

La synchronisation par sémaphore ou flag est un moyen simple et ancien de synchroniser des processus parallèles. A la différence de la synchronisation par le moniteur le programmeur a accès aux états de ce drapeau et peut le manipuler. Le principe est directement hérité des chemins de fer d'où son nom : lorsque le sémaphore est levé, le processus P peut continuer son chemin; lorsqu'il est baissé il doit attendre jusqu'à ce qu'un autre processus Q le lève. P et Q sont l'équivalent de deux trains roulant sur deux voies distinctes qui doivent se synchroniser pour pouvoir franchir un croisement sans accident.

Dans le modèle le plus simple il existe trois primitives:

  • lever (c) fait passer le sémaphore c de la valeur "baissé" à "levé".
  • baisser(c) fait passer le sémaphore c de "levé" à "baissé".
  • flag(c) retourne vrai si le sémaphore c est baissé.

Les sémaphores sont des variables communes mises à la disposition des différents processus par le système d'exploitation qui peuvent les consulter, les modifier et sur lesquelles ils peuvent se mettre en attente.

Pour l'illustrer reprenons l'exemple du transfert de résultats au moyen d'un tampon, que nous avons décrit dans la section 2.2. Le fonctionnement est le suivant:

Processus P Processus Q
baisser(e); lever(f);
while (calculs à faire){ while (éléments à transférer) {
    calculs des éléments du tampon (a);     if (flag(e)) {
    baisser(e);                      attendre(e)
    if (flag(f)) {                     }
         attendre(f);     baisser(f);
    }     lire tampon(a);
    écrire tampon (a);     lever(f);
    lever(e); }

Nous n'avions pas évoqué comment les variables e et f pouvaient être communes à deux processus distincts. A la différence des threads les segments de données sont disjoints donc il faut imaginer un moyen de partager ces informations. Les sémaphores sont une solution pour résoudre ce problème. Ils font partie du contexte commun à l'ensemble des processus. Ces variables ne peuvent prendre que deux valeurs. Elles doivent être déclarées au moyen d'instructions spéciales qui précisent les noms des processus qui peuvent les partager. Les sémaphores sont un moyen simple de synchronisation qui, cependant, est en désuétude car il ne permet qu'un partage pauvre (binaire) d'informations. On préfère aujourd'hui une synchronisation par messages qui, comme son nom l'indique, permet d'échanger des informations. MPI, PVM, que nous avons évoqué antérieurement sont une solution mais ce n'est pas la seule. Nous nous étendrons pluis longuement sur ce point dans la suite.


Copyright Yves Epelboin, université P.M. Curie, 1998 MAJ 4 avril, 2005

Page d'accueilTable des matièresNiveau supérieurPage précédenteHaut de la pagePage suivante