Premiers pas avec Xenomai

Image non disponible


précédentsommairesuivant

V. Qu'est-ce que Xenomai ?

V-A. Origines

L'histoire de Xenomai est un peu tumultueuse. L'explication de M. Franke établit une synthèse et un « arbre généalogique » très clairs auquel le lecteur pourra se reporter.

V-B. Xenomai, comment ça marche ?

Xenomai est un système d'exploitation temps réel qui a Linux pour tâche de fond. Linux est alors préempté comme une simple tâche. Le discours sur la préemption impossible des sections critiques, les handlers... est caduc avec Xenomai.

Les tâches gérées par Xenomai apportent ainsi une garantie d'exécution temps réel dur.

Qui dit deux systèmes d'exploitation, dit deux ordonnanceurs… et (au moins) deux problèmes : comment partager le matériel, et comment faire interagir les tâches Linux et Xenomai entre-elles.

Les explications qui suivent sont une vulgarisation de haut niveau, on pourra se reporter à l'article technique Life with ADEOS de Philippe Gerum pour plus de détails.

Si vous être pressés, lisez ce paragraphe ! Il est essentiel.

V-B-1. Le routage des interruptions avec ADEOS

Comment alors faire cohabiter ces deux OS sur le même matériel ? Pour l'accès au CPU et à la mémoire, il n'y a pas de problème car Linux est une tâche. Mais si une interruption (timer, carte…) arrive, qui va la traiter ?

Image non disponible

La solution consiste à intercaler une couche entre le matériel et les systèmes d'exploitation. Cette couche de virtualisation (ou hyperviseur, ou encore couche d'abstraction matérielle) s'appelle ADEOS.

ADEOS est un nanokernel(20) qui va capturer les évènements pour ensuite les dispatcher vers Xenomai ou Linux, mais pas dans n'importe quel ordre ! Le but étant tout de même d'avoir un OS temps réel, il est impératif que Xenomai soit le premier à les traiter. Si elles ne sont pas pour lui, elles sont alors « passées » à Linux.

Le lecteur attentif que vous êtes aura remarqué le changement de terminologie entre le début et la fin du paragraphe : on est passé d'interruptions à évènements. Cette généralisation sera expliquée par la suite.

Image non disponible

Très concrètement, ADEOS(21) se présente sous la forme d'un patch du noyau Linux. Son arborescence de développement est distincte de Xenomai, ses évolutions sont assurées par Philippe Gerum.

V-B-2. Coexistence Xenomai/Linux et partage des ressources : le co-scheduling

 

En théorie, la virtualisation peut faire cohabiter en toute indépendance plusieurs OS sur le même matériel. Or, que veut-on ? Réponse : faire du temps réel avec Linux afin de profiter de tout l'environnement non temps réel. Intuitivement, on sent bien qu'il faut faire un lien entre les deux. Oui, mais comment ? Par les ressources utilisées !

Pour l'instant, chacun est tranquillement chez soi : les tâches Xenomai dans leur scheduler, idem pour les tâches Linux. Imaginons, un instant qu'une impétueuse tâche Xenomai cherche à obtenir la date. La ressource « date » appartient au noyau Linux et on ne peut pas aller la chercher directement depuis Xenomai, il se peut en effet qu'elle soit en cours de mise à jour et donc invalide ! Il faut par conséquent passer par un appel système Linux. Un peu idiot me direz-vous, puisqu'on va retomber sur le problème de performance de Linux pour du temps réel. Remettons la polémique à plus tard et attardons-nous plutôt sur le fonctionnel.

Comment traiter les appels système Linux depuis les tâches Xenomai ? Les appels système regroupent les accès à des ressources partagées (terminal, couche réseau…) dont la concurrence d'accès est gérée par Linux. Or, Linux ne connaît pas les tâches Xenomai !!!

La solution consiste à déplacer les tâches d'un scheduler à l'autre en fonction des ressources utilisées. Une tâche créée via l'API Xenomai pourra s'exécuter sous Linux, ce mécanisme totalement transparent est appelé shadow threading.

