Station MinuitPortail personnel de révision

IFT-2001 — Systèmes d’exploitationAutomne 2026

Semaine 5 — Concurrence

6. Sémaphores

LECTURE 09 / 205 repèresSynthèse avec omissions acceptées

6. Sémaphores

6.1 Modèle

Un sémaphore de Dijkstra comprend :

  • un compteur K de permissions ou de ressources disponibles;
  • une file L de participants bloqués.

Deux opérations atomiques le manipulent :

  • P, down ou wait : si une permission est disponible, la consommer; sinon placer l’appelant en attente;
  • V, up, signal ou post : réveiller un attenteur, ou augmenter le nombre de permissions si personne n’attend.

Une file FIFO produit un sémaphore fort et limite la famine. Une politique non équitable, par exemple LIFO, peut laisser un ancien attenteur indéfiniment en file.

6.2 Comptage, binaire et ordre

  • Un sémaphore de comptage représente plusieurs ressources interchangeables.
  • Un sémaphore binaire ne prend que les états 0 et 1 et peut servir à l’exclusion, sans acquérir automatiquement la sémantique de propriété d’un mutex.
  • Un sémaphore initialisé à 0 peut imposer un ordre : une tâche exécute S1 puis effectue post; l’autre attend avant S2. Ainsi, S1 précède toujours S2.

6.3 Producteur-consommateur corrigé

Code (text) · sélectionner pour copier

producteur                       consommateur
produce()                        down(full)
down(empty)                      down(mutex)
down(mutex)                      retirer de la file
insérer dans la file             up(mutex)
up(mutex)                        up(empty)
up(full)                         consume()

Initialisation :

  • empty = N : nombre de places libres;
  • full = 0 : nombre d’éléments disponibles;
  • mutex = 1 : accès exclusif à la structure.

Il faut acquérir le sémaphore de ressource avant le mutex. Sinon, un thread pourrait dormir en conservant le mutex dont l’autre a besoin pour rendre la ressource disponible.

6.4 API POSIX des sémaphores

  • POSIX distingue les sémaphores nommés et non nommés; les références du module détaillent surtout le cycle de vie des objets non nommés.
  • sem_init(&s, pshared, value) initialise un sémaphore non nommé. pshared == 0 le limite aux threads du même processus; une valeur non nulle exige une mémoire réellement partagée entre processus.
  • sem_wait décrémente ou bloque. sem_trywait retourne immédiatement avec EAGAIN; sem_timedwait utilise une échéance absolue. Une interruption par signal peut produire EINTR.
  • sem_post rend une permission et peut réveiller un attenteur. L’appel est async-signal-safe; dépasser SEM_VALUE_MAX produit EOVERFLOW.
  • sem_getvalue permet de consulter la valeur exposée par l’implantation, mais cette observation instantanée ne remplace pas une opération atomique de synchronisation.
  • sem_destroy doit être appelé avant de libérer la mémoire, mais seulement lorsqu’aucun participant n’attend. Réinitialiser un sémaphore actif ou le détruire pendant une attente mène à un comportement indéfini.
Retour au sommaire de l’unitéHaut de page
Récupérer manuellement les données locales

Copier séparément les données ci-dessous dans des fichiers texte avant de fermer la page ou de modifier le stockage. Une valeur illisible ou incompatible reste en place. Aucun effacement ni rétablissement écrasant n’est effectué automatiquement. L’export/import JSON est disponible sur la page Progression du cours. Cette récupération séparée reste utile pour une valeur brute ou un conflit.

Clé de ce cours : . Format v1 porté par cette clé; dates UTC et identifiants durables.

Si l’accès est refusé, la valeur persistée peut rester inaccessible. Réautoriser le stockage dans le navigateur puis rouvrir ce cours permet de la relire. Une réinitialisation exige une décision explicite après récupération; aucune commande de suppression n’est proposée ici. Les données restent sur cette origine et cet appareil, sans transfert automatique.