Solutions INFORMATI Q U E I N D U S T R I E L L E Linux renforce son intérêt pour le temps réel Linux gagne chaque jour des parts de marché dans le secteur de l’informatique embarquée. Seul frein à cette généralisation : son manque de déterminisme. A l’inverse, les systèmes d’exploitation temps réel sont capables des meilleures performances mais restent très, voire trop spécialisés. Voici quelques pistes pour vous aider à choisir entre Linux et un système d’exploitation temps réel. I l existe une grande différence entre les systèmes d’exploitation temps réel et les systèmes d’exploitation basés sur Linux. Les premiers, aussi appelés RTOS (pour Real Time Operating Systems) sont des systèmes propriétaires conçus spécialement pour effectuer du traitement déterministe. Les seconds font partie du monde des logiciels libres. Il s’agit de systèmes d’exploitation généralistes (GPOS, pour General Purpose Operating System), davantage portés sur les applications bureautiques. Le mariage des deux philosophies (logiciel libre et traitement temps réel) suscite un Automaticiens et roboticiens utilisent couramment des RTOS pour leurs applications temps réel. Mais Linux aussi sait se montrer déterministe, avec la possibilité d’utiliser des logiciels génériques. intérêt évident pour les utilisateurs industriels. Les éditeurs travaillent donc depuis longtemps sur le sujet. Différentes techniques ont été mises au point pour conférer à Linux des capacités de traitement temps réel. On distingue deux principales méthodes : rendre le noyau préemptif ou ajouter un second noyau temps réel. Transformer Linux en un OS temps réel Rendre le noyau préemptif (on parle aussi de “kernel préemptif”) revient à modifier le noyau de Linux afin d’associer aux différentes tâches des niveaux de priorité, les tâches prioritaires “prenant la main” sur les autres. Cela réduit le temps pendant lequel le noyau traite des sections de code non prioritaires. Cette approche nécessite l’installation d’un patch spécifique sur le noyau Linux, une méthode difficile à appliquer lorsqu’il s’agit d’assurer le suivi ou la mise à niveau d’un grand parc d’équipements. Sans compter que, pour les applications critiques nécessitant une certification (norme aéronautique DO-178B ou norme de sécurité IEC 61508, par exemple), c’est tout l’ensemble noyau et patch qui doit être certifié à chaque modification ou changement du patch. Cette méthode requiert par ailleurs un grand savoir-faire si l’on veut assurer un déterminisme poussé. En effet, la charge du processeur est répartie entre les tâches prioritaires et non prioritaires, mais il peut MESURES 818 - OCTOBRE 2009 - www.mesures.com arriver que certaines instructions non prioritaires soient trop complexes ou trop longues pour le temps qui leur est accordé à chaque temps de cycle. C’est donc souvent l’application tout entière qui doit être adaptée afin de réduire la taille de ces instructions. Un travail fastidieux, qui nécessite de tester absolument toutes les instructions du noyau. De plus, ces tests doivent être réalisés dans des conditions de charge processeur proches de celles qui seront rencontrées dans l’environnement réel de l’application, ce qui est quasiment impossible dans la pratique. Du coup, même si cette méthode est efficace en théorie, la complexité du noyau Linux est telle qu’il sera difficile de garantir le déterminisme final d’une application. De nombreux projets Open Source sont en cours au sein de la communauté Linux afin d’optimiser les caractéristiques préemptives du noyau. Le plus significatif reste le projet “Preempt_RT”, initié par Ingo Molnar. Ce patch préemptif apporte beaucoup de modifications au noyau, notamment en L’essentiel ce qui concerne les drivers de périphéri Les outils de développement ques. Même si dans la temps réel se diversifient. plupart des cas le patch Les ingénieurs systèmes ont préemptif reste commaintenant le choix entre un patible avec les drivers OS Linux et un OS spécialisé standard, les perfordans le temps réel. mances et le fonction Il existe plusieurs méthodes nement des périphépour fournir à Linux des riques ne sont pas caractéristiques temps réel. garantis. Tous les an- Linux présente l’avantage ciens drivers doivent d’un coût moindre faire l’objet d’une (pour de grandes séries) et nouvelle validation peut même convenir lors du passage à un pour les applications temps noyau préemptif, ainsi réel “dur”. qu’à chaque installa- Les RTOS continuent de tion de nouveau péris’imposer sur le marché des applications critiques. phérique. L’approche préemptive suscite ➜ 31 Solutions ➜ toutefois un grand intérêt. Le projet “Preempt_RT” n’est plus considéré aujourd’hui comme un projet annexe. Il fait même partie des principaux projets. Un grand nombre de développeurs de la communauté Linux travaillent donc à améliorer sa qualité et sa maturité. Rajouter un cœur temps réel L’approche “cœur temps réel” consiste quant à elle à rajouter un noyau déterministe à côté du noyau Linux classique. Le cœur temps réel partage de la mémoire avec le cœur Linux, et les deux communiquent par le biais de files d’attente. Toutes les instructions sans exception passent par le noyau temps réel. Ce dernier renvoie toutes les instructions non critiques vers le noyau Linux standard et se charge d’exécuter les autres. Mais il n’envoie les tâches non critiques au noyau Linux standard qu’après avoir traité les tâches prioritaires. Principale différence avec le noyau préemptif : puisque les applications critiques sont directement chargées dans le cœur temps réel, elles ont un accès privilégié aux périphériques dont elles ont besoin. Leur performance d’exécution est donc moins sujette à variation qu’avec un noyau préemptif. Contrairement au noyau préemptif dont l’installation est relativement transparente, le principe du cœur temps réel induit des différences avec le fonctionnement classique de Linux, du fait du partage de la mémoire entre les deux cœurs. Les développeurs doivent donc s’appliquer à écrire des appli- 32 Solutions cations pouvant être chargées directement dans le cœur temps réel. Concrètement, il faut utiliser un format identique à celui des systèmes de fichiers et des pilotes de périphériques. Le cœur temps réel communique directement avec le matériel. On parle d’“exécution en mode kernel” car l’application temps réel s’exécute dans le noyau temps réel comme s’il s’agissait d’un driver. Pour résumer, l’approche préemptive a l’avantage de faire partie intégrante du monde Linux, et convient bien au développement d’applications temps réel “mou”, puisqu’elle ne peut pas garantir un véritable déterminisme. A l’inverse, mettre en place un cœur temps réel nécessite en quelque sorte de “s’écarter du monde Linux” (ce type de cœurs n’est d’ailleurs pas supporté par la licence GPL). Une approche non standard, donc, mais qui fournit l’assurance d’un temps réel “dur” (à condition bien sûr d’écrire les applications afin qu’elles s’exécutent directement sur ce cœur). Le choix d’utiliser un RTOS Ces deux approches tendent à apporter à Linux les fonctionnalités temps réel qui lui font défaut. Mais bien entendu, il est possible d’opter pour la solution inverse : ajouter à un RTOS la capacité d’exécution de fonctions non critiques. L’architecture de base d’un RTOS comprend un noyau temps réel relié à un ordonnanceur. Ce dernier définit l’ordre de traitement des tâches en fonction de leur priorité. Un algorithme préemptif s’exécute en parallèle Architecture Linux standard Linux + cœur temps réel Architecture optimisée avec mode kernel et mode utilisateur Comme tous les systèmes d’exploitation généralistes, Linux standard forme une couche d’abstraction au-dessus du matériel. Le cœur temps réel prend complètement la main sur le système. Il traite directement les tâches critiques et envoie toutes les autres au noyau Linux. Les architectures les plus récentes placent une couche d’abstraction au-dessus du cœur temps réel. Ceci afin de pouvoir développer des applications sans forcément maîtriser les langages de bas niveau. afin de vérifier à chaque temps de cycle qu’une nouvelle interruption critique ne s’est pas déclenchée. Par ailleurs, contrairement à un système d’exploitation généraliste, un RTOS n’utilise qu’un seul espace mémoire pour exécuter et sauvegarder toutes les tâches (il n’y a pas de transferts de données entre mémoire virtuelle et mémoire physique). mode “kernel”. Contrairement aux OS généralistes, ils n’incluaient aucun mécanisme d’abstraction pour faciliter les communications entre l’OS et les périphériques. Cela obligeait les développeurs à travailler au plus près du matériel. Toutes les communications entre équipements devaient être définies par le programme, avec le risque d’erreurs que cela entraîne. Le temps de débogage pouvait être très long même pour un développeur expérimenté. Heureusement, la puissance des processeurs augmentant, les dernières générations de Les RTOS se perfectionnent Historiquement, les systèmes d’exploitation temps réel ne traitaient les tâches qu’en RTOS disposent de mécanismes pour exécuter des processus non critiques en parallèle des tâches temps réel. On appelle ces processus des modes “utilisateur” ou “user mode”. Le développement de certaines applications s’effectue alors dans un environnement différent du mode kernel, et chacun des deux noyaux utilise un secteur distinct de la mémoire. Les applications ainsi créées bénéficient toujours des performances déterministes du RTOS, mais disposent d’une mémoire séparée pour exécuter toutes les autres tâches annexes. Cela facilite le travail Temps réel “dur” et temps réel “mou” se font face Linux n’est pas adapté aux applications certifiées Un système temps réel se définit par sa capacité à exécuter une tâche dans un intervalle de temps donné. Cette caractéristique est appelée le déterminisme. Bien entendu, chaque application impose un temps de réponse différent, plus ou moins long selon les cas. Si certaines peuvent se satisfaire d’un temps de réponse moyen, avec des valeurs tantôt au-dessus et tantôt en dessous de la valeur annoncée, d’autres ont absolument besoin d’une synchronisation fine. Elles ne peuvent accepter aucun dépassement du temps de réponse, au risque de déclencher un plantage de tout le système. C’est pourquoi les applications déterministes se divisent en deux catégories : on distingue le traitement temps réel “dur” du traitement temps réel “mou”. Le temps réel “mou” fournit la garantie que le processeur garde suffisamment de ressources disponibles pour effectuer une tâche prioritaire dans un délai imparti. Typiquement, on optera pour des systèmes d’exploitation généralistes tels que Linux pour répondre à ce genre d’applications. Avec le temps réel “dur”, à l’inverse, on cherche davantage à surveiller le temps de réponse qu’à mesurer les ressources disponibles dans le processeur. La criticité concerne le temps que met le système à répondre (ou réagir) à un événement. Concrètement : on ne doit jamais Lorsqu’il s’agit de certifier du code embarqué pour un secteur critique (norme FDA 510k pour le médical, DO-178B pour l’aéronautique, ou encore IEC 61508 pour les applications de sécurité), il paraît bien difficile d’intégrer des solutions telles que des OS Linux. Comment prouver la sûreté de fonctionnement d’un OS comptant autant de lignes de codes, autant de modules qui interagissent tous les uns avec les autres ? La certification ne se limite pas seulement à livrer le code source du système d’exploitation, il faut pouvoir en expliquer chaque détail. En ce qui concerne Linux, il n’y a aucune visibilité sur les aspects de qualité du code, de par le principe même de la communauté : tout le monde peut rajouter des fonctions, mais à aucun moment un document ne pourra attester de la validité du code. Pire : on ne saurait même pas où s’adresser en cas de problème. Car comme pour n’importe quel logiciel, un OS sans bug n’existe pas. Le problème n’est pas que des bugs subsistent dans le code, mais plutôt de savoir où ils sont situés et ce qu’ils font. Pour les applications critiques, il faut absolument éviter qu’un OS ne plante sans crier gare ou ne mette le système dans un état instable. Il est donc impératif d’oublier la notion d’Open Source et manquer de traiter un événement ou une interruption. Ces besoins en temps réel dur sont encore plus rigoureux lorsqu’il s’agit, par exemple, d’un calculateur d’ABS automobile. Car aux besoins en temps de réponse très courts s’ajoutent toutes les contraintes liées à la sécurité du conducteur. Toutefois, le temps réel dur n’est pas toujours systématiquement employé. C’est le cas, par exemple, du traitement audio sur un ordinateur : pour le décodage d’une piste sonore classique, échantillonnée à 44,1 kHz, le logiciel a besoin de transférer 32 bits de données vers le matériel toutes les 22,7 microsecondes ! Aucun système d’exploitation généraliste n’est capable d’atteindre ces vitesses de traitement, d’autant que d’autres services, qui s’exécutent en parallèle, peuvent retarder le système et entraîner des coupures dans le son. C’est pourquoi on utilise une mémoire tampon pour compenser ces délais. En remplissant cette mémoire seulement toutes les 0,1 seconde, on résout un problème de temps réel dur matériel en utilisant un système d’exploitation temps réel mou. Toutes les applications dans les domaines de l’aérospatiale, de la Défense, du contrôle industriel, de l’instrumentation, de la robotique et des télécoms demandent des temps de traitement inférieurs à la microseconde et une priorisation des tâches. MESURES 818 - OCTOBRE 2009 - www.mesures.com MESURES 818 - OCTOBRE 2009 - www.mesures.com des développeurs, qui n’utilisent qu’un seul environnement de programmation. La comparaison des performances Avec les fonctions Preempt_RT disponibles pour le noyau Linux, des niveaux de priorité peuvent être associés au traitement de certaines interruptions. Mais les temps de traitement restent sujets à variations. On réservera cette méthode à des applications de contrôle fin, mais non critique. On parle de temps réel “mou”. Les cœurs temps réel rendent possible, quant à eux, un traite- ➜ de s’orienter vers les solutions certifiables proposées par certains éditeurs. Ces OS peuvent être fournis avec des documents de vérification et de validation, voire même avec des outils de couverture de tests propres à une norme. Toutefois, il reste possible d’intégrer un OS Linux à l’intérieur d’une application critique en faisant appel à la virtualisation (voir article Mesures n° 810, page 35). Rappelons que la virtualisation consiste à faire tourner plusieurs OS ou applications sur un seul et même système, en leur faisant croire qu’ils s’exécutent sur des systèmes physiquement différents. Une fois la plate-forme de virtualisation installée (entre la couche matérielle et l’OS), Linux peut tourner en parallèle de Windows, d’un RTOS ou même d’applications Java, Ada, etc. De plus, les outils de virtualisation sont tous légers, ce qui facilite leur certification (car ce sont eux les garants de la sûreté de fonctionnement du système). A noter bien sûr que ces deux dernières solutions ont un coût non négligeable. Que l’on opte pour une solution Linux propriétaire ou pour un hyperviseur, on s’éloigne fortement du modèle “gratuit” des OS Linux. Et il reste encore à programmer et à certifier l’application proprement dite. 33 Solutions Avec la méthode du noyau préemptif, une certaine variabilité subsiste dans les temps de latence. Une bonne illustration de ce que l’on appelle le temps réel mou. ➜ ment rapide et véritablement déterministe de certaines interruptions. Les autres tâches, non prioritaires, sont traitées par le noyau Linux comme des processus classiques. Cette méthode présente l’avantage de la séparation de la mémoire. En revanche, ces solutions sont propriétaires. A l’inverse, la méthode du cœur temps réel présente à la fois un seuil minimum très bas pour les temps de réponse et une faible variabilité. On peut alors parler de temps réel dur. A l’inverse, dans un RTOS, véritable outil industriel, tout est pensé dans le sens des performances temps réel. Dans le secteur de l’électronique embarquée, la quantité de mémoire est toujours dimensionnée au plus juste. L’empreinte mémoire de l’OS joue donc également un rôle dans le choix entre Quelques notions de temps réel On mesure le déterminisme d’un système d’exploitation par son temps de réponse à une interruption, aussi appelé “temps de latence”. Il s’agit du temps que met le noyau du système d’exploitation avant de répondre à un évènement. Cela inclut le temps de sauvegarder la tâche en cours, de déterminer la provenance de l’interruption et d’effectuer le traitement proprement dit. Rappelons qu’un système d’exploitation contient un tableau de fonctions, appelé “handler d’interruptions”, qui associe à chaque interruption ou séquence d’interruptions une action à effectuer. Mais avec la plupart des applications temps réel, avant que le système ne réponde à une interruption, il lui faut juger de l’importance de cette dernière et la comparer avec les traitements déjà en cours. C’est pourquoi l’on a besoin d’une gestion des priorités entre les tâches. Le fait d’effectuer ce contrôle de priorité avant de traiter une tâche induit forcément des temps de latence supplémentaires. Il y a surtout le temps nécessaire pour identifier le niveau de priorité. C’est le même principe que l’on retrouve dans un commutateur Ethernet, qui doit analyser l’entête de la trame avant de la traiter. A cela s’ajoutent forcément le temps de la comparaison entre les deux degrés de priorité, celui de la tâche en cours et celui de la tâche en attente. La latence totale d’un système est donc la somme de ces trois temps : le temps d’identification du niveau de priorité, le temps de comparaison avec la tâche en cours et le temps de traitement de l’interruption. 34 un OS Linux et un RTOS qui occupera moins d’espace qu’un Linux avec cœur temps réel. Ajoutons à cela que les RTOS bénéficient pour la plupart de dizaines d’années d’utilisation, durant lesquelles ils ont été améliorés et optimisés par leurs éditeurs. A l’inverse, Linux, bien que supporté par une communauté, manque encore de maturité pour l’embarqué. Sans compter que les RTOS sont plus facilement certifiables pour les applications militaires et aéronautiques, qui doivent répondre à des normes très strictes. La taille du système d’exploitation Linux, inadaptée au monde de l’embarqué, le rend plus difficile et surtout plus coûteux à certifier. Le choix entre Linux et RTOS revient donc en quelque sorte à déterminer si une application est plutôt orientée “tâches critiques” ou “tâches annexes” (affichage, calcul sur des données, sauvegardes, etc.). Il faut trouver un compromis entre les deux critères principaux que sont l’indépendance que l’on souhaite conserver entre les différentes tâches d’une application, et les besoins en communication entre ces tâches. Restent quelques aspects à prendre en considération avant d’arrêter son choix entre un RTOS et Linux temps réel, tels que la disponibilité des logiciels tiers utiles à l’application. Si des logiciels génériques sont nécessaires, on optera plus volontiers pour Linux. Autre point délicat : les coûts globaux de maintenance et de mise à jour, qui ne sont pas clairement identifiables avec les logiciels libres. L’amortissement d’une solution propriétaire sera donc plus facile à calculer. Et enfin, il faut bien sûr s’assurer de la disponibilité d’une solution Linux ou RTOS pour la plate-forme matérielle considérée. Frédéric Parisot d’après Hans Juergen Rauscher, architecte système chez Wind River MESURES 818 - OCTOBRE 2009 - www.mesures.com