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).



I. Démarrage de la cible

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 :

  1. Récupérez le fichier .rhosts et copiez le dans la racine de votre repertoire personnel ($HOME).
  2. Le shell VxWorks ne supporte pas certaines définitions utilisées dans les shell Unix : afin d'éviter les conflits, renommez votre .cshrc.
  3. Connectez la carte par la liaison série. Pour ce faire, lancer la commande connect A.
  4. 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

  5. Lancez le chargement de l'exécutif VxWorks par la commande

    @

  6. 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.

II. Hello world : test de l'environnement

Nous allons maintenant tester le fonctionnement de la cible en exécutant un programme VxWorks simple. Pour ce faire :
  1. 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.

  2. Chargez le module objet dans la cible par la commande :

    ld < hello.o

  3. 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.


III. Tâches et ordonnancement

Cet exercice va vous permettre d'expérimenter les services d'ordonnancement de l'exécutif VxWorks.

III.1 Création de tâches


III.2 Rate Monotonic


  1. 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.

  2. Déterminez "à la main" l'ordonnancement à obtenir.
  3. 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





IV. Outils de synchronisation



IV.1 Accès concurrent : paradigme de la section critique


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 :

Pour illustrer la mise en oeuvre de section critique sur VxWorks, nous allons utiliser les opérations sur fichiers :

  1. Récupérez le programme verne.c ainsi que le fichier verne.txt . Etudiez le programme verne.c.
  2. Compilez et exécutez verne.c.

    Vous exécuterez l'application par la commande :

    sp init

  3. Un fichier resultat.txt est alors généré. Que constatez vous ? Pourquoi ?
  4. Utilisez un sémaphore de type mutex pour supprimer ce comportement. Vous avez besoin des primitives semMCreate, semGive et semTake.



IV.2 Producteurs/consommateurs : paradigme du compteur de ressources


Soit le programme
prodcons.c :
  1. 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.
  2. 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.
  3. Modifiez le programme prodcons.c de sorte que plusieurs consommateurs et plusieurs producteurs puissent manipuler le tampon.




IV.3 Le problème des philosophes : paradigme des sémaphores privés


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 :

  1. Il ne fait rien pendant une durée quelconque (en fait ... il pense).
  2. 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 :

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.


IV.4 Le roi du pétrole



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 :

  1. Une tâche du pipeline doit être initialement bloquée sur un sémaphore.
  2. 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.
  3. 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.



IV.5 Inversion de priorité

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 :

  1. Dessinez l'ordonnancement généré par RM (mode préemptif) sur les 20 premières unités de temps.
  2. Identifiez l'intervalle de temps où se situe l'inversion de priorité.
  3. 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.
  4. Compilez et chargez sur la cible les deux modules objets. Vous exécuterez l'application par la commande :

    sp init

  5. Vérifiez que l'ordonnancement généré correspond bien à celui prévu dans la question 1.
  6. 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.
  7. 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.
  8. 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.




V. Outils de communication

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 :






VI. Manipulation de vxgdb


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