A. Zone critique et exclusion mutuelle

Zone critique

Une zone critique peut être une structure de données, une ressource partagée, une section de code au timing délicat, une zone de mémoire.

Une zone critique ne peut être interrompue une fois commencée. Il faut donc désactiver les interruptions à l’entrée de la section critique et les réactiver à la sortie.

Une seule tache a le droit d'accéder à une zone critique. Elle doit être protégée pour que les autres taches ne puissent modifier les données ou l'état du matériel. La technique des sémaphores que nous verrons plus loin doit donc être utilisée.

 

Exclusion mutuelle

Lorsqu'une ressource n'est pas partageable entre plusieurs taches, un mécanisme doit en assurer l'accès exclusif. Un tel mécanisme est appelé exclusion mutuelle : lorsqu'une tache utilise la ressource, aucune autre tache ne peut l'utiliser.

Une imprimante peut être utilisée par plusieurs processus (par exemple, par Word, par Excel, et d'autres logiciels) mais son accès est exclusif. Sinon, on pourrait avoir un mélange de fichiers si plusieurs processus se mettent à imprimer en même temps.

L'exclusion mutuelle peut être réalisée de différentes façons :

 

A. Tache

Définition

Une tache est un programme qui s’exécute comme s’il était le seul à utiliser le CPU. Il possède une priorité, du code à effectuer, une partie de la mémoire et une zone de pile.

Une tache peut être dans différents état comme le montre le schéma suivant :

Le tableau suivant montre dans quel cas une tache peut passer d'un état à un autre :

Etat d'origine
Nouvel Etat
Evènement provoquant la transition
Dormante
Exécutable
La tache est activée
Exécutable
Active
L'Ordonnanceur donne le CPU à la tache
Active
Bloquée
La tache est en attente d'une ressource (bloquée par un sémaphore).
Bloquée
Exécutable
La ressource dont la tache était en attente est libérée
Active
Exécutable
L'Ordonnanceur donne le CPU à une autre tache (préemption)
Active
Interrompue
Une interruption stoppe la tache
Interrompue
Active
Le traitement de l'interruption est terminé

 

Multi-tâches

Un OS multi-tâches permet l’exécution simultanée de plusieurs taches. Pour un système mono-processeur (CPU unique avec exécution séquentielle des instructions), l'exécution simultanée est simulée : chaque tache a l'impression de posséder le CPU mais c'est l'ordonnateur qui répartit le CPU.

Le processus de conception pour les applications temps-réelles implique de diviser le travail à effectuer entre différentes taches chacune responsables d’une partie du problème.

 

Ordonnanceur

L'Ordonnanceur est le composant du noyau responsable de la distribution du temps CPU entre les différentes taches. Il est basé sur le principe de la priorité : chaque tache possède une priorité dépendant de son importance (plus une tache est importante, plus sa priorité est élevée). Il attribue le processeur à la tache exécutable (non dormante et non bloquée) de plus haute priorité.

Lorsque qu’une tache T2 plus prioritaire que la tache active T1 passe de l’état bloqué à l’état exécutable, T1 est suspendue et l’Ordonnanceur attribue le processeur à T2. C'est le principe de la préemption. La préemption permet un temps de réponse des taches optimum.

 

Changement de contexte

Quand l'ordonnaceur doit transférer l'usage du processeur d'une tache à l'autre, il opère un changement de contexte. Le contexte représente l'état du processeur à un moment donné.

La tache suspendue doit pouvoir continuer son éxécution sans être affectée, la première opération à effectuer est donc la sauvegarde de l'état du processeur au moment de la suspension. Le noyau possède pour chaque tache non dormante un espace mémoire réservé à cet effet.

Les données temporaires utilisées par la tache suspendue doivent être préservées lors des opérations de la nouvelle tache active. Ces données sont organisées sous forme de pile contenant le contexte des appels de sous routines en cours (adresse de retour, valeur des resgistres) ainsi que les paramètres et le s variables temporaires de ses sous-routines.

Une tache peut être suspendue à tout moment et l'usage du processeur tyransféré vers une autre tache susceptible d'appeler des sous-routines et d'allouer des variables temporaires. Chaque tache possède sa propre pile.

Le temps recquis pour un changement de contexte est déterminé par le nombre de resgistres à sauvagarder et à restaurer par le CPU.

 

Niveau de contrainte temporelle

Un système temps réel se compose de plusieurs taches. Pourtant, toutes ces taches ne relèvent pas du temps réel. On peut distinguer trois niveaux de contraintes temporelles :

Ainsi, chaque tache se voit attribuer une priorité qui est fonction de son caractère critique. Plus une tache est importante, plus sa priorité est élevée. Il existe deux types de priorité de taches :

L'inversion de priorité est une problème qui survient lorsqu'une tache est suspendue dans l'attente d'une ressource contrôlée par une tache moins prioritaire. Par exemple, s'il existe deux taches T1 et T2 avec T1 plus prioritaire que T2. T1 attend qu'un événement se produise dans T2 (par exemple la libération d'un sémaphore). Dans ce cas, la priorité effective de T1 est réduite à celle de T2 car elle est en attente d'une ressource détenue par T2.

Pour résoudre ce problème, il suffit d'élever temporairement le priorité de T2 en la rendant égale à celle de T1 pendant le laps de temps qu'elle utilise la ressource en ensuite de restaurer sa priorité normale.

 

B. Communication entre taches

Problématique

Le transfert correct de données entre taches dans un programme temps-réel soulève des problèmes plus importants que dans le cas d'un programme unique communiquant avec des routines d'interruption car :

Pour communiquer entre différentes taches, le noyau fourni des services destinés à :

 

Sémaphore

Le concept de sémaphore est utilisé pour contrôler l'accès à une ressource. Lorsqu'une tache accède à une ressource non partageable, le sémaphore à l'entrée de celle-ci devient bloqué et le reste tant que la tache a relaché la ressource. Il empeche ainsi tout autre tache a accéder à cette ressource.

Dans la signalisation ferroviaire, il ne doit y avoir qu'un train au maximum par tronçon de voie férrée. Lorqu'un train entre dans ce troncon, aucun autre train de peut y entrer tant que le premier train ne l'a pas quitté.

Un sémaphore peut être généralisé au cas où une ressource est accessible par n taches simultanément. Dans ce cas, le sémaphore peut prendre n + 1 états qui seront représentés par un compteur.

Un sémaphore est possède une valeur entière s qui représente le nombre de taches qui accèdent à la ressource qu'il surveille. Sa valeur est positive ou nulle et est uniquement manipulable à l'aide de deux opérations : wait(s) et sinal(s) :

Un sémaphore qui ne peut prendre que deux états (libre et bloqué) est appelé sémaphore binaire ou mutex. Dans ce cas, une seule tache peut avoir accès à la ressource.


Les files de communication

Une file d'attente est un objet permettant la communication synchrone ou asynchrone de valeurs entre des taches. Les caractéristique d'une file de communication sont les suivantes :