TP Xenomai¶
Documentation¶
-
Un très bon tutoriel complet à lire ici
-
les explications sur ce qu'est Xenomai, quels problèmes il résoud, et comment il le fait sont ici
-
Les API de Xenomai sont documentées ici
Test de l'environnement¶
Après avoir démarré vos machines avec l'image Xenomai, placez vous dans le répertoire /usr/lib/xenomai
(peut être légèrement différent sur les machines de l'école) et cherchez un exécutable nommé latency
. Lancez cet exécutable avec les privilèges administrateur.
Vous pouvez également essayer la commande dmesg | grep -i xenomai
pour vérifier que vous avez des sorties ressemblant à I-pipe: head domain Xenomai registered.
Si cela fonctionne, vous avez bien démarré le bon noyau, bravo.
HelloWorld¶
-
Vous allez chercher dans la documentation de Xenomai ou dans les répertoires de tests fournis comment écrire un programme très simple, qui lance une tâche à la plus haute priorité temps réel (99) pour afficher le message "Hello Real-time World", en utilisant
printf()
- au debut de votre main, ajoutez la ligne
mlockall( MCL_CURRENT | MCL_FUTURE );
afin de désactiver le mécanisme de swap mémoire sur disque pour votre application - création d'une tache avec
rt_task_create()
puis démarrage avecrt_task_start()
- ou bien les deux en même temps avec
rt_task_spawn()
rt_task_join()
dans le main après le démarrage de la tâche temps réel pour attendre sa terminaison.
- au debut de votre main, ajoutez la ligne
-
Pour compiler avec l'utilitaire
make
, vous allez avoir besoin d'unmakefile
un peu particulier. Reportez vous à cette page
Warning
attention, il faut bien travailler avec le skin alchemy (et pas vxworks). De plus il se peut que le script xeno-config, utilisé dans le makefile, existe en plusieurs version sur votre système. Il faut bien utiliser celui qui utilise le noyau cobalt, et pas mercury.
-
Si ca ne marche pas, vérifiez que vous êtes super-utilisateur pour lancer l’application.
-
Si ca ne marche toujours pas, essayez avec le code et le makefile de cette archive
-
Proposez une autre version du programme, en utilisant
rt_printf
à la place deprintf
.
Danger
Si ca ne marche pas, c'est peut-être que les librairies spécifiques à Xenomai ne sont pas installées, il va falloir le faire vous même, pour cela il faut suivre la documentation. Les étapes à suivre :
- Les sources devraient etre disponible dans le répertoire "/user/sources". Sinon téléchargez les sources de xenomai 3.1 ici https://xenomai.org/downloads/xenomai/stable/latest/
- décompressez l'archive et placez vous à la racine du repertoire obtenu puis tapez
scripts/bootstrap
- executez la commande
./configure
- executez la commande
make
- en tant que root, executez la commande
make install
Changement de contexte et passage en mode secondaire¶
Modifier vos deux programmes pour que l'affichage soit fait dans une boucle infini avec une attente d'1s :
Vous pouvez réaliser l'attente avec la fonctionrt_task_sleep()
.
Attention, cette fonction prend en parametre un nombre de tics, pas des nano secondes. Cherchez dans les API comment convertir.
-
Pour les deux versions du programme, pendant qu'elles s'exécutent (pas en même temps !), testez dans un autre terminal les commandes suivantes :
ps -eTo pid,ppid,ucmd,class,rtprio,nice --sort class
cat /proc/xenomai/sched/stat
cat /proc/xenomai/sched/threads
-
Expliquez les résultats obtenus.
- Pour une explication des sorties de cat, vous pouvez vous aider de cette page
- Regardez notamment les autres fichiers de
/proc/xenomai
-
Téléchargez cette archive et prenez le temps de regarder les commentaires dans le code. Compilez et executez d'abord en gardant la ligne
printf
puis en la remplacant par la lignert_printf
. Concluez.
Tâche périodique¶
Pour rendre une tâche périodique, deux choses :
-
Au début de la tâche, appeler
rt_task_set_periodic()
- astuce : une tâche peut obtenir un descripteur de type
RT_TASK
d'elle-même avec la fonctionrt_task_self()
- pour gérer le temps, le type à utiliser est
RTIME
et des constantes sont définies comme par exempleTM_NOW
- astuce : une tâche peut obtenir un descripteur de type
-
Entrer dans une boucle infinie (prévoyez dans la phase de debug de ne rentrer dans la boucle que 3 ou 4 fois...). Un passage dans la boucle correspond alors à une instance ou un job. Au début de la boucle, appeler la méthode bloquante
rt_task_wait_period()
: c'est elle qui va provoquer la suspension de la tâche jusqu'à sa prochaine activation périodique. -
Tester en faisant une tache qui affiche toutes les secondes le temps courant et la durée écoulée depuis le dernier affichage (voir fonction
rt_timer_read()
. Vérifiez empiriquement la précision de l'activation. -
générez maintenant un coût de 0,8s pour cette tâche grâce à la fonction
rt_timer_spin()
-
observez ce qu'il se passe si vous descendez la période à 0,5s en gardant le coût à 0,8
-
utilisez le paramètre de
rt_task_wait_period()
pour afficher le compteur de dépassement proposé par xenomai. Expliquez comment il fonctionne (si il fonctionne).
Influence de la charge système¶
- Ecrivez une tache périodique de période 1 ms qui affiche la durée écoulée entre deux activations périodiques en nanosecondes
- Exécutez le programme en redirigeant la sortie vers un fichier pendant quelques secondes (
a.out > fichier.log
par exemple) - Télécharger le code de calc-stat.c et compilez-le (avec la librairie mathématique, option -lm de gcc). Ce programme permet de calculer le minimum, la moyenne et l'écart type d'une grandeur se trouvant dans un fichier.
- utilisez-le pour obtenir des statistiques sur le fichier de résultat obtenu précédemment :
cat fichier.log | ./calc-stat
- refaites l'expérience mais en faisant tourner en parallèle la commande
dohell
fournie dans les répertoires de xenomai (commande qui génère de la charge parasite)
Mon système de tâche !¶
Proposez un programme qui lit les fichiers de description de systèmes de taches tels que définis au TP précédant et lance les taches périodiques correspondantes (utilisez rt_timer_spin()
) pour simuler les coûts.