Les politiques d’ordonnancement

Dans le document en fr (Page 89-95)

capteurs sans fil

2.7 Le système d’exploitation LIMOS

2.7.2 Les politiques d’ordonnancement

La politique d’ordonnancement des événements et des processus s’effectue en accord avec leurs caractéristiques propres. L’architecture à deux niveaux du système se retrouve dans l’ordonnancement de ces différents éléments. Ainsi, le système est à la fois muni d’un gestionnaire d’événements et d’un ordonnanceur de processus, représentant un des autres aspects novateurs introduits par le système LIMOS.

2.7.2.1 Le gestionnaire d’événements

De la même manière que sous les systèmes TinyOS et Contiki, un événement ne peut pas être préempté par un autre événement. Du moment où les traitements associés à un événement ont débuté, ils se poursuivent jusqu’à leur terminaison. L’unique arrêt autorisé concerne la prise en compte d’une interruption. A l’arrivée d’une interruption, le noyau du système traite celle-ci puis redonne la main de suite à l’événement suspendu. En résumé, un événement est donc interruptible mais ne peut être préempté (voir Figure 2.23). Par conséquent, les différents états d’un événement sont :

• l’état « Inactif » ;

• l’état « Prêt » ;

• l’état « Elu ».

Figure 2.23 – Diagramme d’états et de transitions des événements

Au démarrage du système, l’événement débute dans l’état « Inactif ». Il passe ensuite dans l’état « Prêt » dès l’arrivée d’un signal matérialisé par l’apparition d’un message dans son tuple associé. En outre, un événement périodique est synchronisé soit sur la fréquence d’acquisition d’une donnée issue d’un capteur physique soit sur sa fréquence propre gérée par le système. La notion de tuple est très importante dans le système LIMOS et correspond, pour un événement, à un espace mémoire réservé où les messages à son attention sont déposés.

Une définition et une présentation plus détaillées sont fournies dans la section 2.7.3.2 dont l’objet est la communication et la synchronisation au sein du système LIMOS. Comme nous allons le voir, les tuples interviennent également dans le choix de l’événement courant à exécuter. Dans l’état « Prêt », l’événement entame une phase d’attente qui se termine par sa prise en charge par le système accompagné d’un passage à l’état « Elu ». A la fin de son exécution, l’événement revient à l’état « Inactif ».

CemOA : archive ouverte d'Irstea / Cemagref

Au-delà de son état, les autres attributs des événements sont :

• son identifiant;

• la liste ou table des processus qui lui sont associés ;

• l’identifiant de son tuple ;

• le nombre de messages en attente dans son tuple ;

• sa priorité.

L’ensemble de ces attributs donne la structure d’un événement telle qu’elle est présente dans le système LIMOS (voir Figure 2.24).

Figure 2.24 – Structure d’un événement dans le système LIMOS

Le gestionnaire des événements du système LIMOS combine un ordonnancement simple sur les priorités et un autre basé sur la politique EDF (Earliest Deadline First).

L’ordonnancement obtenu est à 2 niveaux (voir Figure 2.25).

Figure 2.25 – Algorithme d’ordonnancement des événements

/*!

struct Thread* thread_tab[MAXTHREAD]; /* liste des processus associés */

char event_tuple; /* identifiant du tuple */

char event_tuple_num ; /* nombre de messages du tuple */

char event_prior; /* priorité */

};

/* Ordonnancement des événements */

/* Ordonnancement simple sur les priorités */

Sélection du ou des événements « Prêt » de plus haute priorité

SI égalité entre événements ALORS

/* Ordonnancement basé sur la politique EDF */

Sélection du ou des événements avec le plus de messages en attente

SI égalité du nombre de messages en attente ALORS Exécution de l’événement le plus ancien SINON

Exécution de l’événement avec le plus de messages en attente FINSI

SINON

Exécution de l’événement de plus haute priorité FINSI

Retour au début de la procédure d’ordonnancement des événements

CemOA : archive ouverte d'Irstea / Cemagref

