IV. Linux et le(s) temps réel▲
Xenomai est une des réponses à la question « Comment faire du temps réel dur avec Linux ? ».
IV-A. Les avantages et les inconvénients de Linux pour les applications temps réel▲
Comme il est assez hasardeux de généraliser, on considère ici un besoin de type contrôle/commande RT à travers des interfaces série (RS422/485 et consorts), c'est-à-dire quelque chose qui puisse être mis en œuvre grâce à du matériel standard ; financièrement l'utilisation de Xenomai est très intéressante.
Pour la partie logicielle, le calcul est simple puisqu'avec une distribution Linux gratuite et Xenomai, on arrive à un total de… 0 €. Quant au matériel, son coût tourne autour de quelques milliers d'euros au maximum.
D'autres solutions propriétaires(17) auraient ici plusieurs inconvénients (en plus du côté « propriétaire ») : le prix de la partie matérielle serait beaucoup plus élevé et le développement nécessiterait l'acquisition de licences.
Quelle que soit la technologie utilisée, il ne faut jamais négliger les coûts et les durées de formation ou de prise en main.
Pour Linux et Xenomai, l'autoformation reste cependant la pratique la plus répandue.
Pour la résolution de problèmes complexes, une expertise externe peut apporter un gain de temps intéressant.
Néanmoins, il faut garder à l'esprit que dans les applications industrielles, l'intégration matériel/logiciel est une étape critique et coûteuse. Les fournisseurs de solutions propriétaires ont déjà fait ce travail pour vous (mise au point de drivers, certification de matériel, intégration à l'environnement de développement).
Si vous employez du matériel spécifique, le support de la Communauté sera limité par la difficulté à reproduire vos problèmes (mise au point de drivers en particulier).
IV-B. Comment faire du temps réel avec Linux : les approches possibles▲
IV-B-1. Aucune préemption forcée▲
Comme nous l'avons vu, par défaut, le code exécuté en mode noyau n'est pas préemptible. Dans cette configuration, les changements de contexte sont réduits : le CPU est disponible pour les calculs et le cache est efficace.
La latence généralement constatée (non garantie) est de l'ordre de la dizaine de millisecondes(18).
L'activation de la préemption à l'intérieur du noyau dégrade les performances globales du système ( overhead).
IV-B-2. Une première possibilité : l'option Voluntary Kernel Preemption▲
Cette option insère des points de descheduling supplémentaires. Concrètement, les appels système relancent volontairement le scheduler dans leur déroulement.
Ces appels modifient peu le code car ils redéfinissent simplement la fonction de débogage might_sleep() déjà existante et la font appeler le scheduler.
Dans cet exemple, extrait du fichier kernel/cpu.c 2.6.25 :
void
get_online_cpus
(
void
)
{
might_sleep
(
);
...
}
IV-B-3. Pour du temps réel « mou » : Preemptible Kernel (Low-Latency Desktop)▲
La préemption volontaire n'est qu'un artifice comparé à cette option : ici tout le noyau (hors sections critiques) devient préemptible.
Dans le code, il est alors nécessaire d'identifier les sections critiques afin de désactiver la préemption à l'intérieur de celles-ci. Travail volumineux me direz-vous, mais pas titanesque. En effet, la redéfinition des mécanismes ajoutés par nos amis du SMP couvre une partie de nos besoins.
L'exemple ci-dessous (2.6.25.4/fs/fat/inode.c) montre l'innocuité de cette option sur une section critique protégée par un spinlock :
void
fat_attach
(
struct
inode *
inode, loff_t i_pos)
{
struct
super_block *
sb =
inode->
i_sb;
struct
msdos_sb_info *
sbi =
MSDOS_SB
(
sb);
spin_lock
(&
sbi->
inode_hash_lock);
...
spin_unlock
(&
sbi->
inode_hash_lock);
}
Le pseudocode spin_lock :
int
spin_lock
(
spinlock_t *
lock)
{
preempt_disable
(
);
...
}
Et dans preempt_disable :
#ifdef CONFIG_PREEMPT // Correspond à l'option low-latency desktop
...
#define preempt_enable() {réactivation de la préemption et rescheduling si nécessaire}
#else
#define preempt_enable() {CONFIG_PREEMPT_NONE : on ne fait rien du tout}
#endif
Les versions standard 2.6 peuvent être une solution, rendant ainsi Linux immédiatement opérationnel. La latence maximale est alors de l'ordre de la milliseconde.
IV-B-4. Le temps réel avec le patch PREEMPT_RT▲
Ce patch, élaboré par Ingo Molnar, ainsi que sa documentation sont disponibles à l'adresse http://rt.wiki.kernel.org/index.php/Main_Page.
Le principe est de rendre « totalement » préemptible le code du noyau, la latence est ainsi abaissée à moins de 50 µs.
Afin de bien comprendre quelles sont les modifications apportées, il faut revenir sur ce qui n'était pas encore préemptible : les sections critiques (au nombre de 11 000 !) et les handlers d'interruption. Grâce à ce patch, ces sections le sont désormais et celles protégées par des spinlock ou des sémaphores supportent l'héritage de priorité.
Les développements d'applications RT reposent sur l'API POSIX classique.
IV-B-4-a. Drivers▲
Les drivers du vanilla kernel étant affectés par le patch, cela signifie qu'ils peuvent être directement utilisés dans un contexte temps réel. L'emploi de drivers extérieurs au vanilla kernel (pilotage d'une carte spécifique), nécessitera probablement une adaptation.
IV-B-4-b. Limitations actuelles et évolutions▲
Le patch atteint presque les 60 000 lignes(19), ce qui modifie par conséquent sensiblement le code du noyau. À l'heure actuelle, il n'est disponible que pour les architectures x86 et ARM.
La feuille de route prévoit une intégration progressive du patch à la mainline du vanilla kernel.
IV-B-5. Le temps réel dur avec les co-noyaux▲
Une autre approche consiste à se reposer sur un micronoyau pour satisfaire les contraintes temps réel. Ce micronoyau gère alors le scheduling des tâches temps réel, les timers, les interruptions et la communication entre processus. Linux reste utilisé pour les services non temps réel qu'il procure (connectivité réseau, USB…) et devient une simple tâche du micronoyau.
Xenomai repose sur ce principe.