Une tâche schedulée par Xenomai est dite en primary mode.
Une tâche Xenomai schedulée par Linux est dite en secondary mode (22).
Une tâche Linux schedulée par Xenomai est dite... ha !ha ! c'était un piège, ça n'existe pas.
Le passage d'un mode à l'autre est fonction des ressources accédées et donc des appels système Xenomai ou Linux.

Les termes primary mode et secondary mode sont hérités de la terminologie ADEOS qui appelle les OS reposant sur lui des domaines (domains). Comme nous l'avons vu un peu plus haut, ces domaines ont une priorité dans la réception des évènements. Dans notre cas, Xenomai les réceptionne en premier (primary domain) et Linux en second (secondary domain).

Une fois que la tâche Xenomai a fait son appel système Linux et qu'elle se trouve en secondary mode, elle y reste tant qu'elle ne fait pas d'appel système Xenomai.

Image non disponible
Illustration : Migration interdomaines d'une tâche Xenomai

Linux devient une tâche de Xenomai. Mais quelle priorité lui affecter ? A priori, la plus faible possible (tâche idle pour Xenomai).

Comment alors considérer la priorité des tâches Xenomai passées dans le scheduler Linux ? Faible comme Linux ou bien constante ?

Dans Xenomai, la deuxième implémentation a été retenue (23).

La priorité d'une tâche Xenomai est constante, quel que soit le scheduler dans lequel elle se trouve.

Cette implémentation n'est possible qu'à une condition : que la priorité de la tâche Linux dans l'ordonnanceur Xenomai évolue dynamiquement, sinon on se retrouverait dans un cas d'inversion de priorité.

La priorité de la tâche Linux dans l'ordonnanceur Xenomai est déterminée de la manière suivante :
  • 0 s'il n'y a aucune tâche en secondary mode (idle Xenomai) ;
  • la priorité maximale des tâches en secondary mode.

Les schémas du paragraphe suivant permettent de mieux visualiser cette politique d'ordonnancement.

V-B-3. La gestion des priorités dans les modes primary et secondary

Nous voici face à un nouveau problème : une fois dans l'ordonnanceur Linux, la tâche Xenomai est maintenant une tâche comme les autres et on revient au point de départ, à savoir, comment faire du temps réel avec Linux ?

Or, qu'avions-nous écrit plus haut ? Que les dérives temporelles étaient introduites par :

  • les interruptions (handlersLinux) : nous avons maintenant ADEOS pour les masquer (Interrupt Shield) ;
  • la préemption par des tâches de plus forte priorité : il suffit de s'exécuter dans la classe SCHED_FIFO(24) ;
  • l'absence de préemption à l'intérieur du noyau : les options natives (« low latency desktop ») la résolvent partiellement.

Une tâche en secondary mode est du temps réel mou et son temps d'exécution est borné (Interrupt Shield).
Pour les tâches à contrainte temps réel dur, il faut absolument rester en primary mode (25).
Les tâches Xenomai ont 99 niveaux de priorité possibles, exactement comme la classe SCHED_FIFO/RR. Ceci est normal puisque les priorités ne changent pas d'un scheduler à l'autre, la correspondance est donc immédiate (26).

Les exemples ci-dessous détaillent les différents cas de figure.

Soient Ln les tâches schedulées par Linux et Xn celles par Xenomai. Chaque tâche a une priorité, notée PrioLx ou PrioX, selon l'ordonnanceur de départ. Cette distinction est de pure forme car toutes les priorités évoluent dans le même espace.

Les priorités Xenomai sont constantes à travers les schedulers :

Image non disponible

Le noyau Linux est une tâche de fond dont la priorité évolue dynamiquement en fonction de la tâche Xenomai de plus haute priorité éligible en mode secondaire.

Image non disponible

Comme vous pouvez le constater (et peut-être vous en étonner), il y a deux tâches élues dans le schéma précédent. On est pourtant bien sur un exemple simple, monoprocesseur. En fait, chaque tâche élue est considérée en fonction de son ordonnanceur et non pas du processeur.

Image non disponible