L’événement suivant dans l’ordre d’exécution est celui qui a la plus grande priorité stockée dans l’attribut « event_prior ». Si plusieurs événements ont la même priorité, celui qui a le plus grand nombre de messages en attente dans son tuple est choisi. En cas de nouvelle égalité au niveau du nombre maximum de messages en attente, l’événement le plus ancien est sélectionné. La dimension d’un tuple étant limitée, il faut éviter que des messages soient perdus du fait qu’un événement n’a pas été pris en charge à temps. La priorité d’un événement est déterminée selon l’importance de celui-ci à l’initialisation du système.

2.7.2.2 L’ordonnanceur des processus

A contrario d’un événement, un processus peut être préempté. Cette propriété se retrouve dans les attributs qui lui sont associés (voir Figure 2.26) :

• son identifiant ;

• son état ;

• l’adresse de la fonction qui lui est associée ;

• l’identifiant de son tuple ;

• l’adresse de début de sa pile ;

• l’adresse courante de sa pile ;

• sa priorité ;

• son quantum de temps d’exécution ;

• l’identifiant de l’événement auquel il appartient.

Figure 2.26 – Structure d’un processus dans le système LIMOS

L’état « Suspendu » se rajoute aux états d’un événement et correspond soit au cas où le processus est en attente d’une ressource indisponible pour l’instant soit au moment où il est préempté par un autre processus (voir Figure 2.27).

Sous certaines conditions, un processus suspendu peut entrer directement dans l’état

« Inactif ». Celui-ci correspond à la fois aux processus non activés et à ceux terminés. Quand les processus d’un événement ont réalisé leur traitement et sont passés dans l’état « Inactif », l’événement a terminé son exécution et devient à son tour « Inactif ». Il est à souligner qu’un événement passe dans l’état « Prêt » quand il a au moins un processus prêt à être exécuter et réciproquement.

char thread_id; /* identifiant */

char thread_state; /* état */

char thread_tuple; /* identifiant du tuple */

char thread_address /* adresse des traitements associés */

char thread_stack_inisp /* pointeur de début de pile */

char thread_stack_cursp /* pointeur courant de pile */

char thread_prior /* priorité */

char thread_quantum /* quantum de temps */

char thread_event /* identifiant de l’événement */

};

CemOA : archive ouverte d'Irstea / Cemagref

Figure 2.27 – Diagramme d’états et de transitions d’un processus

Les tuples sont de nouveau utilisés comme espace d’échange entre processus. Chaque processus dispose d’un tuple propre où sont postés les données qui le concernent. Une pile est attachée à tout processus. Elle permet de sauvegarder son contexte d’exécution s’il est préempté. Une attention toute particulière doit accompagner la définition des actions et du mode de fonctionnement des processus pour éviter les situations d’inter-blocage. En général, ce type de problème survient quand un processus de forte priorité préempte un autre processus et attend une donnée qui doit lui être fourni par le processus qu’il vient de préempter ou, plus généralement, un processus de plus faible priorité. Une des solutions est d’affecter, dès le départ, une priorité plus faible ou égale au processus consommateur par rapport au processus producteur. Quand le nombre de processus s’échangeant des informations est supérieur à 2, une étude approfondie de leurs interactions est nécessaire. En cas de blocage avéré et persistant, un mécanisme de type chien de garde peut être utilisé pour redémarrer et réinitialiser le système sans toutefois résoudre totalement le problème.

A la base, dans le système LIMOS, les processus sont ordonnancés selon la politique du tourniquet à quantum de temps déjà utilisée au sein des micronoyaux DREAM et SDREAM (voir Figure 2.28).

La sélection d’un processus se fait par comparaison de leur priorité. En cas d’égalité, les processus se partagent les ressources systèmes chacun leur tour pendant une durée de temps fixé (quantum de temps). Une rotation est donc effectuée entre les processus jusqu’à ce qu’ils aient fini leurs traitements (voir Figure 2.29). Le temps alloué à chaque processus est obtenu à partir de son attribut « thread_quantum ». Si la configuration du système spécifie un même quantum de temps pour tous les processus, l’attribut « thread_quantum » peut être omis de la structure des processus. Un processus ne pouvant pas être stoppé brutalement, la préemption se produit dès que celui-ci n’est plus dans une section critique d’exécution.

