Travaux Pratiques sur la Programmation de Serveurs Apériodiques

Index


1 Programmer des serveurs périodiques de tâches apériodiques en POSIX-C


1.1 Introduction

L’objectif de ce travail consiste à mettre en oeuvre une politique d’ordonnnancement de type RMS puis différents types de serveurs périodiques de tâches apériodiques.

Vous pouvez suivre les liens suivants pour trouver les sources et les transparents du cours Ordonnancement Temps Réel.

Pour décompresser l’archive faire :

gunzip src.tar.gz
tar xf src.tar

1.2 Architecture générale


1.2.1 Identifier les fichiers concernés

En termes de programmation, vous n’aurez qu’à compléter des fichiers déjà existants (periodictasks.c) et notamment les diverses implémentations des serveurs de tâches apériodiques (backgroundserver.c, sporadicserver.c, pollingservers.c, deferred_servers.c).


1.2.2 Identifier où faire les modifications

Sur la forme, les morceaux de code à modifier sont indiqués par un appel à la fonction NYI (Not Yet Implemented) qui prend comme paramètre une chaîne de caractères vous indiquant le type de modification à apporter. Il est en général précédé d’un commentaire explicitant ce qu’il convient de faire.


1.2.3 Identifier comment faire les modifications

Sur le fond, votre travail consistera à insérer le code permettant de "configurer" et "gérer" l’activité de ces serveurs de tâches apériodiques pour respecter la périodicité, le comportement des serveurs, la recherche d’évènements dans la file associée aux serveurs, le traitement des évènements.

Le TP ne requiert pas de compétences particulières en termes de programmation C ou POSIX, ou RT-POSIX.


1.2.4 Evaluer vos modifications

Dans ce TP, nous vous proposons différentes configurations de tâches logiques que vous devez faire exécuter correctement. Ces configurations ou scénarii se trouvent décrits dans le fichier scenarii.c. Ils portent un numéro de 1 à 7. Lorsque l’on vous demandera de vérifier que l’implantation d’une fonctionnalité est correcte il s’agira de vérifier que l’un de ces scenarii se déroule correctement. Ces différents scenarii correspondent à ceux présents dans le cours.

On sélectionnera un scenario (par exemple le scenario 3) au lancement en exécutant la commande :

make
./runapsvr 3

Lorsque vous exécutez, le programme ./runspsvr en fournissant un numéro de scenario en argument, les caractéristiques des tâches de celui-ci sont rappelées en début d’exécution.


1.2.5 Comprendre l’architecture de l’application

Les sources fournies vous permettent d’exécuter des tâches périodiques sous forme de threads POSIX. Une tâche logique décrite dans le scenario par un ensemble de données est associée à une tâche physique de l’API POSIX (c’est à dire un thread POSIX). La procédure principale de ce thread se trouve décrite dans runPeriodicTask du fichier periodictasks.c.

Ces tâches physiques sont ordonnées par un processeur dont nous simulons et contrôlons l’activité. En effet, chaque tâche physique ou thread POSIX peut demander à avoir accès au CPU. En fonction de sa priorité (selon la politique RM), le processeur lui attribuera ou non une unité de temps de temps et simulera une unité de temps d’exécution.

La fonction computeDuringTimeSpan fait ainsi exécuter une tâche pendant une certaine quantité de temps lorsque celle-ci devient prioritaire pour le processeur. Plusieurs fonctions décrites dans le fichier tasks.h permettent de controler l’activité de ces tâches. Celles que vous devez utiliser dans ce travail sont indiquées au début du fichier.


1.3 Tâches périodiques

Pour découvrir l’architecture de l’application, nous allons terminer l’implantation des tâches périodiques et plus particulièrement de leur procédure principale runPeriodicTask dans periodictasks.c. Il s’agit faire en sorte que la tâche logique s’exécute pendant son budget et attendre sa prochaine activation.

Vous pouvez évaluer votre travail en utilisant les scenarii de 1 à 3. Le premier est très simple, le deuxième échoue et le troisième correspond au deuxième en termes d’utilisation, mais dont les temps de calcul et les périodes ont été modifiées. Ces exemples sont présents dans le cours. Des sorties de réference sont fournies dans les fichiers scenario-<N>.ref où N varie entre 1 et 7.

Pour comparer votre exécution à celle de référence :

make
./runapsvr 1 > scenario-1.log
diff scenario-1.log scenario-1.ref

Attention : il peut y avoir des différences d’affichage.

49d48
< p1 40 activated
50a50
> p1 40 activated

Comme certains événements arrivent simultanément, il arrive que ceux-ci soient signalés dans un ordre aléatoire. Typiquement, lors que p1 et p2 ont des activations simultanées.


1.4 Serveurs périodiques de tâches apériodiques

