



suivant: Bibliographie monter: Dossier Technique précédent: GNU/Linux comme système d'exploitation Table des matières
Le monde des Linux temps réel profite de la popularité du système d'exploitation GNU/Linux. Il bénéficie donc de l'immense base de documentation que représente Internet. D'autre part, sa particularité et son exploitation dans des conditions bien précises de l'informatique industrielle lui confère une place bien à part du grand tumulte Linux ! Cette place à l'écart ne l'empêche pas de faire parler de lui... Plusieurs initiatives ont vu le jour pour adapter Linux au temps réel ``dur''.
L'une des caractéristiques du Logiciel Libre est... sa liberté ! Dans le domaine émergeant des Linux temps réel, la multitude des offres requiert une étude approfondie des avantages et inconvénients de chaque système. Cette étude doit aussi prendre en compte la notoriété d'un produit, ses soutiens éventuels et leur solidité, enfin le support de mise en oeuvre et de documentation disponible sur Internet.
Le choix de RTLinux par rapport à RTAI s'est imposé dans cet environnement industriel pour plusieurs raisons:
Du fait des ses nombreuses fonctionnalités, de son support du temps réel ``mou'' depuis l'espace utilisateur, de sa gestion du système de fichier /proc (information système), et du développement de modules PERL, RTAI est un système extrêmement intéressant et particulièrement adapté à un développement dans un cadre universitaire ou de recherche et développement.
RTLinux apparaît plus adapté à l'industrie bien que, une fois encore,
RTAI prenne de plus en plus d'importance dans ce secteur.
Finalement, les deux systèmes sont excellents et il ne faut en négliger
aucun ! La compétition acharnée qu'ils se livrent parfois ne fait que stimuler
la créativité de leurs ``contributeurs''.
RTLinux est un système d'exploitation dans lequel cohabitent un micro-noyau temps réel et le noyau Linux. L'intention des concepteurs est de continuer d'utiliser les services de haut niveau du système à temps partagé, tout en permettant de fournir un comportement déterministe dans un environnement où le temps de latence est extrêmement faible. En effet, les systèmes temps réel ont souvent besoin d'un support réseau, d'une interface graphique, d'un système de fichier et éventuellement d'un accès à une base de données. Ceci peut être fourni par un système d'exploitation ``monobloc'' où tout service est intégré dans un environnement temps réel, comme LynxOs. Une autre solution est de consacrer une machine aux applications temps réel et la faire communiquer avec d'autres gérant les services non temps réel.
La troisième voie adoptée par RTLinux est celle qui permet à un micro-noyau d'exécuter le véritable noyau Linux comme sa tâche de plus faible priorité. RTLinux implémente en fait une sorte de machine virtuelle pour que le noyau Linux standard soit complètement préemptif. Dans cet environnement, toutes les interruptions sont initialement prises en compte par le noyau temps réel et sont passées à Linux seulement s'il n'y a pas de tâche temps réel à exécuter.
Pour minimiser les changements dans le noyau Linux, les concepteurs ont émulé le contrôleur d'interruptions matériel. Ainsi, quand Linux masque une interruption, celle-ci est quand même prise en compte par RTLinux et aiguillée vers une file d'attente si elle n'est pas utile au niveau du micro-noyau. Lorsque Linux rétablit la possibilité de traiter les interruptions, celles arrivées entre temps sont disponibles et peuvent être traitées par la routine de gestion d'interruptions de Linux (handler d'IT Linux dans la figure 5.1). Les codes assembleurs des processeurs i486 cli, sti et iret sont remplacés dans le noyau Linux par des macro-instructions S_CLI, S_STI et S_IRET. Toutes les interruptions matérielles sont attrapées par l'émulateur qui distribue des interruptions logicielles (soft interrupts).
Les tâches temps réel suivent les spécifications de la norme POSIX.1c décrivant les threads. Elles peuvent êtres application utilisateur, service fourni par l'environnement RTLinux ou pilote de périphérique. Chargées comme module noyau, elles s'exécutent en suivant les ordres dictés par le scheduler. Le temps CPU est fourni à la tâche de plus haute priorité (scheduler de base RTLinux).
Ces ``kernel threads'' disposent des droits entiers sur la machine et peuvent accéder à toutes les ressources. Ils occupent tous le même espace d'adressage (celui du noyau !) et se chargent dynamiquement. Il résulte de ces trois points qu'il est délicat de développer un tel module. En effet, la moindre erreur de programmation, vite advenue en C du fait de la manipulation de pointeurs, est fatale au système. En revanche, cette architecture permet d'augmenter les performances en éliminant les temps de changement de niveau de protection et en raccourcissant le temps de changement de contexte. Toutes les ressources d'une tâche RTLinux sont allouées statiquement (exemples: mémoire, fifo).
La règle primordiale des développeurs sous RTLinux doit être:
Ceci s'applique naturellement aux pilotes de périphériques (device drivers) qui, s'ils n'ont aucune contrainte temps réel à tenir, restent inchangés. Ils doivent tout de même être recompilés dans l'environnement RTLinux (-D__RTL__ et rtl.mk) s'ils emploient les routines cli / sti.
RTLinux version 2 est structuré comme une partie centrale minimale sur laquelle vient se charger tout une collection de modules qui fournissent des services optionnels ou des niveaux d'abstraction. Ces modules sont par exemple:
Le consortium de normalisation POSIX entretient des relations d'attraction / répulsion avec le monde du temps réel et les concepteurs de RTOS. Il est souvent dit par la communauté temps réel que la normalisation de l'interface est un frein à la performance. Le processus est initié par les grands éditeurs d'UNIX qui se préoccupent de gros systèmes ou de systèmes de bureau. L'API proposée, même pour les extensions temps réel (POSIX.4 Draft 14 = P1003.1b), est assez lourde à mettre en oeuvre: de nombreux éditeurs s'en démarque. Par exemple QNX se contente de POSIX.1 (base: processus, fichiers, pipes...) et .2 (shell et utilitaires) ; LynxOS V2.2 y ajoute seulement un support de POSIX.4 Draft 10.
De plus, de part l'architecture originale de RTLinux, de nombreuses implémentations du standard sont impossibles (système de fichier). Un compromis à été trouvé par les concepteurs de RTLinux à savoir l'utilisation du ``Minimal Realtime System Profile'' (POSIX.13 Draft 9) reprenant les spécifications propres aux threads (POSIX.4a Draft 8 = P1003.1c) mais remplace la gestion d'un système de fichier par une simple interface d'entrées / sorties, suffisant pour un noyau de cette taille. RTLinux ajoute aussi un support SMP compatible avec cette norme.
Le principe de base de RTLinux reste, selon ses concepteurs, de ne pas céder à la compatibilité une quelconque perte de performance.
Cependant cet effort de normalisation est fait pour facilité le portage d'applications dans l'environnement RTLinux, pour bénéficier du ``vivier'' de programmateurs déjà habitués à POSIX et enfin, pour simplifier la compréhension du code et l'intégration dans l'environnement GNU/Linux. Le module rtl_posixio est donc à utiliser sans modération lors d'écriture de pilotes de périphériques !
L'installation se passe généralement sans encombre du moment où l'on a déjà compilé un noyau Linux. Les documents livrés avec la ``distribution'' sont assez bien faits. Une attention toute particulière va aux guides d'installation commentés par Phil Wilshire <philwil@on-ramp.ior.com> que l'on peut trouver à la racine de l'archive (du moins à partir de la version 2). Ce document est présent dans le recueil joint en annexes.
Une attention particulière sera portée à l'interface avec le matériel (exemples
de drivers). Sachant qu'il est demandé d'étudier des drivers pour carte ISA
puis PCI, les modes de programmation de telles cartes seront observés avec attention.
Exemples et drivers permettent d'aborder un aspect de la programmation dans
un environnement RTLinux :
La meilleure façon de se familiariser avec un système temps réel est quand même de l'utiliser pour sa raison d'être : l'interaction avec le ``monde réel''. Or, quelle interface avec l'extérieur est mieux adaptée que le port parallèle pour faire des entrées / sorties numériques ? Disponible sur la plupart des PC il est simple à programmer ; on peut néanmoins s'initier à l'utilisation de deux modes de fonctionnement : polling et interruptions tout en mettant en pratique les fonctions primordiales de l'API RTLinux. Attention toutefois à ne pas endommager le composant car il est implanté sur la carte mère : un court circuit ou une mauvaise alimentation en 5V pourrait gravement l'endommager !
|
La manière la plus simple de mesurer l'état de la broche ACK du port parallèle est de créer une tâche périodique qui se charge de lire l'état du bit. Quand on détecte que la valeur a changé, on envoie un message à un processus Linux par l'intermédiaire d'une RT-FIFO. Celui-ci doit être en attente de lecture sur cette FIFO. Le processus Linux peut alors afficher le changement d'état de la broche.
Un autre moyen de mesurer les changements sur la broche ACK consiste à installer un gestionnaire d'interruptions sur l'interruption #7. Cette autre solution dispense de l'usage d'une tâche périodique.
Dans les deux cas, la fonction init_module s'occupe de lancer la tâche. Il suffit de créer les FIFO, la routine de gestion d'interruption (éventuellement), la tâche et enfin de définir sa priorité et périodicité (s'il y a lieu). La valeur de la période est exprimée, comme toutes les grandeurs de RTLinux, en nano-secondes.
Ceci permet de s'initier au fonctionnement de l'API RTLinux pour ce qui est de la gestion du temps, de la création de tâches périodiques. Pour l'autre méthode on aborde la prise en compte d'interruptions matérielles et la mise en place de routines de traitement d'interruptions. Comme les applications communiquent par RT-FIFO, ce mécanisme est aussi... maîtrisé !
L'objectif est ici de mener un développement en interaction forte avec le matériel, de bout en bout. En effet, j'avais à apprendre comment construire un driver, à utiliser les ressources de RTLinux et à coder les programmes de tests de ce driver. Le document présent en annexe est le manuel d'utilisation de ce driver. Pour pouvoir être utilisé par la Communauté, ce document est rédigé en anglais ; l'ensemble des programmes de tests, versions de drivers et documentations sont disponibles sur Internet pour permettre l'utilisation et l'amélioration de mon travail. http://noglitch.free.fr
Ce que l'on peut tirer de ce premier développement complet sous RTLinux est que cet environnement est tout à fait homogène, stable et simple d'utilisation. Il est très important, comme il est mentionné dans tout manuel sur RTLinux, de bien délimiter la partie temps réel et la partie qui ne l'est pas. En effet, Il s'agit de minimiser la partie de code ``critique'' et d'utiliser au maximum les facilités offertes par un développement dans l'espace utilisateur de Linux (déboguage, protection mémoire, librairies, graphismes... ) .
L'API de style POSIX disponible dans l'espace RTLinux, facilite la compréhension du code écrit pour utiliser le driver. Toutefois, elle peut entraîner des confusions avec l'utilisation dans l'espace Linux (noyau ou utilisateur). Je conseille d'avoir les idées claires sur la situation du code que l'on est en train d'écrire (espace RT ou Linux, noyau/utilisateur). Un schéma est toujours utile dans de telles situations...
Pour ce driver il a fallu mettre en oeuvre beaucoup plus de notions de temps réel. La partie documentation a donc été conséquente pour l'approche du signal sonore traité par une carte son dans un environnement GNU/Linux puis pour les changements à apporter en vue d'un comportement déterministe.
Théorie:
Le son est un phénomène analogique; il se traduit par une valeur quelconque sur une échelle continue. Les ordinateurs fonctionnent en numérique : ils utilisent des valeurs discrètes.
Les cartes son fonctionnent grâce à un composant appelé Convertisseur Analogique-Numérique (A/N ou ADC en anglais) afin de convertir les tensions correspondantes aux ondes sonores analogiques en valeurs numériques qui peuvent alors être stockées dans la mémoire de l'ordinateur. De même, un Convertisseur Numérique-Analogique (N/A ou DAC en anglais) convertit les valeurs numériques en une tension analogique qui peut alors être amplifiée pour "attaquer" un haut-parleur et produire du son...
La conversion analogique-numérique (échantillonnage ou "sampling" en anglais) génère des erreurs. Deux facteurs déterminent la qualité du signal échantillonné par rapport au signal initial.
Pratique:
Les cartes son utilisent typiquement un codage sur 8 ou 16 bits pour des fréquences d'échantillonnage allant de 4000 à 44100 (ou même 48000 Hz). L'échantillonnage pouvant être réalisé sur une voie (mono) ou deux (stéréo) (voire plus (8, 16...) pour des cartes professionnelles).
Les pilotes de carte son utilisent des mécanismes bien particuliers pour fournir, au bon moment, les échantillons nécessaires au convertisseur de la carte...
Quelques petits calculs s'imposent à cet endroit de la discussion ; en effet, il faut savoir quel est le débit de données à transférer dans la carte son, pour que celle-ci puisse avoir l'échantillon qu'il lui faut au bon moment. Un échantillon manque, se produit alors un ``crépitement'' du signal sonore.
Avec le débit de données et la taille du buffet alloué au stockage, on peut déduire la fréquence à laquelle il faut remplir
le buffer (problème classique de la baignoire qui se vide à débit constant,
cher à tous les collégiens).
Il ne faut pas de délai entre la fin d'un paquet d'échantillons contenus dans un buffer et l'échantillon suivant d'où, l'emploi de la technique des buffer multiples (Multi-buffering). L'application tient toujours un buffer rempli à la disposition du driver, qui peut s'en emparer lorsqu'il a vidé le précédent: on parle en fait d'un buffer découpé en plusieurs fragments (en général 3). Il faut tout de même savoir que l'application a souvent des traitements à faire sur les échantillons avant de les fournir au driver.
Exemple: avec un débit de données de 176400 octets/s et un buffer de 2 fragments de 4Koctets, l'application dispose de 4096 octets soit de 23ms pour effectuer son traitement et remplir le buffer ce qui est peu ! Il faut alors l'agrandir. Mais, le chargement d'un fragment plus grand demande du temps car il faut transmettre des données, de l'espace utilisateur, au noyau (fonctions write() de l'API son). Cela implique une augmentation du temps de latence pour toutes les autres opérations du système. Il faut donc augmenter la fragmentation du buffer: les transferts de données seront alors plus nombreux mais de plus petite taille.
Le pilote sous Linux calcule en général la taille et le nombre des fragments tel que la latence soit de 0.5s pour une restitution et de 0.1s pour une acquisition. Sous RTLinux, les données sonores résidant sur le disque sont envoyées, via une RT-FIFO, à une tâche temps réel. Cette dernière utilise l'API son classique (OSS: Open Sound System) pour communiquer avec le driver modifié. Je conseille, avant tout développement dans le domaine du son, de lire attentivement les documents mis à notre disposition sur ce site www.opensound.com : Open Sound System TM Programmer's Guide.
Le driver pour la carte son Sound Blaster 128 PCI est celui développé pour la puce d'Ensoniq es1371. Il se trouve dans le répertoire consacré au son dans l'arborescence du noyau Linux, sous le nom es1371.c (!). Le piège à éviter est d'utiliser le driver es1370, ou de chercher celui s'appelant comme la puce présente sur la carte son i.e.: es1373 !!! Pour utiliser ce driver sous Linux, il suffit de le sélectionner comme module lors de la configuration du noyau. Il peut aussi être utilisé quand on travaille sous RTLinux, en agissant exactement comme décrit précédemment, lors de la compilation du noyau ``patché'' pour RTLinux. Le driver ne fonctionnera que dans l'espace Linux et l'on ne pourra lui soumettre aucune contrainte temps réel: il a les désavantages de toutes les tâches tournant sous Linux et peut aussi être préempté par n'importe quelle tâche RTLinux.
Pour que ce driver ait un comportement déterministe, il faut l'adapter à l'environnement RTLinux. Ce qui signifie modifier:
Pour faciliter le travail et en plus permettre au driver modifié de fonctionner aussi bien sous RTLinux que sous Linux (voire sous RTAI), plusieurs initiatives ont vu le jour.