CemOA : archive ouverte d'Irstea / Cemagref

Figure 2.28 – Algorithme d’ordonnancement des processus

Dans l’exemple présenté ci-dessous, si les processus de P1, P2 et P4 ne finissent pas leur exécution avant que le processus P5 ne retourne dans l’état « Prêt », ils seront préemptés par ce dernier. Cette remarque est valable pour le processus P3 pouvant être préempté à la fois par le processus P5 mais également par P1, P2 et P4.

Figure 2.29 – Illustration de l’ordonnancement de processus sous le système LIMOS

2.7.2.3 L’ordonnancement dans le système LIMOS

La déclaration d’un certain nombre d’événements et de processus fait partie de l’étape d’initialisation du noyau LIMOS (voir Figure 2.30). Ces derniers ne peuvent pas être créés

/* Ordonnancement des processus */

/* Ordonnancement simple sur les priorités */

Sélection des processus « Prêt » de plus haute priorité de l’événement courant

SI égalité entre processus ALORS

/* Utilisation de la politique d’ordonnancement du tourniquet par quantum de temps */

Exécution alternée durant leur quantum de temps associé des processus à égalité SINON

Exécution du processus de plus haute priorité FINSI

SI plus aucun processus n’est dans l’état « Prêt » ALORS Appel au gestionnaire d’événements SINON

Retour au début de la procédure d’ordonnancement des processus FINSI

CemOA : archive ouverte d'Irstea / Cemagref

dynamiquement pour garantir le déterminisme du système vis-à-vis des exigences liées à l’application temps réel supportée.

Figure 2.30 – Initialisation du système LIMOS

La création des tuples, des processus, des événements ainsi que leurs relations est réalisée au sein de la fonction init_Software(). Les éléments matériels à initialiser sont la gestion des Entrées/Sorties, les différents ports (série par exemple), le convertisseur analogique-numérique et le temporisateur programmable (« timer ») (Voir Figure 2.31).

Au regard de l’architecture à deux niveaux du système LIMOS, le gestionnaire d’événements est le premier en action et détermine l’événement courant. L’ordonnanceur de processus prend le relai pour mettre à disposition les ressources systèmes aux différents processus de l’événement courant.

Figure 2.31 – Rôles des fonctions « init_Software() » et « init_Hardware() »

Quand tous les processus ont réalisé leurs traitements, le gestionnaire reprend la main pour sélectionner l’événement suivant (voir Figure 2.32). Les événements E1 et E2 ont la même priorité. Par conséquent, le premier à être pris en charge par le système est déterminé en se basant sur le nombre de messages en attente dans les tuples respectifs. En cas de nouvelle égalité, l’événement le plus ancien dans la file d’attente est choisi. L’événement E1 possède 5 processus dont 3 avec la même priorité qui sont donc exécutés alternativement durant leur quantum de temps associé. Le même principe est appliqué aux processus P31 et P32 de l’événement E3. Les processus de l’événement E2 ayant tous des priorités différentes, ils s’exécutent normalement les uns après les autres. L’événement démon (« daemon ») est activé lorsqu’aucun autre événement n’a besoin des ressources du système. Sa priorité est la plus basse du système c’est-à-dire 0, la plus haute étant fixée arbitrairement à 10. Si le noyau

1) Désactivation des interruptions

reste inutilisé pendant un laps de temps assez long, l’événement démon sera en charge de la mise en veille de certains, voire de la totalité des composants du système, afin de diminuer l’énergie consommée. La mise en place de ce genre de mécanisme ne peut se faire qu’en s’appuyant sur une architecture matérielle adéquate.

Figure 2.32 – L’ordonnancement des événements et des processus

Dans le document en fr (Page 89-95)