Parmi un ensemble de tâches Xenomai éligibles, c'est toujours celle de plus haute priorité qui sera exécutée, quel que soit son mode !!!

Ci-dessus, X1 est la tâche courante bien qu'il existe d'autres tâches Xenomai en primary mode.

Les tâches Xenomai en mode secondaire sont en concurrence avec les autres tâches Linux de la classe SCHED_FIFO/RR.

Dans l'exemple suivant, le système possède une tâche L1 sans rapport avec Xenomai. Cette tâche a une priorité de 80.

Image non disponible

L'exécution de Xenomai a basculé la tâche élue X1 en secondary mode, la concurrence d'accès au CPU va donc se jouer dans l'ordonnanceur Linux. Or, L1 va préempter tout le monde !

Si vous êtes dubitatif sur ce changement de priorité dynamique de la tâche Linux, voici un contre-exemple qui devrait vous convaincre. Si la tâche Linux gardait sa priorité -1, on serait alors dans un cas d'inversion de priorité :

Image non disponible

Dans le scheduler Xenomai, la priorité de la tâche Linux est égale :
  • à celle de la tâche de plus haute priorité en secondary mode;
  • à -1 s'il n'y en a pas.

Bizarre ? Disons logique plutôt. On pourrait en fait s'attendre à ce que X2 prenne la main. Non, non, non et non ! Puisque nous serions alors dans un cas d'inversion de priorité.

Attention : une tâche Linux peut préempter une tâche Xenomai.

Il faut être attentif à deux choses pour les tâches en secondary mode afin d'éviter des comportements non souhaités :
- leurs priorités doivent être inférieures à celles en primary mode  ;
- leurs priorités doivent être supérieures aux tâches Linux s'exécutant dans la classe SCHED_FIFO (dépend de la distribution).

V-B-4. ADEOS ou comment modifier Linux proprement

Les fameux « évènements » se précisent. Peuvent provoquer un rescheduling :

  • les interruptions matérielles : timer pour les tâches périodiques, équipement prêt...
  • les signaux logiciels : fin d'une tâche suite à une faute...
  • les créations/destructions de tâche : fork, exit...
  • les changements de caractéristiques d'une tâche : priorité, policy ;
  • les deschedulings volontaires.

L'idée est d'avoir un comportement uniforme quels que soient le type d'évènements et le domaine d'origine. On réapplique ce que nous avions vu pour les interruptions matérielles : tous les évènements sont envoyés dans un tuyau et les domaines (OS) viennent y puiser les informations qui les intéressent.

Image non disponible

Le patch ADEOS est « respectueux » du code initial du noyau Linux car il ne le modifie que très peu.

Petite parenthèse : lors du démarrage de la machine, le domaine Linux est créé avant le domaine Xenomai. Cette primauté lui confère le nom de root domain, terme que l'on va ensuite retrouver dans la liste des tâches Xenomai.

V-B-5. Interrupt shield : sus aux interruptions !

 

(27)Devinette : nous sommes en secondary mode, nous maîtrisons les priorités des autres processus Linux, quelle est la seule chose qui peut augmenter notre temps d'exécution ?

Tic, tac...

Bonne réponse : les handlers d'interruption Linux (top-half) et les tasklets hors de contrôle du scheduler des tâches (bottom-half).

Afin de s'en prémunir, un mécanisme appelé Interrupt shield protège les tâches en secondary mode en filtrant les interruptions. Le temps d'exécution de la tâche est alors borné.

Mais alors pourquoi l'IS n'est-il pas activé par défaut lors de l'installation ? Simplement, car il y a un risque d'inversion de priorité.

Prenons l'exemple suivant, soit deux tâches T1 et T2 en secondary mode. T2 active l'InterruptShield. T1 a la main (normal car elle est prioritaire) puis se place en attente de données. Elle est alors deschedulée, T2 entre alors en jeu. Une interruption arrive. T1 est censée s'exécuter, or elle est schedulée par Linux, et celui-ci n'a pas encore été informé que l'interruption est arrivée (IS). T2 termine alors son traitement, l'interruption est relâchée, T1 est débloquée.

