La conception des systèmes temps-réel répartis embarqués est une tâche rendue de plus en plus complexe de par leur implication dans des domaines variés de notre quotidien (transport, loisirs, etc.). Que ce soit pour parcourir dix mille kilomètres par avion pour atteindre une île tropicale, se localiser dans le désert ou écouter de la musique en attendant le métro, ces systèmes doivent se conformer à des exigences hétérogènes (fiabilité, performance, sûreté, etc.) dépendantes du contexte environnemental dans lequel ils évoluent. Notamment, certains systèmes dits critiques, issus par exemple du domaine avionique ou militaire, doivent garantir leur sécurité d’utilisation, leur bon fonctionnement ou encore l’intégrité des données qu’ils manipulent. Une défaillance de ce type de système dûe à une erreur de conception pourrait engendrer des conséquences dramatiques, financières voire humaines.
Pour répondre à la complexité croissante de ces systèmes dûe à l’augmentation du nombre de fonctionnalités qu’ils doivent fournir, de nombreuses méthodes ont été proposées pour faciliter leur réalisation. Dernièrement, l’ingénierie dirigée par les modèles a permis l’automatisation du processus d’analyse et d’implantation de ces systèmes à partir de la description de leur architecture matérielle et logicielle. Des représentations différentes du système sont ainsi élaborées dans l’objectif de couvrir un aspect du système (faisabilité, performance, comportement, déploiement, etc.). Les modèles d’analyse permettent de vérifier et de valider le système vis-à-vis de ces spécifications. Les modèles de déploiement permettent de spécifier le déploiement des composants logiciels sur la plate-forme matérielle et automatisent la production du code source de l’application.
Pour autant que ces représentations expriment chacune des propriétés pertinentes du système, les formalismes employés pour leur description ne sont pas forcément les mêmes. Ainsi, chaque formalisme dédié à un aspect du système ne permet pas forcément d’exprimer les mêmes hypothèses qu’un autre ni le même niveau de détail. Le passage d’un formalisme à un autre s’effectue parfois manuellement et rien ne garantit que les propriétés du système soient préservées lors de cette transformation. Cette problématique est aujourd’hui traduite par la difficulté d’assurer la cohérence des représentations qu’elles soient dédiées à l’analyse du système ou utilisées pour la génération et le déploiement automatique des composants du système. De plus, les analyses sont souvent effectuées sur une représentation partielle du système, sa partie applicative, omettant l’impact de sa partie exécutive (par exemple, des ressources d’un intergiciel) pouvant même compromettre sa faisabilité. Ce dernier point rend difficile l’implantation du processus de génération de code qui nécessite d’effectuer des hypothèses sur le support d’exécution des composants et d’élaborer des transformations complexes. Ceci augmente les différences sémantiques entre le modèle et le code généré
Modéliser pour l’analyse et la génération de code
Les représentations du système sont élaborées par des formalismes différents et évoluent à des niveaux d’abstraction différents. La sémantique des constructions d’un langage de programmation utilisées pour l’implantation du système définit un niveau d’abstraction trop bas (trop de détails) qui complexifie l’exploitation du code source pour l’analyse des propriétés du système. Les formalismes dédiés à l’analyse d’un système réparti tel les réseaux de Petri (comportement) définissent des abstractions trop élevées pour permettre l’exploitation du modèle d’analyse à des fins de génération de code. Afin de renforcer la cohérence entre les modèles d’analyse et le code généré, il est donc nécessaire de déterminer une représentation intermédiaire contenant à la fois des informations pour l’analyse du système et un niveau de détail suffisant pour une démarche de génération de code efficace.
Analyser une représentation complète du système
Un second problème consiste à réaliser les analyses à partir d’une description complète de l’application incluant aussi bien les composants applicatifs que les composants de son exécutif. Dans le contexte des systèmes TR2E critiques, les composants de l’exécutif correspondent aux composants d’un intergiciel. L’introduction des intergiciels et des standards de répartition a simplifié la conception des applications réparties. Le développeur n’a pas à se charger des aspects dits bas-niveau, notamment liés à la communication (réception des tampons de communication, extraction des données…) et dépendants de la plate-forme d’exécution de l’application. Des routines dites de plus haut-niveau pour l’envoi et la réception des données lui sont fournies et masquent la complexité de la mise en œuvre de la répartition. La spécification des composants intergiciels dès les premières étapes de la modélisation va ainsi à l’encontre de la philosophie des modèles où l’abstraction des détails d’implantation est prépondérante lors des premières étapes d’analyse. Cependant, les ressources déclarées par l’intergiciel ont un impact sur l’architecture logicielle et l’implantation de l’application (gestion des ressources de communication, donnée partagée…). Par conséquent, il est nécessaire de prendre en compte ces ressources lors des différentes analyses (faisabilité, performance…) réalisées sur un modèle final de l’application.
Processus de réalisation automatique et complexité
Les processus de réalisation de systèmes critiques basés sur une approche IDM automatisent les étapes d’analyse, de déploiement, de configuration et d’intégration des composants constituant l’application. Le déploiement revient à sélectionner et placer explicitement les différents constituants de l’application sur leurs emplacements physiques respectifs et préparer leur exécution (par exemple, le placement des entités responsables de l’envoi ou de la réception des messages sur un nœud). La configuration consiste à personnaliser ces composants sélectionnés en fonction des besoins et des propriétés de l’application (par exemple, l’ouverture des canaux de communication requis par un nœud donné). Enfin, l’intégration est la dernière phase de la réalisation permettant l’assemblage des différents composants (applicatifs, intergiciels et utilisateurs) qui forment l’application. Celle-ci s’effectue lors de la compilation de l’application. Cependant, les composants intergiciels sont implantés dans le langage de programmation cible et nécessitent le développement et la maintenance d’un intergiciel par générateur de code. Ceci implique un processus de génération automatique complexe, effectuant plusieurs transformations et introduisant des mécanismes supplémentaires pour assurer l’assemblage correct des composants applicatifs et des composants intergiciels. De plus, ce processus automatique peut être différent en fonction du langage de programmation cible.
I Introduction Générale |