De même que pour les tâches logiques périodiques lorsqu’un scenario est selectionné, toutes les tâches logiques apériodiques associées à ce scenario sont ajoutées au tableau aperiodicTaskTable.

A la différence des tâches logiques périodiques, les tâches logiques apériodiques ne sont pas associées à des tâches physiques ou threads POSIX. Elles sont retranscrites en une structure Event décrite dans le fichier events.h puis seront stockées dans un tableau eventTable.

Lorsque le programme démarre, les tâches apériodiques sont donc retranscrites en événements de type Event. Ces événements seront pris en compte par les serveurs de tâches apériodiques. Plusieurs autres événements viendront se rajouter à ce tableau et notamment les événements de gestion de budget de temps des serveurs de tâches apériodiques (comme le réapprovisionnement des budgets de temps).

Pour comprendre la différence entre événements et tâches apériodiques, nous allons dérouler une exécution. Lorsqu’une tâche apériodique doit être activée à la date T=7s et nécessite un temps de calcul C=3s, un événement de type CONSUME (de temps de calcul) équivalent est créé.

A la date T=7s, cet événement peut être traité et supposons que seulement 2s de calcul puissent lui être consacrées. Nous aurons donc besoin de générer un nouvel événement d’activation T=7s mais de temps de calcul C=1s puisqu’un calcul de 2s a déjà été consacré à la tâche apériodique.

Un serveur de tâches apériodiques qui voudrait produire un réapprovisionnement de son budget à la date T=8s pour une valeur de C=2s peut générer un événement de type PRODUCE en indiquant une date d’activation T=8s et un temps de calcul C=2s.

Les fonctions removeEvent et appendEvent permettent d’extraire et d’ajouter des évenements dans la table en gardant celle-ci triée par ordre d’activation. D’autres fonctions servent à gèrer cette table.


1.5 Serveur tâche de fond

La mise en oeuvre du serveur en tâche de fond s’effectue en complètant la procédure principale runBackgroundServer qui se trouve dans le fichier backgroundserver.c.

Nous rappelons que le serveur en tâche de fond ne gère pas de budget de calcul.

Vous devez complèter ce fichier pour mettre en oeuvre le principe de server en tâche de fond.

Les modifications à apporter sont les suivantes :

Vous pourrez évaluer vos modifications en déroulant le scenario 4 et en vérifiant à l’aide du fichier scenario-4.ref.

make
./runapsvr 4

1.6 Serveur en scrutation

La mise en oeuvre du serveur en scrutation s’effectue en complètant la procédure principale runPollingServer qui se trouve dans le fichier pollingserver.c.

Vous devez complèter ce fichier pour mettre en oeuvre le principe de server en scrutation.

Nous rappelons que le serveur en scrutation gère un budget de calcul. En début de période, il traite les événements présents dans la limite de son budget. S’il lui reste du budget une fois les événements présents traités, il renonce à celui-ci. Il sera renouvellé au moment de sa période au travers d’un événement PRODUCE.

Les modifications à apporter sont les suivantes :

Vous pourrez évaluer vos modifications en déroulant le scenario 5 et en vérifiant à l’aide du fichier scenario-5.ref.

make
./runapsvr 5

1.7 Serveur différé

La mise en oeuvre du serveur différé s’effectue en complètant la procédure principale runDeferredServer qui se trouve dans le fichier deferredserver.c.

Vous devez complèter ce fichier pour mettre en oeuvre le principe de server différé.

Nous rappelons que le serveur différé gère un budget de calcul. En début de période, il traite les événements présents dans la limite de son budget. S’il lui reste du budget une fois les événements présents traités, à la différence du serveur en scrutation, il ne renonce pas à ce budget. L’intégralité sera renouvellée au moment de sa période.

Les modifications à apporter sont les suivantes :

Vous pourrez évaluer vos modifications en déroulant le scenario 6 et en vérifiant à l’aide du fichier scenario-6.ref.

make
./runapsvr 6

1.8 Serveur sporadique

La mise en oeuvre du serveur sporadique s’effectue en complètant la procédure principale runSporadicServer qui se trouve dans le fichier sporadicserver.c.

Vous devez complèter ce fichier pour mettre en oeuvre le principe de server sporadique.

Nous rappelons que le serveur sporadique gère un budget de calcul. Il traite les événements présents dans la limite de son budget. A la différence des serveurs précédents, il ne programme pas son réapprovisionnement de budget en début de période. Lorsqu’il utilise une certaine quantité de calcul, il programme un réapprovisionnement de son budget à la hauteur de ce qu’il utilise à la date de consommation plus sa période.

Les modifications à apporter sont les suivantes :

Vous pourrez évaluer vos modifications en déroulant le scenario 7 et en vérifiant à l’aide du fichier scenario-7.ref.

make
./runapsvr 7