Image non disponible

La solution serait alors que T2 soit protégée des interruptions Linux tout en laissant T1 s'exécuter si des données arrivent.

Image non disponible
Illustration : Interrupt Shield et driver RTDM

Ceci revient à dire qu'il faut que l'interruption pour T1 ne soit pas traitée par Linux mais directement par Xenomai. Si ce handler est géré par Xenomai, le read doit l'être également.

Tout ceci nous amène naturellement à définir des drivers spécifiques à Xenomai (RTDM: Real Time Model Device), un exemple de driver est présenté au chapitre XII.

C'est également depuis l'API RTDM que des tâches Xenomai en mode noyau peuvent être lancées (primitive rtdm_task_init()).

V-C. Les architectures supportées

Xenomai fonctionne sur les architectures suivantes :

  • ARM ;
  • Blackfin (DSP d'Analog Devices) ;
  • i386 ;
  • ia64 (Intel Itanium) ;
  • Power PC ;
  • x86_64 (Intel : Pentium 4, Pentium D, Pentium Extreme Edition, Celeron D, Xeon, Pentium Dual-Core ;
  • AMD : Athlon 64, Athlon 64 FX, Athlon 64 X2, Turion 64, Turion 64 X2, Opteron, Sempron).

Le portage de Xenomai sur une autre architecture revient dans les faits à porter ADEOS. ADEOS joue un rôle de couche d'abstraction matérielle.

V-D. Les modes d'exécution

Les tâches Xenomai « courantes »(28) s'exécutent en mode utilisateur. Le code Xenomai a ainsi l'énorme avantage de tourner sous debugger.

Attention à ne pas confondre primary mode avec kernel mode et secondary mode avec user mode :
  • primary et secondary désignent les schedulers ;
  • user et kernel désignent le mode d'exécution et donc les ressources accessibles.

V-E. L'API native et les skins

Xenomai fournit une API très complète avec les fonctionnalités temps réel suivantes :

  • tâches avec 99 niveaux de priorité, round robin optionnel…
  • files de messages ;
  • allocation dynamique de mémoire spécifique RT ;
  • sémaphores ;
  • watchdogs ;
  • timers ;
  • mutexes ;

Cette API, dite « native », est complétée par des skins. Ce sont des API d'autres RTOS (pSos, VxWorks…) qui encapsulent des appels natifs.

Les skins sont destinées au portage d'applications existantes ou à du prototypage.

Dans le cas des tâches VxWorks, il y a d'ailleurs un problème de translation vers le secondary mode. En effet, les priorités VxWorks vont de 1 (la plus forte) à 255 (la plus faible), ce qui est incompatible avec les 99 niveaux de la classe SCHED_FIFO/RR.

Deux adaptations sont donc réalisées : une inversion et surtout un nivellement. Deux tâches lancées via la skin VxWorks avec les priorités 150 et 220, auront en fait la même priorité en secondary mode.

Attention à la correspondance des priorités en utilisant la skin VxWorks.

V-F. Solutions concurrentes du marché

La principale solution du marché pour le temps réel dur est l'incontournable VxWorks de WindRiver qui présente l'avantage d'avoir une liste de Board Support Packages sur étagère impressionnante.

À noter également, le produit IntervalZero RTX qui permet de faire du temps réel dur tout en gardant la partie « utilisateur » de Windows, à la manière du couple Xenomai/Linux. Il semblerait que la diffusion de ce produit soit cependant assez confidentielle en France.


précédentsommairesuivant
nanokernel est le terme consacré dans la documentation, le terme d'« hyperviseur » peut également correspondre.
Enfonçons encore un peu plus le clou : dans tous les cas le terme « tâche en secondary mode » désigne implicitement une tâche Xenomai.
La première option est implémentée par RTAI/LXRT.
Ou SCHED_RR, tout dépend des options.
Ce point sera plus amplement détaillé dans le chapitre Méthodologie de développement.
Sauf dans la skin VxWorks, cf. §5.E.
Par opposition aux tâches Xenomai en mode noyau, manipulables depuis la skin RTDM.

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+