L'exécutif VxWorks
Frank Singhoff
L'objectif de ce TP est de vous familiariser avec
l'exécutif VxWorks. La première partie doit vous permettre
de configurer votre environnement. Puis, dans les parties
suivantes, les outils de gestion des tâches, de synchronisation
et de communications vous seront présentés.
Pour la signature des différentes primitives VxWorks, n'oubliez
pas que vous disposez du man et des livres de références
(cf. extrait du man VxWorks).
Avant d'écrire et d'exécuter notre premier programme, nous allons
configurer puis démarrer la cible 68000/VME.
Conseil : lisez l'intégralité de l'exercice I. avant
d'effectuer les différentes opérations décrites.
Pour démarrer la cible, récuperez tout d'abord le fichier
vx.csh et utilisez la
commande source vx.csh pour mettre à jour
les différentes variables d'environnement nécessaires.
Puis, effectuez
les opérations suivantes :
- Récupérez le fichier
.rhosts et copiez le dans la
racine de votre repertoire personnel ($HOME).
- Le shell VxWorks ne supporte pas certaines définitions
utilisées dans les shell Unix :
afin d'éviter les conflits, renommez votre .cshrc.
-
Connectez la carte par la liaison série. Pour ce faire,
lancer la commande connect A.
- Le message suivant apparait alors :
Press any key to stop auto-boot
le chargeur commence le démarrage de la cible.
Interrompez alors le démarrage en pressant une touche quelconque du clavier. Si le message ci-dessus
n'apparait pas, pressez les touches CTRL et X.
Une fois le chargeur
démarré, le prompt suivant doit être affiché :
[VxWorks Boot]:
Modifiez avec la commande c les paramètres de démarrage.
Le paramètre user est à modifier (à positionner
avec son nom de login UNIX).
Pour certaines cartes, il est aussi nécessaire de donner son mot de passe
(il est conseillé d'essayer sans, puis, si l'exécutif ne peut être démarré,
d'essayer avec le mot de passe). Attention : après le TP n'oubliez pas d'effacer votre mot de passe et de supprimer le fichier .rhosts.
Pour effacer un champs lorsque vous modifiez les paramètres, il faut
saisir le caractère "." dans le champs en question (ex champs "ftp password").
A titre d'exemple, sur la machine iup303 pour l'utilisateur singhoff, les paramètres
doivent être positionnés ainsi :
[VxWorks Boot]: p
boot device : ei
processor number : 0
host name : iup303
file name : /usr/local/tempsreel/VXWORKS/config/mv162/vxWorks
inet on ethernet (e) : 172.18.9.15:ffffff00
host inet (h) : 172.18.9.203
user (u) : singhoff
ftp password (pw) (blank = use rsh) :
flags (f) : 0x0
target name (tn) : vxaix
- Lancez le chargement de l'exécutif VxWorks par la commande
@
- Une fois l'exécutif
démarré, le prompt -> doit être affiché. La cible
est alors prête pour l'exécution de vos programmes.
Une aide en ligne est disponible sur le shell VxWorks grâce à
la commande help.
Nous allons maintenant tester le fonctionnement de la cible
en exécutant un programme VxWorks simple.
Pour ce faire :
- Récupérez
ce programme de test.
Pour invoquer le compilateur croisé et générer du
code 68000, vous disposez
du script comp68k. Sur l'hôte, invoquez donc la
commande suivante :
comp68k hello.c
Ce qui doit générer un module objet hello.o.
- Chargez le module objet dans la cible par la commande :
ld < hello.o
- Vous pouvez, finalement, exécuter sur la cible le programme
par la commande :
sp helloWorld
Ce qui crée une tâche VxWorks dont le code est la fonction helloWorld.
Cet exercice va vous permettre d'expérimenter les services
d'ordonnancement de l'exécutif VxWorks.
- Soient deux tâches périodiques dont les paramètres sont :
- T1 : période=1 seconde, capacité=200 milli-seconde. Echéance
égale à la période.
- T2 : période=400 milli-seconde, capacité=100
milli-seconde.
Echéance égale à la période.
- Déterminez "à la main" l'ordonnancement à obtenir.
- Complétez
ce programme
afin de créer les tâches
ordonnancées selon la méthode Rate Monotonic
(les zones à compléter sont signalées par des
étoiles).
Le code exécuté par ces tâches est implanté par
la fonction tache. Vous devez passer la capacité
et la période comme paramètres lors de la création
des tâches.
Vous utiliserez les primitives tickGet
et taskDelay pour générer
les périodes d'activation des tâches.
Les deux tâches doivent "démarrer" au même instant ;
pour ce faire
votre solution doit garantir que la tâche lancée par le shell VxWorks
ne soit pas préemptée avant la fin de
la création des tâches périodiques (NB :
la priorité d'une
tâche crée par la commande sp du shell VxWorks est 100).
Vous exécuterez l'application par la commande :
sp init
Le modèle mémoire de l'exécutif VxWorks est simple : toutes les
tâches se partagent un unique espace d'adressage.
Ce modèle s'applique aussi aux entrées sorties.
En effet :
-
Il n'existe qu'une seule table de descripteurs de
fichier et elle est partagée par toutes les tâches
du système ; contrairement à UNIX où une table existe
pour chaque processus.
Ainsi, si une tâche ouvre un fichier et
acquiert un descripteur, n'importe quelle autre
tâche peut effectuer des écritures et des lectures à
l'aide de ce descripteur.
Seuls les descripteurs 0, 1 et 2 (entrées et sorties
standards) peuvent être privées à une tâche.
- Il n'y a pas de fermeture automatique des
fichiers lorsqu'une tâche invoque la primitive exit().
La fermeture des fichiers doit donc être effectuée de
façon explicite.
Pour illustrer la mise en oeuvre de section critique
sur VxWorks, nous allons utiliser
les opérations sur fichiers :
- Récupérez le programme
verne.c
ainsi que le
fichier
verne.txt .
Etudiez le programme verne.c.
- Compilez et
exécutez verne.c.
Vous exécuterez l'application par la commande :
sp init
- Un fichier resultat.txt est alors généré.
Que constatez vous ? Pourquoi ?
- Utilisez un sémaphore de type mutex pour
supprimer ce comportement. Vous avez besoin
des primitives semMCreate,
semGive et semTake.
Soit le programme
prodcons.c :
- Compilez, testez et étudiez ce programme. Ce programme implante un producteur/consommateur.
La taille du tampon partagé entre les tâches est d'un caractère.
Un producteur insère les données caractère par caractère.
Un consommateur retire les données caractère par caractère.
Le tampon est géré de façon FIFO.
nb_plein modélise le nombre de cases pleines.
nb_vide modélise le nombre de cases vides.
- Modifiez le programme prodcons.c afin que la taille du tampon soit de 4 caractères.
On suppose toujours que le producteur insère les données caractère par caractère et
que le consommateur
retire les données caractère par caractère. Le tampon doit toujours être géré de façon FIFO.
- Modifiez le programme prodcons.c de sorte que plusieurs consommateurs et plusieurs
producteurs puissent manipuler le tampon.
Pour illustrer les outils de synchronisation offerts par VxWorks, on
souhaite implanter un problème (très) classique de
synchronisation : le problème des philosophes.
Ce problème est le suivant : NB_PHILOSOPHES sont assis autours
d'une table ronde. Chaque philosophe a devant lui un plat de
spaghetti. Pour manger, un philosophe a besoin de 2 fourchettes.
Une fourchette sépare deux assiettes adjacentes
(cf. figure ci-dessus).
Un philosophe occupe son temps de la façon suivante :
- Il ne fait rien pendant une durée quelconque (en fait ... il
pense).
- Puis, il prend les deux fourchettes
situées autours de lui et se met à manger des spaghetti.
La mise en oeuvre d'un tel schéma de synchronisation peut aboutir, si
l'on n'y prend pas garde, à un interblocage : en effet, si l'allocation
des fourchettes s'effectue fourchette par fourchette, chaque philosophe
peut allouer une seule fourchette et donc conduire à une non vivacité
du système.
La solution qui est généralement
préconisée consiste, soit à allouer les deux fouchettes
si celles-ci sont libres, soit aucune d'entre elles.
Pour ce faire, on peut utiliser le paradigme des
sémaphores privés qui se compose :
- D'un ensemble de variables stockent
l'état du système. Ces variables sont accedées en
exclusion mutuelle afin de garantir une consultation/modification
cohérente.
- D'un sémaphore par tâche (cad par philosophe), initialisé
à zéro, qui permet de bloquer une tâche demandant une
ressource déjà allouée (cad de bloquer un
philisophe s'il ne peut obtenir les deux fourchettes).
- D'une fonction qui permet de tester la disponibilité
des ressources et de les allouer par la mise à jour des variables d'état.
- D'une fonction qui permet de libérer les ressources et d'eventuellement
réveiller les tâches en attente de celles-ci. Cette dernière fonction
accède aussi aux variables d'état.
Compléter le programme
suivant
par les outils de synchronisations
nécessaires à la résolution du problème des philosophes.
Vous utiliserez des sémaphores à compteurs et mutex de VxWorks.
Les zones à compléter sont indiquées par des étoiles.
On vous demande
de compléter le programme
pipeline.c
qui convertit des nombres en base 10 vers la base 2.
Ce programme utilise un pipe-line de 8 tâches.
Chaque tâche
effectue les opérations suivantes :
- Une tâche du pipeline doit être initialement bloquée sur un sémaphore.
- Une tâche i est débloquée par la tâche qui la précède
dans le pipeline. Lorsque une tâche i est débloquée, elle
affiche 0 ou 1 selon que le nombre reçu par la tâche soit divisible ou non par deux.
- Puis, elle transfert le nombre divisé par 2 à la tâche suivante (sauf si le nombre divisé est égal à zéro).
La dernière tâche du pipe-line doit afficher une erreur si le nombre à convertir
dépasse la capacité du pipe-line.
Pour déclencher la conversion, vous affecterez, depuis le shell,
le nombre à convertir à la variable a_convertir. Puis,
vous lancerez la convertion en executant depuis le shell, la fonction
lance
Remarque : tel que le pipe-line est décrit ici, le résultat de la conversion doit normalement afficher le nombre en base 2 à l'envers.
Dans cet exercice, nous allons simuler un protocole (simple)
permettant d'éviter les phénomènes d'inversion de priorité.
Soient quatre tâches périodiques dont les paramètres sont les suivants :
Tâche |
Période |
Capacité |
Priorité fixe attribuée selon RM |
Ta |
6 |
2 |
110 |
Tb |
7 |
2 |
120 |
Tc |
8 |
1 |
130 |
Td |
20 |
4 |
140 |
Les tâches Ta et Td accèdent à une ressource en exclusion
mutuelle et ce durant toute leur capacité.
Les tâches Tb et Tc n'utilisent pas cette ressource.
Travail à faire :
-
Dessinez l'ordonnancement généré par RM (mode préemptif)
sur les 20 premières unités de temps.
- Identifiez l'intervalle de temps où se situe
l'inversion de priorité.
- Récupérez les fichiers
inv.c, ressource.c et
ressource.h. Le premier fichier créée les tâches
Ta,Tb,Tc et Td conformément aux paramètres ci-dessus. Les deux derniers fichiers
simulent un accès exclusif à une ressource.
- Compilez et chargez sur la cible les deux modules objets.
Vous exécuterez l'application par la commande :
sp init
- Vérifiez que l'ordonnancement généré correspond bien à
celui prévu dans la question 1.
- On se propose maintenant
d'expérimenter un protocole d'héritage évitant
l'inversion de priorité. Le protocole est simple : lorsqu'une tâche A souhaite accèder
à la ressource et si une tâche B de plus faible priorité
possède déjà cette ressource.
Alors la tâche B hérite de la priorité de la tâche A.
Lorsque la tâche B libère la ressource, elle récupère sa priorité
initiale.
- Récupérez les
fichiers inv2.c, ressource-h.c et
ressource-h.h.
Implantez le protocole décrit ci-dessus, vous devez compléter
les zones indiquées par les étoiles.
- Tester votre solution et constatez la suppression de l'inversion de priorité.
PS : il est possible de déterminer l'ordonnancement que doit générer votre
solution en utilisant les fichiers
inv.c,
ressource.c et
ressource.h.
Pour
ce faire, vous devez modifier l'initialisation du mutex dans
le fichier ressource.c
en remplaçant l'option SEM_Q_FIFO par
SEM_INVERSION_SAFE | SEM_Q_PRIORITY.
Dans cet exercice, nous allons utiliser les outils de communication
de VxWorks, et en particulier les files de messages.
Nous allons mettre en oeuvre le paradigme du producteur/consommateur :
-
Récupérer
le programme
suivant.
- Ajouter les opérations de création de tâche ainsi que les
opérations de communication.
Vous avez besoin des primitives
msgQCreate,
msgQReceive
et
msgQSend.
Les zones à compléter sont signalées par des étoiles.
-
Vous exécuterez l'application par la commande :
sp init
En guise de conclusion pour cette initiation à VxWorks, nous vous proposons de vous montrer
comment fonctionne la mise au point à distance d'un programme.
Pour ce faire choisissez un des programmes de ce TP. Pour mettre au point ce dernier, effectuez
les opérations suivantes :
Page maintenue par Frank Singhoff
(singhoff@univ-brest.fr)
Dernière mise à jour le 1er février 2001