Restructuration d applications Java Temps réel
Upcoming SlideShare
Loading in...5
×
 

Restructuration d applications Java Temps réel

on

  • 1,121 views

La restructuration de programmes consiste à apporter des modifications sur la structure interne de ces programmes, pour différents buts tels que la facilité de compréhension et de maintenance, ...

La restructuration de programmes consiste à apporter des modifications sur la structure interne de ces programmes, pour différents buts tels que la facilité de compréhension et de maintenance, l’optimisation, l’ordonnancement de tâches, la facilité de conversion d’un langage à un autre, ou la détermination de modules réutilisables. Dans ce travail, nous avons conçu et implémenté un système de restructuration de programmes Java temps réel, qui permet d’obtenir une sensible amélioration de l’ordonnançabilité de ce type d’applications.
En effet, les programmes associés à des systèmes temps réel doivent être logiquement corrects et doivent s’exécuter sans fautes temporelles. Afin de satisfaire leurs échéances, les tâches de ces systèmes sont ordonnancées par des techniques adéquates. Dans le cas par exemple, où un ensemble de tâches serait non ordonnançable, le programmeur procède à des opérations manuelles de modification, de réglage et de restructuration de l’application, afin de la rendre ordonnançable. De telles opérations sont lentes, coûteuses, et non contrôlables. Les solutions existantes dans ce domaine, sont de nature à améliorer l’ordonnançabilité d’une tâche.
Etant donné que Java est un langage de programmation purement orienté objet, nous avons utilisé les modèles de représentation de dépendances qui tiennent compte des différents aspects des systèmes orientées objets tels que la réutilisation et le polymorphisme.

Statistics

Views

Total Views
1,121
Views on SlideShare
1,121
Embed Views
0

Actions

Likes
1
Downloads
16
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Restructuration d applications Java Temps réel Restructuration d applications Java Temps réel Document Transcript

  • MINISTERE DE L’ENSEIGNEMENT SUPERIEUR ET DE LA RECHERCHE SCIENTIFIQUE Faculté des Ingénieurs Département d’Informatique MEMOIRE d’Ingénieur d’Etat en Informatique Option Matériels & logicielsRestructuration d’Applications Java Temps-Réel Par KAMEL MOUATS
  • INTRODUCTIONLa décomposition d’un système temps réel résulte en une collection de processus,chacun est responsable d’une portion spécifique de la tâche globale. La correspondanceentre les modules du logiciel et les entités du monde réel n’est souvent pas apparente àpartir de la structure du code. Ce qui rend difficile la compréhension et la maintenancedu code. De plus, traiter les systèmes temps réel comme étant des groupes de processuscontraints par le temps, oriente la conception vers une vue «événement - action»: lesévénements sont générés par les entités du monde réel ou par les processus logiciel; lesactions doivent être effectuées par les processus logiciels en réponse temporelle à cesévénements. Malheureusement, dans plusieurs systèmes temps réel, les événements discrets sontdes approximations d’activités réellement continues. Dans ces systèmes, les contraintesde temps sont plus naturellement vues comme étant des contraintes de cohérencestemporelles d’information. Par exemple, dans plusieurs systèmes robotiques, l’interfacelogicielle du manipulateur physique entraîne le manipulateur physique à lirepériodiquement son état et à émettre des commandes d’actionneurs. Le logiciel dans untel système, contient une image du manipulateur physique. Cette image doit être tenuecohérente avec l’état courant du manipulateur physique, sinon le planificateur demouvements pourrait générer des plans de mouvements inappropriés. Al’implémentation, cette contrainte de cohérence est transformée en contrainte de tempsde n unités de temps de périodes de scrutation. De plus, dans la plupart des systèmes temps réel, une approximation de laconcurrence doit être faite par l’exécution de plusieurs processus sur des ressourcespartagées. L’ordonnancement de l’exécution de ces processus est souvent basées sur lestemps d’exécution au pire des cas, obtenus au moyen de différentes techniquesd’estimation. Ceci pose le problème de réservation excessive des ressources, lorsque letemps moyen d’utilisation s’éloigne des temps au pire des cas. Le comportement temporel est une caractéristique de base pour les systèmesinformatiques où les programmes doivent être logiquement correct, en s’exécutant sanserreurs de temps.Les erreurs temporelles sont particulièrement produites quand on a un ensemble de tâchesprovoquant un surcharge et un défaut dans l’ordre d’exécution, ce qui ramène le système àune phase d’échec. Les développeurs remédient ces anomalies par des opérationsintensivement manuelles, telles que l’instrumentation, prise de mesure et éventuellement unereconception complète du système. De telles opérations sont coûteuses, lentes etincontrôlables. Dans le but d’aider à prévenir une ordonnançabilité complète, une approche est adoptée,et qui généralise les solutions précédentes à deux niveaux. Dans un premier, elle consiste,pour la perspective d’ordonnancement, à restructurer une large classe de programmes tempsréel qui peut être complexe et contenant une collection de procédures. Dans un deuxièmeniveau, la méthode de restructuration utilise le concept des tranches de programmes(interprocéduraux) et un modèle de dépendance amélioré, permettant par la suite d’améliorerl’ordonnançabilité d’un ensemble de tâches, soit par rendre leurs échéances flexibles, ou bienpar décomposition d’une ou de plusieurs tâches en sous tâches, de telle façon qu’on puisseutiliser les méthodes d’ordonnancement généralisées, de priorités fixes, qui permettentl’augmentation de l’ordonnançabilité d’un ensemble de tâches, à un niveau supérieur de celuifourni par l’algorithme Rate-Monotonic.
  • 1 Le Monde Des Systèmes Temps Réel 111PARTIE 1:Système Temps Réel «Concepts & Conception»:Objectif: Ce chapitre a pour but d’introduire les systèmes temps réel. Il illustre certaines desdifficultés que l’on rencontre lorsque l’on implémente ce genre de système. Un systèmetemps réel est correct en fonction de ses résultats et du moment auwquel il les produit.Les contraintes de temps et de ressources sont déterminantes pour le fonctionnement deces systèmes..I- Introduction: Au fur et à mesure que le prix sur le matériel diminue, on intègre des ordinateursdans de plus en plus de systèmes. Ces logiciels interagissent directement avec despériphériques matériels, et leurs logiciels doivent pouvoir réagir suffisamment vite auxévénements dont le système assure le suivi et le contrôle. Du fait de ce besoin, pour lelogiciel, de répondre à des événements «temps réel», le système logiciel de contrôle aété qualifié de système «temps réel». Un système temps réel consiste en un ensembled’entités contrôlées et un sous-système de contrôle. Ce dernier est formé d’un ensemble desystèmes d’ordinateurs, tandis que les entités contrôlées peuvent être un large éventail desystèmes à comportement mécanique ou tout dispositif, du simple mélangeur au robot[Stankovic91]. Typiquement, le sous-système de contrôle exécute des programmes decontrôle pour recevoir des données de l’environnement et/ou pour émettre des commandesaux entités contrôlées [Chung95]. Un système temps réel (STR) est un système dédié à des applications spécifiques, enparticulier, les systèmes de contrôle. Des capteurs recueillent de l’information qu’ilsfournissent au calculateur(ordinateur). Ce dernier s’occupe de réaliser le contrôle désiré etdonne les résultats pour d’éventuelles interventions. Les systèmes embarqués constituent un sous-ensemble de systèmes temps réel,caractérisés par leur contrôle de systèmes mécaniques tels que les systèmes de contrôlede bateaux, de véhicules, de machines à laver, etc. Comme on a besoin de répondre à des événements qui arrivent à n’importe quelmoment, on doit organiser l’architecture d’un système temps réel de manière à pouvoirtransférer le contrôle au composant approprié dès la réception d’un événement. C’estpourquoi, on conçoit le système comme un ensemble de processus parallèles, et quicoopèrent entre eux. Une partie du système temps réel (quelquefois appelée exécutiftemps réel) est dédiée à la gestion de ces processus.II-Définition d’un système temps réel: Avant d’aller plus loin, il est utile d’essayer de définir la phrase: «Système Temps Réel»(STR) avec plus de précision. Il y a une multitude d’interprétations de la nature exacte d’unSTR; cependant, elles ont tous en commun la notion du «temps de réponse (le tempsnécessaire pour qu’un système puisse générer des sorties à partir d’entrées associées). Le«Oxford Dictionary of Computing» donne la définition suivante pour un STR: «C’estn’importe quel système dans lequel le temps, au bout duquel la sortie est produite, estsignificatif. C’est généralement dû au fait que l’entrée correspond à certains flux dans lemonde physique, et la sortie doit appartenir aux même flux. La différence entre le temps del’entrée et celui de la sortie doit être suffisamment petite pour avoir un temps de réponseacceptable.»Ici, le mot «temps de réponse» est pris dans le contexte du système total. Par exemple, dansun système de contrôle de missiles téléguidées, la sortie est exigée dans quelques 1 1
  • 1 Le Monde Des Systèmes Temps Réel 222millisecondes, cependant, dans les systèmes de contrôle d’assemblage de voitures, la réponsepeut être exigée seulement dans une seconde.Young[1982] définit un STR comme suit: «C’est tout système ou activité de traitementd’information qui doit répondre à une entrée stimulée, extérieurement générée, dans unepériode finie et bien spécifique.»Dans le sens le plus général, ces deux définitions couvrent une catégorie plus large d’activitésd’ordinateur. Par exemple, un système d’exploitation comme UNIX peut être considérécomme un STR dans le cas où un utilisateur introduit une commande et il va attendre pour(recevoir) une réponse dans quelques secondes. Heureusement, il n’est pas généralementdésastreux si la réponse n’est pas rapide.Ces types de systèmes peuvent être distingués de ceux où la panne dans la réponse peut êtreconsidérée aussi mauvaise qu’une réponse fausse. Bien entendu, c’est cet aspect qui distingueun STR de ceux où le temps de réponse est important mais n’est pas crucial.Par conséquent, la correction d’un STR ne dépend pas seulement de la logique des résultatsd’un calcul, mais de plus, du temps dans lequel les résultats sont produits.Les praticiens dans le domaine de la conception des systèmes d’ordinateur à temps réeldistinguent généralement entre les STR hards(stricts) et les STR soft(relatifs).Les STR hards sont ceux où il est absolument impératif que les réponses se produisent dansun échéance spécifié.Les STR softs sont ceux où les temps de réponse sont importants mais le système resterafonctionner correctement si les échéances sont occasionnellement perdus.Les systèmes softs peuvent être distingués par eux même des systèmes interactifs danslesquels il n’y a pas des échéances explicites.Dans un STR soft ou hard, l’ordinateur a généralement une interface directe avec quelqueséquipements physiques et il est orienté à contrôler ou à couvrir l’opération de ceséquipements.Une caractéristique clé de toutes ces applications est le rôle de l’ordinateur comme uncomposant de traitement d’information dans un système d’ingénierie large. Il est pour cetteraison que de telles applications sont reconnues comme des Systèmes Temps Réel.III-Exemples de systèmes temps réel:III-1-Contôle de processus: La première utilisation d’un ordinateur comme un composant dans un systèmed’ingénierie s’est faite à la fin de 1960 dans le contrôle des processus industriels.Considérons l’exemple montré dans la figure I-1, où l’ordinateur effectue une seule activité:c’est d’assurer le passage d’un flux de liquide donné dans un pipe par le biais d’une vanne. Sion détecte une augmentation dans le flux, l’ordinateur doit répondre en alternant l’angle de lavanne; cette réponse doit se produire dans un temps fini si le dispositif de réception en fin dupipe ne se surchargera pas.III-2-La production: L’utilisation des ordinateurs dans la production est devenue essentielle de telle manièrequ’on puisse garder les coûts de la production minimaux avec amélioration de la productivité.L’ordinateur coordonne entre une variété d’engins tels que des manipulateurs, machines àoutils, …etc.III-3-Communication, commande et contrôle: On peut citer comme exemple, la réservation de places sur avion, les centres médicauxpour le suivi automatique des malades et la gestion des comptes bancaires. 2 2
  • 1 Le Monde Des Systèmes Temps Réel 333 Fluxmètre Lecture du flux d’entrée Traitement vanne Angle de la vanne en sortie Temps Fig I-1: Système de contrôle d’un fluide Tous ces systèmes se composent d’un ensemble d’agents (opérateurs) complexes, desdispositifs de collection d’informations et de procédures administratives permettant desupporter les décisions et fournissent la manière par laquelle ils peuvent être implémentés. Il est évident que les dispositifs de saisie de l’information et les instruments demandéspour implémenter les décisions sont distribués sur une zone géographique large.III-4-Systèmes temps réel généralisés: Dans chacun des exemples précédents, l’ordinateur a une interface directe avec leséquipements physique dans le monde réel. Afin de contrôler ces dispositifs du monde réel,l’ordinateur aura besoin de consulter des dispositifs de prise de mesures à des intervalles detemps réguliers, pour cette raison, une horloge de temps réel est exigée. Généralement, il y a aussi une console d’opérateur permettant toute interventionmanuelle. Un agent doit rester informé de l’état du système par des unités de visualisation dedifférents types. Les changements d’état du système sont enregistrés dans une base d’information quipeut être interrogée par les opérateurs (agents), ultérieurement, soit pour restaurer le contextedu système, en cas d’un déséquilibre de son état, ou bien afin de fournir des informationspour des besoins administratifs. La structure d’un STR embarqué typique est représentée dans la figure I-2. Le logicielqui contrôle les opérations du système peut être conçu de manière modulaire reflétant lanature physique de l’environnement. Généralement, on fera appel à un module contenant lesalgorithmes nécessaires pour le contrôle physique des dispositifs, un deuxième responsable del’enregistrement des changements d’état, un troisième pour l’extraction et l’affichage de ceschangements et un dernier pour l’interaction avec l’opérateur.IV- Caractéristiques des STR: Un STR possède plusieurs caractéristiques spéciales (soit héritées ou imposées).Cependant, tous les STR n’ont pas ces mêmes caractéristiques, mais tout langage à objectif 3 3
  • 1 Le Monde Des Systèmes Temps Réel 444général, qui sera utilisé pour la programmation effective des STR, doit supporter, etfacilement ces caractéristiques.IV-1-Taille et complexité: Il est souvent constaté que la plupart des problèmes associés au développement deslogiciels sont ceux relatifs à la taille et la complexité. Ecrire de petits programmes présente unproblème non significatif, comme il peut être conçu, codé, maintenu et compris par une seulepersonne. Si cette personne quitte la compagnie ou cette institution qui utilise ce logiciel, uneautre personne peut apprendre et comprendre ce programme en une durée relativement petite.Malheureusement, tous les logiciels ne présentent cette caractéristique qu’on veut bienl’atteindre et l’avoir. Horloge Algorithmes pour Système le contrôle digital interface d’ingénierie Temps réel Insertion de données Système de (enrichissement) contrôle distant Base de données Extraction de données Dispositifs et affichage d’affichage Console d’un opérateur Interface opérateur Real Time computer Fig I-2:STR typique Lehman et Belady[1985], dans une tentative de caractérisation des systèmes répandus,rejettent la notion simple et intuitive, que la taille est simplement proportionnelle au nombred’instructions, lignes de code ou modules. Par définition, les STR doivent répondre aux événements du monde réel. La variétéassociée à ces événements doit être traitée attentivement. Le coût de la reconception ou la réécriture du logiciel répondant aux exigences duchangement continu du monde réel est extrêmement important. De ce fait, les STR doiventêtre extensibles pour faciliter leur maintenance et améliorer leur performance. 4 4
  • 1 Le Monde Des Systèmes Temps Réel 555IV-2- Manipulation des nombres réels: Un STR implique le contrôle d’un processus industriel manipulant des données. Cesdernières servent de paramètres de prise de décision et d’intervention en cas de situationsanormales.IV-3- Fiabilité et sécurité: Les STR interviennent dans des situations critiques demandant le contrôle desfonctionnalités. Une panne d’un système, impliquée dans le cas du transfert automatiqued’argent entre banques mènera à une perte de millions de dollars sans pouvoir les récupérer ;un composant erroné dans la génération de l’électricité peut exposer la vie, dans une unitésanitaire, à des dangers irrémédiables…etc.Ces exemples dramatiques illustrent que l’ensemble du matériels et logiciels informatiquesdoivent être fiables et protectifs. De ce fait, on a intérêt à concevoir et implémenter dessystèmes dont leur fonctionnement est suivi par un autre système de contrôle. De plus, dans lecas où on exige une interaction avec un agent, on doit être prudent dans la conception de cetteinterface afin de minimiser les effets de toute erreurs humaines qui peut survenir.IV-4-Contrôle de la concurrence des composants séparés du système: Un STR tente de composer des ordinateurs et des éléments externes coexistants, aveclesquels, les programmes de l’ordinateur doivent interagir simultanément. Dans un castypique, le programme doit interagir avec un système d’ingénierie (qui se compose d’élémentsde fonctionnalités parallèles, telles que des robots, capteurs, actionneurs,…etc.) et les unitésd’affichage de l’ordinateur, la console de l’opérateur et l’horloge du temps réel.Heureusement, la vitesse des ordinateurs nous donne l’impression qu’il s’agit d’un traitementsimultané. Cependant, dans d’autres situations, ce n’est pas le cas, par exemple, dans le cas oùles données doivent être rassemblées, traitées dans des sites géographiquement distribués, oùle temps de réponse d’un composant simple ne peut pas être déduit par un seul ordinateur.Dans ces cas, il est nécessaire de considérer des STR distribués et multiprocesseurs.Un problème majeur associé à la production de logiciels qui traitent la concurrence, c’estcomment exprimer la concurrence dans la structure des programmes.Une des approche consiste à charger le programmeur pour construire son système quiimplique l’exécution cyclique d’une séquence de programmes manipulant différentes tâchesconcurrentes. Notez que cette approche de développement n’est en aucun cas applicables vules raisons suivantes : La complication de la tâche de l’utilisateur le met dans des considérations de structures qui sont inadéquates pour le contrôle des tâches. Les programmes résultants seront illisibles et non élégants. Les programmes corrects deviennent difficiles. La décomposition du problème sera compliquée. Une réalisation difficile pour faire exécuter des programmes parallèles sur plus d’un seul processeur. La correction d’un code ayant des erreurs est plus problématique.IV-5-Contrôle du temps réel: Le temps de réponse est crucial dans tout STR. Malheureusement, il est très difficile deconcevoir et implémenter un système qui va garantir que la sortie appropriée se générera dansles délais prescrits et sous toute condition possible.La réalisation de tel système, en permettant une utilisation complète de toutes les ressources àtout moment, est une tâche relativement impossible. Pour cette raison, les STR sontgénéralement construits en utilisant des processeurs ayant des capacités partagées, afin de 5 5
  • 1 Le Monde Des Systèmes Temps Réel 666s’assurer que le comportement, au pire des cas, ne produise aucun retard défavorable durantles périodes critiques du fonctionnement du système.En fournissant une puissance de traitement adéquate, en exigeant le support d’exécution, onpermettra au programmeur de : Spécifier les temps dans lesquels les actions doivent être accomplies. Spécifier les temps dans lesquels les actions doivent se terminer. Répondre à des situations où les exigences temporelles se changent de manière dynamique.IV-6-Interaction avec les interfaces du matériel: La nature des STR exige que les composants de l’ordinateur doivent interagir avec lemonde extérieur. Ils ont besoin de capteurs et actionneurs pour une large gamme de dispositifsdu monde réel. Ces dispositifs interagissent avec l’ordinateur via des registresd’entrées/sorties. Les dispositifs peuvent générer des interruptions afin de signaler auprocesseur que certaines opérations sont accomplies ou qu’il y avait des erreurs qui se sontproduites.De nos jours, vu la variété des dispositifs et la nature du temps critique de leurs interactionsassociées, leur contrôle doit être direct et non pas à travers les fonctions du systèmed’exploitation.IV-7-Implémentation efficiente: Vu la nécessité du traitement du temps critique dans les STR, l’implémentationefficiente (de haute qualité, efficace …) de ces systèmes devient de plus en plus nécessaire etimportante. Il est intéressant que l’un des bénéfices majeurs de l’utilisation d’un langage dehaut niveau est qu’il permet au programmeur de réaliser une implémentation abstraite loin detout détail, en se concentrant sur la résolution du problème. Le programmeur doit toujours êtreconcerné par le coût de l’utilisation de caractéristiques particulières d’un langage. Parexemple, si la réponse à quelques entrées doit apparaître au bout d’une micro-seconde, cen’est plus la peine d’aller utiliser un langage dont l’exécution prend une milli-seconde.V-Spécification des besoins: Tout projet informatique doit impérativement commencer par une descriptioninformelle des objectifs à atteindre. Cela devra être suivi par une analyse des besoins. C’est àce stade que la fonctionnalité du système est définie. Dans le terme de «facteurs spécifiquestemps réels», le comportement temporel du système doit être explicite, tout comme lesbesoins en fiabilité et comportementaux du logiciel en cas où une panne d’un composantsurvienne. De plus, cette phase définit quels sont les tests d’acceptante à appliquer au logiciel.Il est de plus nécessaire de construire un modèle de l’environnement de l’application. C’estune caractéristique des STR qu’ils ont des interactions importantes avec leur environnement.Après la phase d’analyse vient celle de la concrétisation de la spécification des besoins. C’està partir de cette étape qu’apparaît la conception. C’est une phase critique dans le cycle de vied’un logiciel passant à un niveau plus élevé dans la mise au point du STR.VI-Motivations de conception: Dans cette section, nous synthétisons les différentes étapes de conception desystèmes temps réel. Ces étapes se basent sur des paramètres de qualité de service[IEEE97] et elles doivent prendre en compte les besoins d’évolution et donc de lamaintenance. Dans un système intégré à grande échelle, l’une des étapes du processus deconception consiste à concevoir les systèmes, et à partager les fonctions entre matériel et 6 6
  • 1 Le Monde Des Systèmes Temps Réel 777logiciel. On peut considérer que le processus de conception des systèmes intégrés suitune série d’étapes:(1) Identifier les événements que le système doit traiter et les réactions associées.(2) Identifier les contraintes de temps à appliquer à chaque événement, ainsi qu’à la réponse qui lui est associée.(3) Regrouper le traitement des événements et des réactions dans différents processus parallèles. Un bon modèle d’architecture consiste à associer un processus à chaque classe d’événement et à chaque classe de réaction, comme dans la figure I-2. Pour chaque événement et chaque réaction, concevoir les algorithmes qui effectueront le traitement nécessaire. On doit développer la conception des algorithmes à ce stade afin d’avoir une idée du temps de traitement nécessaire.(4) Concevoir un système d’ordonnancement qui permettra de démarrer chaque processus au moment opportun afin qu’il puisse effectuer son traitement dans des contraintes de temps données.(5) Intégrer le système avec un exécutif temps réel. Naturellement, c’est un processus itératif [William96, gestion des itérationsComputer97]. Une fois qu’il a établi l’architecture (découpage en processus) et choisi lastratégie d’ordonnancement, le concepteur doit effectuer des estimations et dessimulations complètes du système pour vérifier qu’il respectera ses contraintes de temps. Contrôleur du Capteur Capteur Réponse Traitement des Données Actionneur Contrôle de l’Actionneur Fig.I.3 Architecture d’un système de contrôle Dans beaucoup de cas, ces simulations vont révéler des défauts de comportementdu système. L’architecture, ou l’ordonnancement, ou l’exécutif, ou les trois à la foisdevront être reconçus afin de pouvoir «tenir» les contraintes de temps. Il est difficiled’estimer le temps d’exécution d’un système temps réel. Du fait de la natureimprévisible des événements apériodiques, les concepteurs doivent faire des hypothèsessur la probabilité pour qu’ils apparaissent (et donc demandent un service) à un instantdonné. Ces hypothèses peuvent s’avérer incorrectes et les performances du systèmedélivré ne seront pas suffisantes. Dasarathy [DAS85] traite de la validation des tempsd’exécution. Du fait que les processus d’un système temps réel doivent coopérer, le concepteur doitcoordonner les communications entre processus. Les mécanismes de coordination des 7 7
  • 1 Le Monde Des Systèmes Temps Réel 888processus assurent l’exclusion mutuelle lors de l’accès à des ressources partagées. Lorsqu’unprocessus est en train de modifier une ressource partagée, les autres processus ne peuvent pasen faire de même. Parmi les mécanismes d’exclusion mutuelle on trouve les sémaphores, lesmoniteurs et les régions critiques. Le langage choisi pour l’implémentation de systèmes temps réel peut avoir lui aussi uneinfluence sur la conception. Ada [Taft92] a été conçu à l’origine, pour implémenter dessystèmes intégrés, et il dispose de caractéristiques comme la gestion des tâches, les exceptionset les clauses de représentation. La notion de rendez-vous représente un bon mécanisme pourla synchronisation des tâches. Malheureusement, ce mécanisme n’est pas adapté àl’implémentation de systèmes temps réel durs. Les systèmes temps réel durs sont souvent écrits en assembleur pour pouvoir tenir lescontraintes de temps. Parmi les autres langages, on trouve des langages de niveau systèmecomme C. Ils nécessitent un noyau d’exécution supplémentaire pour gérer le parallélisme. Afin de pouvoir gérer le développement des STR complexes, deux approchescomplémentaires sont souvent utilisées: décomposition et abstraction. Toutes les deuxforment des concepts de base des méthodes de génie logiciel.La décomposition, comme son nom l’indique, implique le partitionnement systématique d’unsystème complexe en parties plus fines jusqu’à ce qu’on puisse isoler ses composants, afin depouvoir les gérer de manière décentralisée. A chaque niveau de décomposition, on faitcorrespondre un autre niveau de description et une méthode de documentation de cettedescription.L’abstraction permet de considérer les détails et les particularités concernantl’implémentation. Cela permet de simplifier la vision en vers le système et les objectifs àatteindre en gardant ses propriétés et caractéristiques.VI-1-Encapsulation: La conception hiérarchique d’un logiciel permet la spécification et le développementdes sous-composants d’un programme. Le besoin à l’abstraction implique que ces sous-composants doivent être bien définis en terme de rôle, clairs et avoir des interconnexions etinterfaces non-ambigües. Si la spécification entière du système logiciel peut être vérifiéeseulement en terme de spécification des sous-composants immédiats, alors la décompositionest dite compositionnelle. C’est une propriété importante quand on veut analyserformellement les programmes.Les programmes séquentiels sont particulièrement amenés à des méthodes compositionnelleset un nombre de techniques sont utilisées pour encapsuler et représenter les sous-composants.VI-2-Cohésion et couplage: Les deux formes d’encapsulation discutées dans la section précédante nous amène àl’utilisation de modules avec des interfaces bien définies (et abstraites). Mais comment ungrand système peut être décomposé en modules? La réponse est liée aux méthodes dedécomposition des logiciels. Cependant, avant de discuter ces méthodes, il est approprié deconsidérer des principes plus généraux nous permettant une bonne encapsulation.Cohésion et couplage sont deux parmi les métriques décrivant les relations entre les modules.La cohésion est liée à la bonne concordance entre les modules.Allworth & Zobel[1987] donnent six mesures de cohésion:1. Coïncidence: les éléments du module ne sont pas liés autre que dans un contexte très superficiel.2. Logique: les éléments du module appartiennent à la même famille, en terme de vision globale du système, mais non pas en ce qui concerne l’application (logiciel) en cours. 8 8
  • 1 Le Monde Des Systèmes Temps Réel 9993. Temporel: les éléments du module sont exécutés à des temps similaires.4. Procédural: les éléments du module sont utilisés ensembles dans la même section du programme.5. Communication: les éléments du module travaillent sur la même structure de données.6. Fonctionnel: les éléments du module travaillent en collaboration afin de contribuer à la performance d’une seule fonction du système.Le couplage, par comparaison, est une mesure d’interdépendance des modules duprogrammes. Deux modules ont un couplage fort s’ils échangent entre eux des informationsde contrôle. Par contre, ils perdent le couplage si les modules ne communiquent que desdonnées. Une autre façon de voir le couplage est de considérer la facilité de changer unmodule (d’un système complet ) et le remplacer par un autre.Dans toutes les méthodes de conception, la meilleure, et celle ayant une bonne décomposition,vérifie une forte cohésion et un couplage minimum.Ce principe est également vrai dans les domaines de la programmation séquentielle etconcurrente.VI-3-Approches formelles: Elle consiste à modéliser le comportement des systèmes concurrents par l’utilisation desréseaux Petri [Brauer 1980]. Vue la variété des représentations obtenues, on introduit, dans leprocessus de modélisation, le concept des réseaux de transition prédicatives.La notion CSP (Communicating Sequential Processes) est développée, permettant laspécification et l’analyse des systèmes concurrents.Une logique temporelle (extension de la logique des prédicats et propositionnelle) a étéintroduite avec de nouveaux opérateurs afin de pouvoir exprimer les propriétés temporelles.VII-Méthodes de conception: L’industrie du temps réel utilise des méthodes structurées et les approches du génielogiciel pour la mise en œuvre des STR, vu que ces techniques sont applicables à tous lessystèmes de traitement d’information. Ces méthodes ne fournissent pas un support spécifiqueau domaine du temps réel, et ils manquent en richesse voulue quand on épuise toutes lespotentialités des langages d’implémentation utilisés.Typiquement, une méthode de conception structurée utilise un diagramme, dans lequel desarcs orientés schématisent le flux de données à travers le système, et les nœuds désignésreprésentent les sites dans lesquels les données sont transformées et donc traitées.Dans la littérature, on trouve les méthodes JSD (Jackson’s System Development), Mascot3 etPAMELA.Dans la méthode JSD, on utilise une notation pour la spécification et l’implémentation(conception détaillée). Bien entendu, l’implémentation n’est pas seulement une descriptiondétaillée de la spécification, mais de plus, elle est le résultat de l’application detransformations à cette dernière afin d’améliorer l’efficience.La méthode est basée sur un graphe comportant des processus et un réseau de connexions.Les processus sont de trois catégories:1. Processus d’entrée: détectant les actions dans l’environnement en les faisant passer au système.2. Processus de sorti : passant les réponses du système à l’environnement.3. Processus internes.Les processus peuvent être liés de deux manières différentes:1. Par des connexions asynchrones de blocs de données qui sont sauvegardées.2. Par des connexions de vecteurs d’état (ou inspection). 9 9
  • 1 Le Monde Des Systèmes Temps Réel 101010Une connexion du vecteur d’état permet à un processus de connaître l’état interne d’un autreprocessus sans avoir besoin de transfert d’information.Notez que la structure de graphe adoptée vise à représenter l’architecture du système.Malheureusement, JSD n’a pas une technique standard pour incorporer les contraintes detemps. De ce fait, on doit rajouter des dénotations aux diagrammes.Evidemment, JSD fournit une expression de la conception et non pas une conception.La conception incorpore inévitablement l’expérience et la créativité du concepteur.Il est souvent dit que les méthodes structurées et formelles sont orientées enrichissement de lacréativité! Ce n’est pas vrai. Ces techniques offrent une notation bien claire et comprise del’expression de la conception, et un moyen pour la vérification du bon placement de l’idéeadoptée, de ce fait, la conception a besoin de la spécification, et le logiciel implémente cetteconception.Le point le plus important dans une conception JSD est le flux de données. Une bonneconception est celle qui intègre ce flux naturel. L’avantage de ce flux de données est qu’ilpermet l’expression des contraintes de temps comme étant des attributs de données circulantdans le système.Une interruption génère un signal de contrôle ; le signal de contrôle est une transformation del’interruption. Ces transformations sont prises dans des processus en consommant du temps.Un choix approprié des processus va générer des échéances très visibles qui peuvent êtreordonnancées.Une fois la conception est obtenue, son implémentation doit être effectuée de manièresystématique. Avec un modèle de concurrence basé message, dans le langage del’implémentation, ce sera une tâche relativement facile, tout comme les processus deconception et les flux de données bufferisés qui peuvent être codés sous la forme de processusde programme. Malheureusement, cela peut produire une prolifération des processus et uneimplémentation anarchique.Afin de remédier à ces problèmes, on peut procéder de deux manières :1. Transformation de la conception de telle sorte qu’on aura besoin d’un minimum que possible de processus.2. Obtention d’un programme de processus excessif et le transformer afin de réduire le nombre d’objets concurrents.La méthode JSD est une transformation qui consiste à remplacer le processus de conceptionpar une procédure avec un seul processus d’ordonnancement, contrôlant l’exécution d’unecollection de ces procédures. De plus, les contraintes de temps provoque un problème majeur,qui est la difficulté de préserver les durées.En dépit de tout cela, la méthode JSD est appliquée avec succès dans les STR les pluscomplexes.La méthode Mascot a été développée pour la conception, construction et exécution desapplications temps réel. Les descriptions de Mascot doivent contenir: Les sous-systèmes. IDAs (general Intercommunication Data Areas) . Les processus. Des canaux (un IDA se comportant comme un buffer). Des poules (un IDA véhiculant et repositionnant l’information). Des serveurs (un élément de conception communicant avec les dispositifs du matériel externe). 10 10
  • 1 Le Monde Des Systèmes Temps Réel 111111VIII-Implémentation: Le langage de programmation est une interface importante et primordiale entre laspécification des besoins et l’exécution du code machine. La conception d’un langage reste undomaine de recherche actif. Malgré le passage naturel de la conception des systèmes versl’implémentation, les possibilités expressives des langages récents ne sont pas liées auxméthodologies de conception adoptées. Cette adoption poursuit logiquement l’étape decompréhension prévisible de l’étape d’implémentation.Il est possible d’identifier trois classes de langages de programmation qui sont utilisées dansle développement des systèmes temps réels. Ces langages sont: le langage d’assemblage, leslangages d’implémentation séquentielle des systèmes et les langages concurrents de hautniveau.IX-Critères da base d’un langage de conception: Un langage de programmation des STR peut être conçu seulement pour répondre auxbesoins du système. Cependant, il est rarement limité à cette fin.La plupart des langages temps réel sont aussi utilisés comme des langages d’implémentationdes systèmes à objectifs généraux, pour des applications spéciales telles que les compilateurset les systèmes d’exploitation.Young[1982] liste les six critères de base d’un langage de conception temps réel:1. La sécurité: la sécurité, dans la conception d’un langage, mesure la possibilité de détecter des erreurs de programmation, d’une manière automatique, par le compilateur ou par le support d’exécution. Evidemment, il y a une limite pour les types et nombres d’erreurs que le système du langage peut détecter. L a sécurité implique la possibilité de: Détecter facilement des erreurs et très tôt durant le développement du programme, et par conséquent, une réduction dans le coût de la correction et la maintenance. Avoir une compilation facile ne provoquant aucune extension au temps, donc le programme peut être exécuté autant de fois qu’on le compile. L’inconvénient de la sécurité est la complication dans sa mise au point, dans le cas d’un langage complexe, ce qui implique un surcoût dans le temps de la compilation et l’exécution.2. La lisibilité: la lisibilité d’un langage dépend d’une multitude de facteurs concernant le choix des mots clés appropriés, la possibilité de définir des types et la facilité de modulariser un programme. De ce fait, on offre un langage avec une clarté suffisante, permettant d’assimiler les principaux concepts d’opérations d’un programme particulier par une simple lecture du texte du programme. Une meilleure lisibilité implique: La réduction des coûts de la documentation. Une meilleure sécurité. Une bonne et parfaite maintenabilité.3. La flexibilité: un langage doit être suffisamment flexible, permettant au programmeur d’exprimer toutes les opérations demandées d’une manière cohérente et graphique.4. La simplicité: la simplicité possède les avantages suivants: Minimisation de l’effort exigé pour produire les compilateurs. Réduction du coût associé à l’apprentissage du programmeur. Diminution de la possibilité de commettre des erreurs de programmation.5. La portabilité: un programme doit être indépendant du matériel de l’exécution. pour un STR, cela est difficile à réaliser, car c’est comme si on va remplacer une partie du programme par une autre, ce qui implique des manipulations de ressources matérielles. 11 11
  • 1 Le Monde Des Systèmes Temps Réel 121212 Cependant, un programme doit être capable d’isoler les parties d’un programme dépendantes de la machine de celles qui sont indépendantes.6. L’efficience: dans un STR, les temps de réponse doivent être garantis. De ce fait, le langage doit être efficient. On doit, par conséquent, éliminer tout mécanisme provoquant une extension dans le temps.X-Langages de programmation des systèmes temps réel: L’implémentation d’une application temps réel est étroitement liée au choix du langagede programmation, les facilités et les avantages dont il dispose. On a pu identifier trois classes de langage de programmation utilisés dans ledéveloppement des STR qu’on va les présenter.X-1-Les langages d’assemblage: Initialement, la plupart des STR ont été programmés dans le langage d’assemblage, àcause du manque du support des langages de haut niveau sur les ordinateurs, et le langaged’assemblage qui semblait être le seul moyen réalisant des implémentations efficaces,permettant l’accès et la manipulation des ressources matérielles.Le problème majeur, avec l’utilisation des langages d’assemblage, est qu’ils sont orientésmachine, au lieu que ça soit orienté problème. Le programmeur peut être gêné par des détailsqui n’ont aucun rapport avec la programmation de ses algorithmes, ou même, par l’obscuritédes algorithmes eux même. Par conséquent, les coûts des développements restent élevés, etles programmes seront difficilement, ou même inefficacement modifiés, et ceci à l’intentionde corriger des erreurs ou améliorer les performances.D’autre part, l’absence de la portabilité oblige les programmeurs à réécrire tout programme,en vu de le transférer d’une machine à une autre. De plus, une formation, bien complète, estexigée pour tous ceux qui sont concernés par l’utilisation et la programmation en langaged’assemblage.X-2-Langages séquentiels d’implémentation des systèmes: L’apparition d’ordinateurs puissants et la progression dans la technologie descompilateurs ont rendu l’écriture des logiciels temps réel plus avantageuse. On a pu constaterle développement de plusieurs langages, spécialement conçus pour la programmation dessystèmes embarqués. Ces langages ont en commun la propriété qu’ils sont séquentiels. Deplus, ils n’offrent pas aux STR le bon contrôle du temps réel ni la fiabilité adéquate.X-3-Langages de programmation concurrents de haut niveau: Le langage de programmation Modula, développé par Wirth, a prouvé beaucoup dequalités pour la programmation et l’exploitation des dispositifs de la machine. Plusieursexpériences, basées sur l’implémentation en Modula et son utilisation, sont arrivées àModula-2, un langage d’implémentation de systèmes généraux.De nouveaux langages apparaissent, tels que PERL, utilisés intensivement pour lesapplications de contrôle de processus, Mesa (Xerox Corporation 1985), utilisé par Xerox,dans ses bureaux, et CHILL qui a été développé afin de répondre aux besoins du CCITT dansles applications de télécommunication.Tous ces langages, et autres, sont destinés pour le développement des systèmes temps réelembarqués.Le langage Occam, apparu récemment et ses propriétés diverses, avait un rôle important dansl’apparition du domaine des applications embarquées couplées et distribuées. 12 12
  • 1 Le Monde Des Systèmes Temps Réel 131313XI- Analyse des Contraintes de Tâches: Un modèle de tâches temps réel permet de spécifier l’architecture fonctionnelled’un système temps réel. Chaque tâche est définie par un ensemble d’attributs décrivantles contraintes auxquelles elle est soumise. Traditionnellement, les applications temps réel étaient souvent décrites par lemodèle des tâches périodiques [Liu73]. Ce modèle décrit une application temps réel parun ensemble fini (appelé aussi configuration) de tâches périodiques. Une variante de cemodèle consiste à prendre en compte les tâches apériodiques. Dans ce modèle, toutes lestâches doivent s’exécuter jusqu’à leurs fins. Cependant, pour des besoins nouveaux dessystèmes temps réel, certaines tâches n’ont pas la contrainte de terminer nécessairementleur exécution. Ce qui a donné naissance à deux nouveaux types de modèles: le modèledes tâches incrémentales et le modèle des tâches à résultats imprécis. Diverses variantes de ces modèles ont été développées. Certaines d’entre elles sontle résultat d’intégration des modèles existants. D’autres traitent des contraintes de typeressources ou synchronisation.XI-1-Contraintes de temps: La plupart des contraintes de temps sont celles introduites par les modèles detâches périodiques et apériodiques. Ces deux types de modèles sont souvent utilisés entemps réel. En effet, un système temps réel est souvent concerné par le contrôle d’uncomportement continu (procédé) qui nécessite des actions répétitives (tâchespériodiques) ou aléatoires (apériodiques). Il existe trois types de tâches temps réel qui sont conçues pour superviser etcontrôler les différentes fonctions: Les tâches périodiques, sporadiques et apériodiques[Klein94]. Les tâches périodiques sont les plus souvent trouvées dans les systèmes temps réel.Afin de superviser un système physique ou un processus, le système d’ordinateur doitcapter régulièrement des informations sur le processus et réagir quand des résultatsappropriés sont obtenus ou des informations spécifiques sont lues. Cet échantillonnagerégulier d’informations est effectué par la tâche périodique par une série continued’invocations régulières, commençant par une invocation initiale à un certain temps I.Les invocations se produisent périodiquement toutes les T unités de temps. Chacune deces invocation possède un temps d’exécution de C unités qui peut être déterministe oustochastique. C indique souvent la borne maximale (ou le pire des cas) du tempsd’exécution. Chaque invocation de tâche aura une contrainte de temps explicite, appelél’échéance qui signifie que l’invocation doit se terminer avant un certain temps D aprèsson passage à l’état prêt. Ainsi, la première invocation doit se terminer dans le tempsI+D, la deuxième dans I+T+D, etc. Les tâches périodiques sont habituellement invoquées par les temporisateursinternes avec une périodicité choisie telle qu’elle assure une latence suffisamment courtepour réagir aux événements de changement dans l’environnement en question. Les tâches sporadiques et apériodiques sont invoquées à des intervalles irréguliers.La tâche sporadique possède une échéance stricte (hard) et une borne sur l’intervalleséparant deux invocations. La tâche apériodique peut s’effectuer avec un intervallealéatoire qui sépare deux invocations. Par ailleurs, un processus est une séquence d’opérations qui doivent être exécutéesdans un ordre prescrit [Xu93]. Les processus peuvent être divisés en deux catégories: lestâches de la première catégorie ont une échéance «stricte» (hard), c’est-à-dire que lasatisfaction de ses échéances est critique pour le fonctionnement du système, celles de la 13 13
  • 1 Le Monde Des Systèmes Temps Réel 141414deuxième catégorie ont des échéances «relatives» (soft), en ce sens que bien qu’un courttemps de réponse est souhaitable, un dépassement occasionnel de l’échéance peut êtretoléré.XI-2-Contraintes d’importance:Les tâches d’une application temps réel ne sont pas toutes aussi importantes les unes queles autres. En effet, du point de vue du concepteur d’une application, une tâche peut êtreplus importante qu’une autre. Cette caractéristique de la tâche est déterminée par desparamètres (poids, degré d’urgence, priorité externe, tâche critique, etc.). L’échec d’unetâche critique peut entraîner l’arrêt d’exécution du système, situation qui peut êtrecatastrophique. Par exemple, dans un système de contrôle de vol, le concepteur del’application peut associer un poids fort à la tâche qui contrôle la stabilité de l’avion,afin de refléter sa nature critique. Si cette tâche échoue dans le respect de son échéance,l’avion peut s’écraser. Par contre, il accorde un faible poids à la tâche qui contrôlel’enregistreur de vol.XI-3-Contrainte d’interruption Cette contrainte permet d’exprimer si une tâche est interruptible ou non. Parexemple, dans un système temps réel réparti, une tâche qui ne fait que du calcul interne,peut être interrompue. Par contre, la tâche chargée de l’émission d’une trame ne peutêtre interrompue et elle doit se terminer. Si son émission est interrompue, elle doit larecommencer complètement. Une tâche interruptible peut être interrompue par une autretâche prioritaire. Son exécution peut être reprise ultérieurement. Lorsqu’une tâche estinterrompue, elle peut être forcée de libérer temporairement les ressources qu’elle aacquises.XI-4-Contrainte de terminaison Dans des conditions de surcharge, certaines applications temps réel se contententd’exécuter quelques tâches partiellement. De telles applications peuvent se contenter derésultats acceptables. La contrainte de terminaison ont été prises en compte dans lesmodèles de tâches incrémentales et les modèles de tâches à résultats imprécis.XI-5-Contraintes événementielles: Un événement peut démarrer certaines tâches et/ou terminer d’autres. Lesconditions d’activation/terminaison de tâches peuvent être décrites par une combinaisond’opérateurs de la logique temporelle (avant, après, etc.) [Chung95, Sahraoui85] avecdes arguments qui sont (une date, un changement d’état, une expiration d’un délai, etc.).Activation/terminaison d’une tâche peut être utilisé aussi bien pour décrire descontraintes temporelles que des contraintes décrivant son interaction avec d’autrestâches.Comme ces contraintes peuvent exprimer d’autres situations (autres que les contraintesde temps), cela justifie de les considérer indépendamment et dans la partie descontraintes intrinsèques à une tâche.XI-6-Les contraintes extrinsèques: Les contraintes extrinsèques à une tâche décrivant les contraintes résultant de soninteraction avec d’autres tâches. Au cours de leur exécution, les tâches ne sont pasindépendantes les unes des autres (relations de coopérations, relations de compétition,etc.). Les relations de coopération indiquent l’existence d’un ordre d’exécution, de 14 14
  • 1 Le Monde Des Systèmes Temps Réel 151515synchronisation, de communication, etc. Les relations de compétition indiquent lamanière avec laquelle les tâches utilisent des ressources partagées. Généralement, dans les applications informatiques, la mise en œuvre descontraintes de coopération et de compétition est réalisée par des mécanismes desynchronisation (rendez-vous, moniteur,…), d’exclusion mutuelle (sémaphores,…), decommunication (boites aux lettres,…), et bien d’autres.XI-7-Contraintes d’accès aux ressources: Les tâches utilisent des ressources disponibles en nombre limité pour lesquelleselles entrent en compétition. La bonne utilisation des ressources partagées se traduit parl’existence de contraintes de ressources. Parmi les contraintes de ressources on peutdistinguer les contraintes liées à leur utilisation et celles liées à leur fonctionnement. Une ressource est dite non préemptible (telle qu’une imprimante) si elle ne peutêtre retirée à une tâche Ti au profit d’une autre tâche sans qu’il y ait avortement de latâche Ti; une ressource est dite consommable (telle qu’un missile dans une applicationmilitaire) si après son utilisation par une tâche, elle est consommée et donc n’existeplus, etc. Parmi les exemples des contraintes liées au fonctionnement des ressources, on peutciter [Liu94]: la durée d’acquisition d’une ressource, la durée de restitution d’uneressource et la durée de commutation de contexte. La durée d’acquisition de ressourcesest la durée maximale qui peut être prise en compte par une tâche afin d’acquérir uneressource oisive due aux propriétés de la ressource elle même. La durée de restitutiond’une ressource est la durée maximale séparant l’instant où une tâche libère la ressourceet l’instant où la ressource n’est plus dans le contexte de la tâche et donc disponible pourd’autres tâches. La durée de commutation de contexte est la durée nécessaire pourcommuter une ressource d’une tâche à une autre, généralement suite à une interruptionde la première tâche par la seconde. Dans plusieurs cas, la durée de commutation decontexte d’une tâche est égale à la somme de durée d’acquisition et de la durée derestitution de ressource. Cependant, ceci n’est pas toujours le cas. En effet, dans le caspar exemple d’un seul processeur, les informations de gestion de ce dernier telles que lescontenus de registres, nécessitant d’être sauvegardées et restaurées durant unecommutation de contexte et pas pendant l’acquisition ou la restitution. Les contraintes d’accès de ressources associées à une tâche, indiquent, d’une part,le type de ressources indispensables à son exécution, et d’autres part, le mode d’accès(exclusif, partagé, etc.) qu’exige la tâche sur les ressources. Pour ce dernier cas,l’expression de telles contraintes est nécessaire pour décrire les situations où la tâchedésire un accès en exclusion mutuelle sur une ressource à n points d’accès. Enenvironnement temps réel, la connaissance des contraintes de ressources parl’algorithme d’ordonnancement est nécessaire pour qu’il puisse effectuerl’ordonnancement des tâches qui les utilisent et réaliser leur gestion dans le cas où lagestion de ressources est une fonction de l’ordonnanceur.XI-8-Contraintes de placement: Le besoin d’expression de contraintes de placement est spécifique aux systèmescentralisés multiprocesseurs ou répartis. En effet, une tâche peut exiger que sonexécution se fasse sur un certain processeur (pour des raisons de compatibilité du codeexécutable par exemple) ou sur un site donné (parce qu’elle fait des entrées/sorties surun dispositif particulier, par exemple). 15 15
  • 1 Le Monde Des Systèmes Temps Réel 161616XI-9-Contraintes de tolérance aux fautes: En environnement temps réel, les contraintes de tolérance aux fautes, associées auxtâches, sont capitales pour exiger que le respect de leur contraintes temporelles soitvérifié, ceci même en présence de fautes liées aussi bien au système d’exploitation, àl’exécution des tâches, qu’au matériel (ordinateur, réseaux de communication, etc.).XII- Architectures Temps Réel: Dans la plupart des architectures de contrôle, la façon de partager les rôles deprises de décision nous révèle la manière de fonctionnement des architectures. Les rôlesdes différents aspects du problème de contrôle sont souvent partagés à travers lesmodules. Un rôle est constitué d’un ensemble de responsabilités homogènes conçuesdans la perspective d’un objectif déterminé. On affecte à chaque module un ou plusieursrôles. Les modules sont souvent interdépendants dans la perspective de réaliser leurspropres objectifs ou ceux du système global. Ces dépendances sont habituellementétablies à travers des communications clairement définies entre les modules. Le type decommunication entre les modules et les types de rôles affectés aux modules, ont unimpact significatif sur la façon d’interaction du système avec son environnement. Le rôle de prise de décision dans un système temps réel peut être partagé commeétant une décomposition soigneusement ordonnée de tâches d’un côté, et une étroitecoopération entre ces tâches d’un autre côté. Le premier cas est souvent considérécomme une forme de contrôle centralisé, le second est un contrôle décentralisé.XII-1 Architecture centralisée: Dans ce type d’architecture, le système est constitué d’une seule unité detraitement, composée d’un ou de plusieurs processeurs se partageant une mémoirecommune. La principale caractéristique d’une telle installation, par rapport à la suivante,est que la durée de transmission de l’information d’une tâche à une autre est négligeabledevant le temps qui s’écoule entre deux transitions d’états (points observables). Cetteunité de traitement est reliée par des interfaces à une série de capteurs et d’actionneurs.La datation se fait par une horloge unique qui est utilisée pour la gestion du temps(temporisation, chien de garde, etc.). La mémoire commune contient le contexte destâches et les données de l’application. Elle permet de mémoriser instantanément, l’étatglobal du système. De plus, elle représente le mécanisme de base pour la communicationet la synchronisation entre les tâches. Les avantages de cette architecture sont ceux des systèmes centralisés: contextecentralisé, temps cohérent, applications simples à mettre en œuvre. Par contre, lesperspectives d’évolution d’un tel système sont limitées par ses possibilités physiques.De même, le seul traitement à apporter aux surcharges est de fonctionner en modedégradé. Comme exemple de contrôle centralisé, considérons un système de robot dont lasimple hiérarchie de contrôle consiste en un planificateur de mouvement et un contrôleurde mouvement. Le planificateur de mouvement doit acquérir des données del’environnement au moyen des capteurs, construire un modèle interne de la réalité sur labase des données collectées et ensuite, faire le choix de la meilleure action. Le plan del’action sera soumis au contrôleur de mouvement sous la forme d’une trajectoire depoints dans certain cadre cartésien de coordonnées. Le rôle du contrôleur de mouvementest maintenant de suivre cette trajectoire autant précisément que possible. Le contrôleur de mouvement a un rôle temps réel critique de conduire le robot toutau long d’un chemin passant par certains points. Tous les aspects de contraintes detemps au niveau du contrôleur de mouvement sont liés à la capacité d’effectuer un 16 16
  • 1 Le Monde Des Systèmes Temps Réel 171717mouvement sans heurts avec des déviations minimales par rapport au chemin spécifié.La validité de ce chemin incombe au planificateur de mouvement. Les contraintes de temps du planificateur de mouvement sont quelque peu moinssévères, et plus négociables que celles du contrôleur de mouvement. Dans ce type desystème, chaque niveau travaille sur un sous problème spécifié par un niveau supérieur.Dans ce sens, le contrôle est centralisé au sommet de la hiérarchie.XII-2 Architecture répartie: Les fonctions de l’application peuvent être prises en compte par n’importe quelleunité de traitement, grâce aux possibilités de communication du médium. Les capteursémettent sur le réseau les données (mesures ou événements) qui sont traitées dans un ouplusieurs sites. En environnements répartis, de nouveaux problèmes se posent et auxquels il fautfaire face: le placement des tâches, la mise à jour des copies multiples de données, lasynchronisation de tâches, etc.Les inconvénients des systèmes répartis sont: difficulté de la gestion répartie desressources, incohérences des horloges locales, prise en compte des pannes, absence decontexte global, etc. Par contre, c’est le schéma qui semble le plus souple par sescapacités d’évolution, par ses possibilités de tolérance aux pannes et de répartition de lacharge ou capacités de réponses aux surcharges. XIII- Conclusion Les systèmes temps réel sont souvent distribués et possèdent différentescontraintes de temps, de sécurité, de fiabilité, et de robustesse, imposées parl’environnement de l’application. Comprendre et contrôler le comportement temporelconstituent un aspect critique pour assurer la sécurité et la fiabilité. La vitesse (vitesses de processeurs par exemple) seule, n’est pas suffisante pour lasatisfaction des contraintes de temps. Des techniques rigoureuses de gestion deressources doivent aussi être utilisées, afin de prévenir des situations dans lesquelles destâches longues et à priorités réduites bloquent d’autres tâches à priorités plus élevées ettemps d’exécution réduits. Le principal guide de gestion des ressources des systèmes temps réel est lacapacité de déterminer si le système peut satisfaire toutes ses contraintes de temps. Cebesoin de prévisibilité nécessitent le développement et l’utilisation de modèlesd’ordonnancement et des techniques analytiques. Leurs applications nécessitentl’intégration de certaines qualités de services, particulièrement en matière deprévisibilité des temps d’exécution des tâches, de tolérance aux fautes, de disponibilitéet de performances. Ils doivent présenter des interfaces utilisateurs conviviales. Laprévisibilité dans le contexte temps réel «hard» requiert une importance capitale. Cessystèmes peuvent comprendre des ressources hétérogènes telles que les CPUs, lesréseaux, et les périphériques d’entrée/sortie qui doivent être ordonnancées de façon àêtre prévisibles, flexibles, et faciles à analyser mathématiquement. La prévisibilité nécessite le développement de modèles d’ordonnancement et detechniques analytiques afin de déterminer si le système temps réel peut ou non satisfaireles contraintes de temps. Les difficultés de spécifications, analyse, et ordonnancements de processus dansles systèmes temps réel à contraintes de temps strictes (hard) sont augmentées par le faitque le système physique contrôlé consiste souvent en plusieurs sous-systèmesindépendants produisant des signaux asynchrones de capteurs et valeurs de contrôle[Kramer93]. De tels systèmes peuvent avoir besoin de logiciels de contrôle distribué 17 17
  • 1 Le Monde Des Systèmes Temps Réel 181818fournissant des capacités adéquates de traitements et de temps de réactions poureffectuer des tâches périodiques avec des ordonnancements serrés et pour le traitementdans le temps requis d’événements arrivant de façon asynchrone. 18 18
  • 2 Ordonnancement Des TâchesI- Types de tâches temps réel: Nous utilisons une classification de ces tâches en fonction des propriétés de la liste de leursdates doccurrences. Trois types de tâches ont été identifiées : périodiques : Une tâche périodique est définie comme une tâche qui doit être prête à êtreexécutée à des intervalles de temps fixés (ou périodes) et dont lexécution doit être terminéeavant le début de la période suivante [Bestravos93]. Une autre définition dit quune tâchepériodique demande une allocation du temps processeur à des intervalles réguliers, ces tempsprocesseur devant être alloués de façon à ce que lexécution de la tâche ne dépasse pas ses dateslimites [Howell94] [Gupta94]. apériodiques: [Burns90] Lactivation dune tâche apériodique est essentiellement due à unévénement aléatoire et est déclenchée généralement par une action externe au système. Sa datelimite est fixée par lenvironnement extérieur. Les tâches apériodiques ont également descontraintes de temps qui leurs sont associées, par exemple le démarrage de leur exécution àlintérieur dune période de temps prédéfinie. Souvent les tâches apériodiques sont déclenchéespar les événements critiques de lenvironnement externe du système, cest pour cela que leursdates limites sont souvent contraintes. sporadiques: Une tâche sporadique est comme pour une tâche apériodique souvent déclenchéepar un événement extérieur au système, mais on constate lexistence dune durée minimum entredeux événements apériodiques (issus de la même source). La tâche sera alors dite sporadique[Howell94] [Burns90].II- Ordonnancement des applications temps réel: Dans les systèmes temps réel, un problème d’ordonnancement consiste, à partir d’unearchitecture matérielle (une ou plusieurs machines mono ou multiprocesseurs, un ouplusieurs réseaux,…), d’une architecture fonctionnelle, et d’un ensemble d’objectifssouhaités, à trouver un planning d’exécution des tâches de façon à garantir le respect descontraintes de temps. L’ordonnancement joue un rôle important puisque c’est lui qui définit le planningd’exécution de tâches de façon à ce que les contraintes de tâches soient vérifiées. Dans laplupart de ces systèmes, le respect de ces contraintes de temps reste le principal critère àsatisfaire. 19
  • 2 Ordonnancement Des Tâches Un problème d’ordonnancement dans un système temps réel est défini par le modèledu système, les tâches et leurs natures, ainsi que les objectifs que l’algorithmed’ordonnancement doit réaliser. Le modèle de système décrit l’architecture matérielle du système disponible(machine(s), réseau(x), etc.), qu’on appellera services, et les contraintes associées. Les tâches et leurs natures sont décrites au niveau de la spécification fonctionnelle del’application et des contraintes associées. Comme exemple de ces contraintes, on peut citer[Cardeira94]: les contraintes de temps, les contraintes de ressources, de précédence, etc. Le challenge de l’ordonnancement est de garantir que toutes les contraintes duproblème sont satisfaites, particulièrement les contraintes de temps. L’ordonnanceurproduit un planning d’exécution de tâches, qui assure le respect des contraintes. Unordonnancement (planning) valide est un ordonnancement qui vérifie, sur une durée infinie,que toutes les contraintes sont satisfaites. L’intervention du temps fait des systèmes réactifs des systèmes temps réel. Le tempsest alors un facteur déterminant puisqu’il intervient aussi bien dans la définition descritères de performances (par exemple, appliquer en une millisecondes une commandeexterne à chaque fois qu’un capteur détecte une mesure excédant une certaine valeur) quedans le séquencement interne d’un logiciel (par exemple, lancer une tâche de surveillanceséquentiellement toutes les 100 millisecondes). Les méthodes du génie logiciel concernant les systèmes informatiques usuels fontappel à des modèles fonctionnels. En effet, la dynamique de ces systèmes étant pauvre, unedécomposition fonctionnelle structurée et l’identification des informations circulant entrefonctions sont suffisantes pour spécifier la plupart des problèmes [Vallotton91]. Les approches fonctionnelles ne sont pas satisfaisantes pour traiter la spécificationdes systèmes réactifs, car les aspects émergeant de ces derniers sont essentiellementdynamiques. Un système réactif n’évolue pas seulement en fonction de ces entrées, maisaussi des états internes. Un exemple trivial l’illustre: un logiciel qui doit exécuter uneroutine d’interruption sauf si elle survient alors qu’il est déjà en cours de traitement. Unecomposante de son état est «être en cours de traitement de l’interruption», sa connaissanceest nécessaire pour prévoir le comportement du système. Dès que l’on a affaire à un système temps réel d’une certaine complexité, le point devue du comportement réactif devient primordial. Il doit donc intervenir dans sa 20
  • 2 Ordonnancement Des Tâchesmodélisation. Les méthodes spécifiques du temps réel introduisent généralement lecontrôle, mais davantage pour assurer la cohérence des modèles fonctionnels que pourintroduire de réels moyens de modéliser le comportement. Dans la pratique, les portions temps critique des systèmes temps réel durs continuentd’être implémentées par des langages de programmation de bas niveau. Elles sontmanuellement réglées afin de satisfaire toutes les contraintes. Les développeurs rencontrentde grandes difficultés dans l’élaboration et l’analyse de codes complexes et ce, enl’absence d’un langage, supportant des outils appropriés de spécification des contraintes detemps [Chung95, Gerber97]. La spécification des contraintes de temps de granularité très fine dans le contexted’un langage de programmation de haut niveau n’est pas encore possible. On établitmanuellement des portions de code en langage assembleur pour exprimer des contraintesstrictes de temps. Ce qui rend ces programmes très difficiles à écrire et à maintenir, et unordonnancement automatisé devient presque impossible. Les langages tels que Ada[Taft92] ne permettent de spécifier les contraintes de temps qu’entre les tâches,lexicographiquement adjacentes dans le code source, et ne permettent pas de les spécifierentre les instructions. Cette adjacence est aussi artificielle qu’insuffisamment expressive.III- Etude formelle Dans les STR, garantir que les tâches s’exécutent en respectant leurs échéances prescritesest un point critique pour assurer l’intégrité de ces systèmes (systèmes en robotique) et la réussitede ses missions. Capteur1 Actionneur1 Capteur2 Actionneur2 Flux d’Information Echantillonnage Intervention Système Réaction Capteurs de Actionneur k et Contrôle Temps Actionneur m Réel Capteur n Actionneur n Fig I-4:Modélisation du fonctionnement d’un système temps réel 21
  • 2 Ordonnancement Des Tâches Dans de tels systèmes, les tâches sont accomplies (exécutées) régulièrement etpériodiquement, dans le but de contrôler des processus physiques et le fonctionnement desappareils de contrôle. Elles échantillonnent des informations pour effectuer un traitementspécifique, dans le but de produire des commandes pour les actionneurs. L’invocation de ces tâches typiques se fait périodiquement, à chaque unité de temps T.L’exigence la plus commune est qu’une invocation d’une tâche doit être achevée (complétée)dans D unités de temps après qu’elle ne soit dans l’état Prêt. Les paramètres T et D sont appelésrespectivement la période et l’échéance. Dans le cas où on confronte un problème de l’accomplissement de la tâche dans le tempsapproprié, ou on marque la présence d’un flux dans la logique du programme, on pourramarquer, par conséquent, des résultats catastrophiques dans les STR hards. On peut en déduireque la rencontre de contraintes de temps est extrêmement importante dans de tels systèmes. Poursatisfaire leurs échéances, les tâches doivent être ordonnées d’une manière adéquate. Les algorithmes d’ordonnancement de tâches des les STR typiques confirment que lestemps d’exécution dans le plus pire des cas sont connus. Un tel système est conçu pour s’assurerque toutes les tâches peuvent s’achever au bout de leurs échéances tant qu’il n’y a pas une tâchedans le système qui s’exécute pendant une durée supérieure au temps d’exécution dans le cas leplus pire. Une tâche qui dépasse le temps d’exécution prévu, peut entraîner une perte d’échéanceet l’échec total du système. Différents modèles et théories ont été développés et utilisés comme une base permettantl’étude et l’analyse du comportement des STR. En particulier, la théorie d’ordonnancement avecpriorités fixes a prouvé sa capacité de développement d’une sorte de découverte théorique pourl’analyse du comportement temporelle des systèmes et de conception de systèmes amenant àréaliser cette analyse. Dans un simple ordonnancement Rate-Monotonic, Gerber & Hong ont montré qu’ilspeuvent améliorer l’ordonnançabilité en divisant le programme de la tâche en deux fragments. Lepremier dépend d’un événement observable, et le deuxième concerne un calcul interne (local) quipeut être exécuté plus tard. Cependant, cette approche traite seulement des programmes simpleset monolitiques. Dans le but de considérer une classe plus générale de problèmes d’ordonnancement,Gonzalez, Härbour et al ont réalisé un travail de fond pour le raisonnement à propos du 22
  • 2 Ordonnancement Des Tâchescomportement temporel dans le contexte des tâches composées d’une série de sous-tâches quis’exécutent avec des priorités multiples (dynamique). La notion dordonnanceur de tâches prend toute sa signification lorsquon souhaite faireexécuter les tâches par une architecture matérielle. Il faut être capable en cours dexécution dusystème, dallouer du temps CPU dune ressource de larchitecture matérielle à toute tâche quiferait son apparition, et ce avant sa date limite dexécution. Un algorithme qui alloue les tempsprocesseurs pour chaque tâche dans un système de tâches est un algorithme dordonnancement[Burns90] [Howell94]. Ces algorithmes peuvent avoir diverses propriétés. On peut les qualifier : • dalgorithme optimal : [Krithi94] [Di Natal] [Atanas94] [Howell94] Un algorithme dordonnancement est optimal sil peut correctement ordonnancer un système de tâches chaque fois que ce système est ordonnançable ; • dalgorithme NP-complet : [Di Natal] NP est la classe de tous les problèmes de décision pouvant être résolus dans un temps polynomial par une machine non- déterministe. Si un problème R appartient à la classe NP et que tous les problèmes de la classe NP sont polynomialement transformables en R alors le problème R est reconnu NP-complet. Lalgorithme gérant ces problèmes décisions est alors NP-complet ; • dalgorithme NP-hard : [Di Natal] NP est la classe de tous les problèmes de décision pouvant être résolus dans un temps polynomial par une machine non- déterministe. Si tous les problèmes de la classe NP sont polynomialement transformables en un problème R mais quon ne peut pas prouver que ce problème R appartient lui-même à la classe NP, alors le problème R est dit NP-hard. Lalgorithme gérant ce problème de décision est dit NP-hard.III- Ordonnancement "à base de priorités": Nous allons regarder le cas particulier de deux algorithmes (ces deux algorithmes sont trèsétudiés au niveau de la recherche sur lordonnancement temps réel) : le Rate Monotonic et leEarliest Deadline.III-1- Lalgorithme Rate Monotonic: La notion dordonnancement Rate Monotonic a été introduite en premier par Liu etLayland [Liu73] en 1973. Lordonnancement Rate Monotonic est un ordonnancement statique etne sapplique que pour des tâches périodiques. Il sagit dun algorithme dordonnancement àpriorités fixes. Lavantage dune allocation fixe des priorités est que les priorités, allouées une 23
  • 2 Ordonnancement Des Tâchesfois pour toutes, ne sont pas réévaluées au cours du temps. Le terme Rate Monotonic dérive de lafaçon dont sont allouées les priorités aux différentes tâches, elles sont allouées selon unefonction "Monotonic" du "Rate" (de la période) de la tâche. Plus la tâche a une période courte,plus la priorité allouée sera importante. De nombreux travaux ont étendu lapplication du RateMonotonic aux tâches synchronisées, à données partagées, aux systèmes avec des tâchesapériodiques...III-2- Lalgorithme Earliest Deadline: Tout comme pour le Rate Monotonic, la notion dalgorithme Earliest Deadline a étéintroduite en premier par Liu et Layland [Liu73] en 1973. lordonnancement Earliest Deadline estun ordonnancement dynamique. Il peut sappliquer pour lordonnancement de tâches périodiquesainsi quapériodiques car il sagit dun algorithme dordonnancement à priorités dynamiques. Leterme Earliest Deadline vient de la façon dont les priorités sont allouées aux tâches. La tâchedont la date limite qui arrive le plus tôt aura une priorité élevée. Les priorités sont constammentréévaluées au cours du temps (par exemple dans le cas où une nouvelle tâche arrive et que sadate limite est la plus proche).II-3- Critère dordonnançabilité pour chacun de ces algorithmes: Dans le cas de systèmes où seules des tâches périodiques doivent être ordonnancées, destravaux ont été réalisés pour déterminer, connaissant lensemble des tâches, à partir de quelpourcentage dutilisation CPU les dates limites de ces tâches seront sûres dêtre respectées[Liu73]. Le taux dutilisation CPU pour une tâche i est le rapport entre le temps dexécution de cettetâche et sa période . Le taux dutilisation CPU pour un groupe de tâches est la somme de cesrapports. Pour lalgorithme dordonnancement Rate Monotonic le pourcentage dutilisation CPU doitrespecter la relation suivante si on veut être sûr que toutes les dates limites des différentes tâchessoient garanties : (1) Lorsque n devient important, on remarque que pour être sûre de respecter les dateslimites des différentes tâches en utilisant lalgorithme Rate Monotonic pour ordonnancer lestâches, le processeur doit être utilisé à moins de 69 %. Dans le cas particulier où les périodes des 24
  • 2 Ordonnancement Des Tâchesdifférentes tâches sont harmoniques, une étude a montré que quelque soit le taux dutilisationCPU si lordonnancement est réalisable alors il pourra être réalisé. Pour lalgorithme dordonnancement Earliest Deadline le pourcentage dutilisation CPUdoit respecter la relation suivante si on veut être sûr que toutes les dates limites des différentestâches soient garanties : (2) Même lorsque n devient important, on remarque que quelque soit le taux dutilisationCPU, si lordonnancement est réalisable, il pourra être réalisé.III-4- Les limites des deux algorithmes: Ces algorithmes ne posent pas de problèmes dapplication tant que lon reste dans uneutilisation avec des tâches périodiques (dans le cas du Rate Monotonic seulement, le EarliestDeadline pouvant prendre en compte les tâches apériodiques), pas de protocoles (partage dedonnées entre tâches, ...), pas de surcharges. Des études ont permis lamélioration de ces algorithmes pour prendre en compte lesdifférents cas cités ci-dessus.IV- Modes dordonnancement: Lordonnancement est une fonction centrale dans un système temps réel. En fonction delapparition des entrées en provenance du système contrôlé (entraînant la demande dexécutiondune tâche), il doit réorganiser laffectation des ressources processeur en vue du respect desdates limites de chaque tâche. Lordonnancement peut se faire de deux façons. La première façon dordonnancer estlordonnancement «offline» pour lequel lordonnancement est planifié dès la conception, destables dordonnancement sont créées et vont être utilisées en fonctionnement. Durant lefonctionnement, le système se contente de lancer les tâches aux dates prévues. La deuxièmefaçon est lordonnancement online pour lequel lordonnancement est réalisé à chaque instant dufonctionnement du système. Si les ordonnancements réalisés offline donnent des systèmes trèsrapides à lexécution, et dune grande fiabilité, ils ne peuvent sappliquer quaux systèmes dont onconnaît entièrement a priori le système contrôlé. Dans le cas contraire, un ordonnancementonline est nécessaire pour replannifier les tâches à lapparition dun nouvel événement significatif[Atanas94] [Howell94]. Les algorithmes dordonnancement peuvent également être dits statiques ou dynamiques.Un algorithme dordonnancement est dit statique lorsque lordonnancement est prévisible avant la 25
  • 2 Ordonnancement Des Tâchesmise en fonctionnement du système, il faut pour cela connaître les tâches a priori. Un algorithmedordonnancement est dit dynamique lorsque lordonnancement est créé au fur et a mesure delarrivée des tâches dont on peut ne rien connaître a priori. Un ordonnancement statique est plusfiable mais moins flexible quun ordonnancement dynamique (pour un ordonnancement statiqueil faut connaître lensemble des tâches à réaliser, alors que pour un ordonnancement dynamiquece nest pas la peine de toutes les connaître) [Atanas94]. A partir de ces différentes propriétés qui sont associées aux algorithmes dordonnancement,une classification de ces algorithmes ressort : • les ordonnanceurs que lon peut qualifier de "tout planifiés". Ces ordonnanceurs sont des ordonnanceurs offline et statiques. En effet, un ordonnancement est créé à partir dune table dordonnancement qui est construite à laide des caractéristiques des différentes tâches. Cet ordonnancement est ensuite appliqué sur le système. Cette approche ne peut sappliquer que pour lordonnancement de tâches périodiques (ou qui ont été transformées en tâches périodiques) puisquil faut connaître à priori lensemble des tâches et de leurs caractéristiques. Cette approche est hautement prédictible mais nest pas flexible : un changement sur une des tâches ou une de ses caractéristiques entraîne la reconstruction totale de la table [Krithi94] ; • les ordonnanceurs que lon peut qualifier dordonnanceurs "à base de priorités". Ces ordonnanceurs sont online mais peuvent être statiques ou dynamiques. Des priorités sont affectées aux tâches, lordonnanceur va ordonnancer les tâches suivant la valeur de la priorité qui leur est affectée. Pour ce type dordonnancement apparaît la notion de préemptivité (si une tâche de basse priorité est en train dêtre exécutée et quune tâche de priorité plus haute est déclenchée, la tâche de basse priorité sera interrompue et le processeur sera affecté à la nouvelle arrivée) [Krithi94]. Un algorithme dordonnancement peut être à priorités fixes (statiques) ou dynamiques [Atanas94]. Dans le cas dun ordonnancement à priorités fixes, on va associer à chaque tâche une priorité, cette priorité va rester la même tout au long du fonctionnement du système. Dans le cas dun ordonnancement à priorités dynamiques la valeur de la priorité dune tâche va évoluer au cours du fonctionnement du système ; • les ordonnanceurs que lon peut qualifier de "dynamiques". Ces ordonnanceurs sont online et dynamiques. Il apparaît deux approches "dynamiques", les approches "Dynamic Planning-Based" et les approches "Dynamic Best-Effort". Les approches "Dynamic Planning- Based" lorsquune tâche apparaît vont, avant de lexécuter, créer un plan dexécution de cette tâche et vérifier si ce plan va garantir son exécution. Si lexécution de cette tâche nest pas 26
  • 2 Ordonnancement Des Tâches garantie alors dautres alternatives seront envisagées (tel lenvoi de la nouvelle arrivée sur un autre nœud du système pour un système distribué) [Krithi94]. Pour les approches "Dynamic Best-Effort", les tâches vont être ordonnancées mais en aucun cas, leurs dates limites ne seront garanties [Krithi94]. Pour le génie automatique, les ordonnanceurs du type "tout planifiés" ne peuvent pasrépondre aux problèmes posés par lapparition à caractère aléatoire des événements issus dusystème contrôlé. En effet il est impossible de planifier, avant la mise en route du système,laffectation des tâches sur le ou les processeurs du système contrôlant car on ne connaît pas lesdates de demande dexécution. Les ordonnanceurs du type "dynamiques" ne peuvent passappliquer dans le domaine de lautomatique car les systèmes que nous étudions sont dessystèmes contraints et que dans le cas de ces ordonnanceurs on ne sait pas a priori si toutes lesdates limites pourront être garanties. Par contre les ordonnanceurs du type "à base de priorités"sont très prisés par les acteurs du Génie Automatique. Nous allons donc dans la suite de notreétude détailler ce type dordonnanceurs.V- Création dordonnancements plus complexes: Les algorithmes Rate Monotonic et Earliest Deadline sont complétés par dautresalgorithmes ou protocoles dans le but de pouvoir répondre à des spécifications du système pluscompliquées (la prise en compte de tâches apériodiques, des protocoles tels le partage desdonnées ..., le traitement des surcharges transitoires).V-1- Introduction des problèmes "dinversion de priorités" (dus aux partages de donnéespar exemple): Comme nous lavons déjà vu, un algorithme dordonnancement est préemptif lorsquaucours de lordonnancement il peut interrompre lexécution dune tâche et allouer le tempsprocesseur à une autre tâche. Par exemple lorsquune tâche de plus haute priorité arrive, le RateMonotonic ou le Earliest Deadline vont interrompre lexécution de la tâche qui est en cours pourexécuter la nouvelle arrivée. Une tâche peut être préemptée plusieurs fois sans aucune pénalité.Les algorithmes non préemptifs ne peuvent pas interrompre lexécution dune tâche de cette façon[Burns90] [Atanas94] [Sha93]. Dans les systèmes temps réel, les tâches interagissent pour satisfaire des spécifications pluslarges du système. Les formes que prennent ces interactions sont variées, allant de la simple 27
  • 2 Ordonnancement Des Tâchessynchronisation jusquà la protection par exclusion mutuelle sur les ressources non partageables,et les relations dantériorité. Pour cela, il existe des événements, des langages de programmationconcurrente fournissant des primitives de synchronisation (drapeaux, contrôleurs...). La difficultéprincipale avec ces drapeaux, contrôleurs ou autres messages de base des systèmes, est que destâches à haute priorité peuvent être bloquées par des tâches à priorité plus basse. Ce phénomèneest connu sous le nom dinversion de priorité. Quatre approches permettent de résoudre ceproblème : • une approche appelée "prévention dinversion de priorité"[Howell94], • une approche appelée "héritage des priorités" [Klein90] dont le "Ceiling Protocol" est un algorithme particulier [Klein90] [Di Natal]. Le travail de ce protocole lié avec un ordonnanceur Rate Monotonic a été étudié par Sha et al. [Rajkumar90], et le même protocole lié avec un ordonnanceur Earliest Deadline a été étudié par Chen et Lin [Chen90], • une approche appelée "Stark Ressource" [Di Natal]. L’adjonction de tels protocoles ne nous permet plus davoir une estimation delordonnançabilité des différentes tâches à ordonnancer.V-2- Traitement des tâches apériodiques ou sporadiques : les algorithmes "bandwithpreserving": Beaucoup de systèmes temps réel doivent traiter des tâches périodiques ainsi que destâches apériodiques. Quand on veut prendre en compte des événements apériodiques, il faututiliser une approche dynamique, telle le Earliest Deadline. Mais malgré cela, lexécution en casde surcharges transitoires pose des problèmes (Les dates limites qui ne sont pas respectées nesont pas forcément celles dont limportance pour le système est la moindre), ce cas est traité dansle paragraphe suivant. Le Rate Monotonic a été adapté pour pouvoir gérer des tâches apériodiques. Pour cela, unetâche périodique aura la fonction de servir une ou plusieurs tâches apériodiques. Différentsalgorithmes permettent de gérer cela : • le "Priority Exchange"[Sha87], • le "Deferrable Server" [Sha87], • le "Sporadic server" [Harbour91] [Sha87], • le "Slack Stealing" [Davis93]. 28
  • 2 Ordonnancement Des TâchesV-3- Traitements en cas de surcharges transitoires: (dus au fait que certaines tâches sont apériodiques). Le fait de devoir gérer des tâches apériodiques peut entraîner un phénomène de surchargestransitoires. Il peut se présenter des situations pour lesquelles il nest pas possible de respecter lesdates limites, le système est alors dit en exécution de surcharge transitoire. Malheureusement, une application directe du Rate Monotonic nest pas appropriée dans lecas de telles surcharges. Par exemple dans lapproche Rate Monotonic, une surcharge transitoireva amener la tâche dont la période est la plus longue à dépasser sa date limite. Cette tâche peutcependant être plus critique que les autres. La difficulté vient du fait que le concept de prioritépour le Rate Monotonic est une indication de la période qui peut ne pas être une indication delimportance de la tâche vis à vis du système. Ce problème peut être résolu en transformant lapériode dans le cas dune tâche importante [Burns90]. Le Earliest Deadline est un algorithme optimal lorsquil ny a pas de surcharge. Lephénomène typique qui se produit en cas de surcharge avec le Earliest Deadline est leffetdomino [Di Natal]. Pour contrôler les retards des tâches sous des conditions de surcharges, onassocie à chaque tâche une valeur reflétant limportance de chaque tâche dans le système. Alorsla gestion des tâches à partir de ces valeurs peut être réalisée par lalgorithme de Smith" [DiNatal]. Malheureusement, les contraintes dantériorité sur les tâches sont souvent générales. Uneheuristique a été proposée dans le projet SPRING, où les dates limites et les algorithmes de coûtont été combinés avec dautres algorithmes pour revoir dynamiquement ces valeurs et accorderles dates limites avec les contraintes dantériorité. Certains algorithmes heuristiques, proposéspour gérer les surcharges, améliorent lexécution du Earliest Deadline [Livny91][Thambidurai89]. 29
  • 4 JAVA Langage De L’Avenir Le langage JAVAI- Introduction: Java est un langage de programmation développé par Sun Micro-systems en 1990. Autout début, Java était destiné à la programmation de systèmes embarqués tels que ceux del’électroménagers et d’appareils électriques (vidéos, micro-ondes, lave-vaisselle, etc.). Cegenre de programmation était auparavant effectué en assembleur ou en C. Ces deux langagesétait coûteux car il fallait soit réécrire le code source lorsqu’un nouveau processeur sortait surle marché (assembleur) ou bien il fallait réécrire le compilateur (C ou C++). Java futdéveloppé pour être un langage universel, capable de s’adapter à n’importe quelle type demachine. Sun Micro-systems avait aussi comme but de faire un langage plus simple à utiliserque l’assembleur, le C ou le C++. Avec l’arrivée d’Internet, on s’est vite aperçu que Java était le langage idéal pour fairede la programmation sur le web car il est multi-plateforme. Mais que veut dire multi-plateforme? Cela signifie qu’une application écrite en Java peut être utilisée soit sur un PC,sur un Macintosh, sur une station Sun utilisant UNIX comme système d’exploitation, etc. Lesapplications développées en Java ne sont pas dépendantes du système d’exploitation. Commel’Internet relie tous les types d’ordinateurs imaginables, un seul choix s’imposait en se qui atrait à la programmation sur le web. Java semble le langage de l’avenir ! Mais un langage de programmation ne saurait être parfait. Pour pouvoir être multi-plateforme, un élément important a dû être sacrifié : la vitesse. Java n’est pas un langageexécuté, il est interprété. Mais quelle est la différence entre un langage exécuté et un autreinterprété? Les langages exécutés, comme le C ou le C++ par exemple, utilisent uncompilateur pour transformer le code source en langage machine. Le langage machine,composé de “1” et de “0”, est la seule et unique chose qu’un ordinateur peut comprendre. Leproblème est que chaque processeur possède sont propre langage machine, c’est-à-dire que lafaçon de disposer les “1” et les “0” est différente pour chacun d’entre eux. Heureusement, laplupart des processeurs ont à peu près le même type d’instruction, ce qui évite de faire uncompilateur pour chaque processeur. Imaginez un compilateur pour un Intel PII 233, un autrepour un Intel PII 266, etc. On ne s’y retrouverait plus ! À la place, les PC fonctionne sur lemême “langage machine”. Il en va de même pour les Macintosh et les stations Sun pour n’ennommer que quelques-uns. Pour compliquer les choses, les systèmes d’exploitation ont eux aussi leur façon defonctionner. Développés par différentes compagnies à des périodes différentes, les systèmes 30
  • 4 JAVA Langage De L’Avenird’exploitation n’ont pas eu la chance de bénéficier de la même technologie. On n’a qu’àpenser à DOS et à Windows 95. On ne peut pas faire des applications utilisant une interfacegraphique pour être utilisées sous DOS. Il ne faut donc pas seulement un compilateur pourchaque grande famille d’ordinateur, mais il faut en plus tenir compte des systèmesd’exploitation ! C’est là qu’intervient Java, un langage multi-plateforme. Java est aussi compilé. Ladifférence est que le compilateur Java ne crée pas de fichier exécutable (*.exe). À la place,c’est du p-code qui est généré sous forme de fichiers classe (*.class). Le p-code, aussi appelébytecode, c’est comme si le code source était à moitié compilé. Le p-code n’est pas encorelisible par tous les processeurs et par tous les systèmes d’exploitation. Il faut tout d’abord quele p-code soit interprété. Interprété veut tout simplement dire qu’on termine de compiler justeavant l’utilisation. Cette technique a pour avantage de rendre le code source multi-plateforme,mais ralenti de beaucoup les performances de l’application. Par exemple, une applicationdéveloppée en C++ va en moyenne 10 fois plus vite que si elle avait été écrite en Java. Doncsi vous attendez 2 secondes pour que l’application effectue une opération spécifique sousC++, vous allez en attendre 20 secondes sous Java. Java est donc un bon langage pour créerdes applications qui ne requiert pas une très grande vitesse d’exécution.II- Java : Un langage orienté objet: Java, comme tous les langages de programmation qui permettent la création d’interfacesgraphiques utilisateurs (Graphic User Interface ou GUI), n’est pas de type structuré mais biende type orienté objet. Mais quelle est la différence entre les deux? La programmationstructurée met l’accent sur les actions (les fonctions) tandis que la programmation orientéeobjet se base sur les objets. Par exemple, si vous regardez le langage C, vous remarquerezque, la plupart du temps, les noms de fonctions sont représentés par des verbes (Afficher,Lire, Additionner, ...etc.). Dans la programmation orientée objet, on va plutôt définir chaqueobjet avec toutes les actions et attributs qu’il possède. Par exemple, on pourrait définir unobjet “voiture” ayant les actions avancer, reculer, accélérer, démarrer et s’arrêter pour n’ennommer que quelques-uns. Les attributs de l’objet voiture pourrait être NbrePortes,VitesseMaximale, NbreCheveauxVapeur,...etc. Vous voyez que l’approche est complètementdifférente. Tous les langages de programmation orienté objet fonctionnent sur le même principedes objets. Lorsqu’on en connaît un, il devient très facile d’en apprendre d’autres. Java est 31
  • 4 JAVA Langage De L’Avenirtotalement orienté objet, comparé au C++ dans lequel il est facile de retomber dans laprogrammation structurée.Note En Java, comme dans tous les langages, il y a plusieurs façon de faire qui donne lemême résultat. Nous entendons par “façon de faire” que le code source est différent mais quel’exécution du programme est identique. Ce phénomène est d’autant plus vrai pour ce qui estde la programmation d’interfaces graphiques utilisateurs (GUI). En effet, on peut avoir deuxexécutions identiques mais avec des codes sources totalement différents. De plus, certainsfabricants de logiciels servant à écrire du code source en Java (comme Borland JBuilder etMicrosoft Visual J++) ont créés plusieurs nouvelles classes pouvant faciliter ou accélérer larédaction du code source.III- Programme simple: En Java, il est possible de faire deux types de programme: des applets et desapplications. Les applets sont destinées exclusivement aux pages web sur Internet tandis queles applications sont semblables à des programmes développés en C, à savoir toutes lesapplications autonomes, qu’elles soient développées avec une interface graphique ou non. Le langage Java étant un langage orienté objet, tout le code doit se retrouver à l’intérieurde classes. Nous pouvons en avoir plusieurs, mais il se peut que vous en aillez qu’une seule.Le nom de la classe doit absolument être identique au nom du fichier *.java contenant le codesource. Par exemple, le fichier App1.java doit obligatoirement contenir la classe App1. Cetteclasse est appelée la classe principale du programme. La classe principale doit avoir, dans le cas d’une application et non d’une applet, laméthode “main”. Cette méthode est appelée automatiquement lors du démarrage del’application. Lorsque la méthode “main” est terminée, l’application est aussi terminée. La seule différence est le mot “args” qui est une variable, donc qui peut s’écrirepresque n’importe comment. Analysons chacun des mots qui composent la méthodeprincipale : public : Signifie que la méthode est accessible à l’extérieur de la classe dans laquelle elle se trouve. Cela permet à l’interpréteur d’appeler la méthode “main”. static: Indique que la méthode “main” s’applique à toute la classe. void: Signifie que la méthode ne retourne rien. main: Nom de la méthode. Doit demeurer inchangé. String args[]: Tableau contenant des chaînes de caractères. Ce sont les commandes passées à l’application. 32
  • 4 JAVA Langage De L’Avenir Dans Java, nous n’avons pas à inclure le package de base à chaque fois que nous faisonsune application. En effet, le package “java.lang” est inclus automatiquement. Ce packagecontient toutes les classes de base d’une application. C’est entre autre le cas de la classe“System”, qui contient elle-même “in” et “out” (entrée et sortie). La partie “out” contient lesméthodes “print” et “println”, différentes seulement par le fait que la dernière ajoute unchangement de ligne après avoir afficher du texte. L’utilisation de ces deux méthodes est trèssimple : il s’agit de mettre du texte entre guillemets dans les parenthèses et ce texte seraaffiché à l’écran. Ces méthodes sont l’équivalent de la fonction “printf” en C.Classe Structure de données qui comprend des attributs et des méthodes. Une classe estcomparable à une structure en C, avec quelques modifications.Eléments importants à retenir : • Les attributs déclarés dans une classe sont “private” par défaut. • Il ne peut y avoir qu’une seule classe “public” dans un même fichier (*.java) et cette classe doit avoir le même nom que le fichier. Les classes commencent toujours par une lettre majuscule en Java.Méthodes Aussi appelées fonctions, fonctions membres ou procédures, elles jouent le même rôleque les fonctions en C à la différence près qu’elles sont toujours définies à l’intérieur d’uneclasse.Eléments importants à retenir : • Les méthodes sont toujours définies à l’intérieur d’une classe. • Les méthodes peuvent être public, protected ou private. • Les méthodes peuvent retourner des valeurs (int, double, …) ou non (void). • Le nom d’une méthode ne peut pas contenir de caractères spéciaux (espace, astérisque, etc.), exactement comme en C. • Voir la “Surcharge” et la “Redéfinition” pour plus de détails. • Les méthodes ont accès à tous les attributs de la classe sans avoir à les passer en paramètre ou à les déclarer à l’intérieur de celle-ci.Attributs Un attribut, aussi appelé donnée, ce n’est ni plus, ni moins qu’une variable déclarée àl’intérieur d’une classe. Certains auteurs les appelleront aussi variables membres de la classe. 33
  • 4 JAVA Langage De L’AvenirEléments importants à retenir : • Un attribut peut être déclaré public, protected ou private. Par défaut, l’attribut est private. • Une instance d’une classe peut être un attribut d’une autre classe. • Deux attributs ne peuvent pas avoir le même nom.Instances Dans la programmation orientée objet, les classes ne serviraient à rien si ce n’était pasdes instances. Une instance, c’est une variable qui a comme type une classe. Dans Java, toutesles instances sont déclarées à l’intérieur des classes. Elles deviennent donc des attributs. Pourfaire un parallèle avec le langage C, une instance pourrait être comparée avec une variable quia pour type une structure. Toutefois, à la différence d’une variable, il faut appeler un constructeur de la classepour ensuite pouvoir l’utiliser. Les constructeurs sont traités dans la section du même nom.Pour l’instant, il faut seulement se rappeler que le constructeur n’est autre qu’une méthodeayant le même nom que la classe et qu’il est appelé à l’aide du mot réservé “new”. Il y a aussi une deuxième façon de déclarer une instance, qui ressemble beaucoup à lapremière. Il s’agit de faire la déclaration sur une première ligne et ensuite appeler leconstructeur sur une seconde. Rectangle Largeur Hauteur ModifierLargeur ModifierHauteur Périmètre Aire AfficherPerimetre AfficherAire Affichage Ce symbole signifie que la classe du dessous hérite de la classe au-dessus. Donc PrismeRectangulaire PrismeRectangulaire hérite de Rectangle. Profondeur ModifierProfondeur Volume1 Volume2 AfficherVolume 34
  • 4 JAVA Langage De L’Avenir Véhicule à moteur Moteur Réservoir d’essence Volant Cadrans Siège Roues Accélérer Freiner Tourner Voiture Train Avion MotoPortes à pentures Portes coulissantes Fuselage Roues avec rayonsCarrosserie Carrosserie Ceintures TransmissionCeintures Transmission Ailes PneusTransmission Wagons Hublots ClignotantPneus App. de navigationClignotant Autonomie de volReculer Reculer Décoller Rouler sur une roue Atterrir Prendre de l’altitude Avion à réaction Hydravion Ultra-légers Pneus Flotteurs Pneus Cabine pressurisée Hélice Hélice Réacteurs Amerrir Voler à haute altitude Flotter Avion de combat Transporteur Bombes Télévisions Système de poursuite Petite cuisine Réacteurs Voler à l’envers Voler à haute altitude 35
  • 4 JAVA Langage De L’Avenir Avec une instance, on peut utiliser tout ce qui est déclaré “public” dans la définition dela classe. Lorsqu’on dit “tout ce qui est public”, on veut dire toutes les méthodes et tous lesattributs qui ne sont pas protected ou private.Nous expliquerons en détail les différences entre les trois types dans la section portant sur les3 principes de la programmation orientée objet. L’appel de ces attributs et de ces méthodesdéclarées “public” se fait par l’intermédiaire d’un point situé entre l’instance et l’attribut ou laméthode.Eléments importants à retenir : • Une instance déclarée à l’intérieur d’une classe devient un attribut de cette même classe. • À la différence de la déclaration de variables, la déclaration d’instances requiert l’appel d’un constructeur. • Avec une instance, on peut utiliser tout ce qui est déclaré “public” dans la définition de la classe.Héritage L’héritage est extrêmement important dans la programmation orientée objet. Il permetde faire une copie d’une classe et d’y faire des modifications. On appelle “classe mère” ou enanglais “super class” la classe sur laquelle la copie est faite. Vous vous en doutez sûrement, laclasse copie de la classe mère s’appelle “classe fille” ou “sub class” en anglais. L’héritage permet de passer tous les attributs et toutes les méthodes de la classe mère à laclasse fille, bien que la classe fille n’a pas accès aux attributs et méthodes private de la mère.Cela peut être difficile à comprendre, mais les attributs et méthodes private de la mère sontbel et bien passés à la classe fille mais celle-ci n’y a pas accès.Eléments importants à retenir : • Il est possible de faire plusieurs fois de l’héritage. Une classe fille peut, elle aussi, avoir une ou des classes filles. • Une classe mère peut avoir plusieurs classes filles. • Il existe une grande quantité de classes déjà toutes faites et prêtes pour l’utilisation. Ces classes, développées par Sun Micro-systems, vous sauverons beaucoup de temps et bien des maux de tête. 36
  • 4 JAVA Langage De L’AvenirIV- Les trois principes de la programmation orientée objet: Les trois principes de la programmation orientée objet, sont trois choses qu’on ne peutnormalement pas faire dans la programmation conventionnelle ou structurée. Il s’agit del’héritage, de l’encapsulation et du polymorphisme. IV.I- L’Héritage: Premièrement, lorsque l’on veut créer une interface graphique utilisateur (GUI), il estextrêmement économique aux points de vu temps et argent d’utiliser l’héritage pour ne pasavoir à réécrire du code qui existe déjà. Imaginez une seconde tout ce qu’il faut spécifier pourpouvoir créer une simple fenêtre. Ce serait énorme comme travail! Une application simple quiprend une heure à développer prendrait plusieurs mois s’il fallait tout refaire à chaque fois.C’est pour cette raison que la programmation de fenêtres et de GUI en général ne peut êtreaccomplie que par des langages de programmation orientée objet. De plus, l’héritage peut vous sauver d’écrire plusieurs fois la même chose dansplusieurs classes. En effet, si vous avez plusieurs attributs et plusieurs méthodes communs àvos classes, pourquoi ne pas faire une classe mère qui les contiendrait tous? Dans notre exemple, nous ne voulons pas réécrire tous les attributs et toutes lesméthodes dans chacune des classes ou encore moins faire du “copier-coller”. En déclarant leséléments des classes supérieures d’une façon public ou encore mieux, protected, on permetaux classes inférieures d’en bénéficier. Un autre avantage de l’héritage, c’est la correction des erreurs. Si vous regardezl’exemple précédent, vous remarquerez sûrement qu’il manque beaucoup d’attributs et deméthodes. Toutefois, il est très facile d’en ajouter un autre. Par exemple, si l’on veut rajouterun attribut à tous les véhicules, on a qu’à le déclarer public ou protected dans la classe“Véhicule à moteur” et le tour est joué. De cette façon, on pourrait ajouter l’attribut“Carburateur” à la classe “Véhicule à moteur” au lieu d’aller le placer dans chacune des 10classes. On sauve du temps et de l’argent. Mais la correction des erreurs ne s’arrête pas là. Il faut aussi être capable d’enlever oude modifier un attribut ou une méthode. Par exemple, on peut apercevoir, dans la classe“Véhicule à moteur”, un attribut “Roues”. Toutefois, si nous voulons ajouter la classe fille“Bateau” à la classe “Véhicule à moteur”, il y a un problème car les bateaux n’ont pas deroues. Il en va de même pour l’hydravion. Mais, on pourrait choisir tout simplement d’ignorerl’attribut “Roues” dans les classes “Bateau” et “Hydravion” (faire comme s’il n’existait pas).On pourrait penser que cette pratique est de la mauvaise programmation, mais elle est parfoisnécessaire car il serait trop long de l’écrire dans toutes les classes. De plus, lorsqu’on fait du 37
  • 4 JAVA Langage De L’AvenirGUI, on hérite de classes déjà faites et on utilise normalement entre 5% et 10% des attributs etméthodes héritées.IV-2- Encapsulation: Après avoir vu la différence entre les types public, protected et private, une questionnous brûle les lèvres : Pourquoi ne pas seulement déclarer des attributs et des méthodes detype public? Il serait beaucoup plus facile de ne pas utiliser les types private et protected. Laraison à cela est l’encapsulation des données. L’encapsulation des données est surtout utile lorsqu’on travaille en équipe oulorsqu’on fait un gros projet. Elle évite qu’un attribut ne prenne une mauvaise valeur pouvantfaire mal fonctionner le programme pendant l’exécution de celui-ci.IV-3- Le polymorphisme: Le troisième et dernier principe de la programmation orientée objet est peut-être leplus difficile à appliquer. Il peut sembler simple au début mais il prend beaucoup de pratiqueà assimiler. Le polymorphisme vient des mots “poly” qui veut dire plusieurs et “morphe” quisignifie forme. Dans la programmation orientée objet, on peut transformer les méthodes pourqu’elles aient “plusieurs formes”. Mais avant de continuer, il devient impératif de décrire lepolymorphisme sous ses deux formes : La surcharge et la redéfinition.Surcharge: La surcharge, c’est lorsqu’on a deux ou plusieurs méthodes dans la même classe, quiont exactement le même nom mais leurs paramètres respectifs diffèrent en type et/ou ennombre. Le terme anglais pour la surcharge est “overloading”. On utilise surtout la surcharge lorsqu’on veut qu’une même méthode fasse plusieurschoses différentes mais similaires, dépendament des paramètres qu’on y passe. Cettetechnique s’avère particulièrement intéressante avec les constructeurs que nous allons voir unpeu plus loin.Redéfinition: La redéfinition, c’est lorsqu’on a deux méthodes, l’une dans la classe mère et l’autredans la classe fille, qui ont la même signature (même noms, même paramètres) mais que leurcontenu est différent. Le terme anglais pour redéfinition est “overriding”. On utilise généralement la redéfinition quand la classe fille hérite des méthodes de laclasse mère mais qu’une de ces méthodes ne lui convient pas. 38
  • 4 JAVA Langage De L’AvenirV- Constructeur: Un constructeur est un type particulier de méthode. La particularité de cette méthodeest qu’elle est appelée automatiquement à la création d’une instance de la classe. Il y aplusieurs types de constructeurs, il y a le constructeur par défaut, le constructeur d’instance etle constructeur de copie (pour ne nommer que ceux-là). Lorsqu’il vient le temps d’écrire unconstructeur, il faut se souvenir des quatre choses suivantes : 1. Le nom du constructeur doit être exactement le même que celui de la classe. 2. Le constructeur ne possède pas de type (void, int, ..etc.). 3. Le constructeur est toujours public. 4. Le constructeur ne retourne jamais rien (return).Les constructeurs servent à initialiser les instances lors de leur déclaration. En effet, au lieud’avoir à chaque fois à donner des valeurs similaires à toutes les instances qu’on déclare, leconstructeur se charge de le faire à notre place. Le constructeur est appelé à l’aide del’opérateur “new”.De plus, il est fréquent de voir un constructeur surchargé. Il est alors possible de créer denouvelles instances avec différents constructeurs.V-1- Constructeur par défaut : C’est le constructeur qui va être appelé si l’on ne passe pas de paramètres à l’intérieurdes parenthèses. Il faut bien sûr qu’il n’y ait aucun argument de passé en paramètre aumoment de la définition du constructeur. Il ne peut pas y avoir plus d’un constructeur pardéfaut.V-2 Constructeur d’instances : C’est le nom donné aux constructeurs ayant un ou plusieurs arguments passés enparamètre. Ils permettent de créer une instance avec une légère différence par rapport auconstructeur par défaut. Il peut y avoir plusieurs constructeurs d’instances.V-3- Constructeur de copie : Un constructeur de copie, c’est un constructeur d’instance où il n’y a qu’un seulargument passé en paramètre. Cet argument doit être une instance de la classe dans laquelle leconstructeur est défini. 39
  • 4 JAVA Langage De L’Avenir public Cheque(Cheque Copie) Instance de la classe “Cheque”, classe dans laquelle le constructeur est défini. Les constructeurs de copie, comme leur nom le laisse savoir, servant à faire une copied’une instance qui existe déjà. Cette copie n’a pas à être parfaite. Il peut y avoir certainesmodifications. Il peut être utile de rappeler qu’une méthode a accès à toutes les méthodes etles attributs de la classe, même s’il s’agit d’une instance de celle-ci. Par exemple, nous avonsdéjà mentionné que les attributs déclarés “private” ne pouvait être utilisés à l’aide d’uneinstance, mais nous pouvons tout de même le faire à l’intérieur du constructeur de copie. Laraison pour laquelle c’est possible, c’est parce que le constructeur de copie est déclaré àl’intérieur de la même classe que l’instance. Il en va de même pour toutes les méthodes.Eléments importants à retenir : • Un constructeur doit avoir le même nom que la classe. • Il y a trois types de constructeur : par défaut, d’instances et de copie. • Un constructeur ne retourne jamais rien (return). • Un constructeur n’a pas de type. • Un constructeur doit être public. • Les constructeurs sont appelés à l’aide de l’opérateur “new”VI- Destructeur: Les destructeurs sont des méthodes appelées automatiquement à la destruction d’uneinstance de la classe. Dans Java, il n’y a pas de destructeur. La raison pour cela est que Javapossède un système de ramassage de déchets (garbage collection subsystem) qui se charge delibérer la mémoire. Un tel système n’existe pas en C++, d’où l’utilité du destructeur. Cependant, il existe une méthode, la méthode finalize(), qui est appelée lorsqu’uneinstance est détruite.VII- Les exceptions: Le traitement des exceptions est très important dans Java. Mais avant de commencer àexpliquer comment utiliser les exceptions, il faut d’abord définir ce que c’est. Une exception,c’est un problème qui se produit lors de l’exécution d’une application. Par exemple, unedivision par zéro soulève une exception, ou encore, l’utilisation de l’indice 10 d’un tableau de 40
  • 4 JAVA Langage De L’Avenir10 éléments (de 0 à 9). En bref, le traitement des exceptions permet de réagir d’une façonspécifique lorsqu’un problème survient.VII-1- Le traitement des exceptions : Dans Java, comme dans tous les langages, il est presque impossible de prévoir toutes leserreurs. Toutefois, il est possible de réagir d’une façon spécifique lorsqu’une erreur seproduit. On pourrait, par exemple, vouloir afficher un message d’erreur convivial et ensuitefermer l’application au lieu de tout faire planter.VII-2- Gérer les exceptions une à une: Maintenant, il peut être très utile de réagir différemment, en fonction du type d’erreurrencontré. Par exemple, le message envoyé à l’usager ne sera pas le même pour une divisionpar zéro que pour un index hors limite dans un tableau. La convivialité de votre applicationdépend de la façon que vous traitez les exceptions.VII-3- Le try avec plusieurs catch La meilleure façon de gérer les exceptions est bien souvent d’utiliser un try-catch,avec plusieurs catch. En utilisant cette technique, vous serez en mesure de capter toutes lesexceptions possibles ayant un point en commun. Par exemple, toutes les erreurs arithmétiques,que ce soit une division par zéro ou une extraction de la racine carrée d’un nombre négatif,seront captées par le même catch. Pour être en mesure d’utiliser la technique du try-catch de façon efficace, il faut bienconnaître les types d’exceptions. Les tableaux suivants vous aideront à mieux gérer lesexceptions.Les exceptions suivantes ne sont pas vérifiées par le compilateur:Exceptions SignificationArithmeticException Erreurs arithmétiques, comme la division par zéro.ArrayIndexOutOfBoundsException L’index d’un tableau est hors limites.ArrayStoreException Assigner un élément d’un tableau à un type incompatible.ClassCastException Appel invalide.IllegalArgumentException Argument illégal utilisé pour invoquer une méthode.IllegalMonitorStateException Opération illégale d’un moniteur, comme 41
  • 4 JAVA Langage De L’Avenir attendre après un “Thread unlocked”.IllegalThreadStateException L’opération demandée n’est pas compatible avec l’état du Thread.IndexOutOfBoundsException Certains types d’index sont hors limites.NegativeArraySizeException Tableau créé avec une grandeur négative.NullPointerException Utilisation invalide de la référence null.NumberFormatException Conversion invalide d’une String vers un format numérique.SecurityException Violation de la sécurité. Les exceptions qui suivent sont vérifiées par le compilateur:Exceptions SignificationClassNotFoundException La classe est introuvable.CloneNotSupportedException Tentative de cloner un objet qui n’implémente pas l’interface Cloneable.IllegalAccessException Accès à une classe est refusé.InstantiationException Tentative de créer un objet d’une classe abstraite ou d’une interface.InterruptedException Un Thread a été interrompu par un autre Thread. Méthodes définies par Throwable:Méthodes DescriptionThrowable fillInStackTrace() Retourne un objet Throwable qui contient la trace de la pile. Cet objet peut être redirigé.String getMessage() Retourne la description d’une exception.void printStackTrace() Affiche la trace de la pile.void printStackTrace(PrintStream stream) Envoie la trace de la pile vers la stream spécifiée.String toString() Retourne un objet String contenant la description de l’exception. 42
  • 5 Modélisation Des DépendancesModèles de dépendances des programmesI-Introduction: Les programmes sont représentés par un graphe orienté où les nœuds sont les entités duprogramme et les arcs représentent les types des dépendances existantes entre ces dernières.II- Notion de dépendance: Une relation de dépendance entre deux instructions d’un programme impliquel’existence de contraintes entre leur ordre d’exécution. En compilation, on fait appel à ceconcept afin d’étudier la possibilité de reformuler l’écriture du programme (ou une de sesparties), c’est à dire, changer la structure interne de ce programme sans altérer sa sémantique.C’est un concept fondamental dans l’analyse du comportement du programme etl’optimisation de son code (modification, alternance, suppression d’instructions, … ). La notion de dépendance définit un ordre d’exécution (total ou partiel) entre lesinstructions. La relation de dépendance a été utilisée pour le parallélisme dans les programmesséquentiels, la compréhension de programme et l’intégration de versions. La relation d’ordre définie ainsi peut être explicitée par un organigramme ou un graphereprésentants ainsi et respectivement la séquence d’opérations à exécuter et la relation dedépendance (positive ou négative), générant éventuellement un graphe partitionné, où chaquepartie est un organigramme d’exécution d’un ensemble d’instructions. On doit signaler que la contrainte d’ordre n’est pas seulement la seule relation qui peutexister entre les relations, mais de plus, il y a un transfert d’information entre les instructions,et ce qu’on appelle un flux de données, qui matérialise la dépendance de données entre lesinstructions, et encore l’existence d’instructions qui confirment ou infirment l’exécution ded’autres instructions, matérialisant par conséquent le concept de la dépendance de contrôle.III- Types de dépendances: Le parallélisme au sein d’un programme est limité par ses dépendances. Unedépendance entre deux instructions d’un programme provoque un conflit dans leur exécutionconcurrente. On peut avoir trois types de dépendances: ressource, donnée et contrôle. Une dépendance de ressource, entre deux instructions, est une conséquence de la limitedu matériel disponible dans n’importe quel système informatique physique. Ce type dedépendance se produit lorsque deux instructions différentes tentent simultanément d’utiliser lamême ressource physique, tel les que deux opérations de multiplication entrant en compétitionpour réquisitionner (occuper) un seul multiplicateur ou deux opérations de référence mémoirevoulant accéder à une même cellule (port) mémoire. Une dépendance de données existe dans le cas où deux instructions ne peuvent pas êtreexécutées simultanément à cause d’un partage de données, c’est à dire que ces deuxinstructions référencient la même location mémoire ou accèdent au même registre (bloc)physique. Il y a quatre formes de dépendances de données : dépendance de flux, anti-dépendance, dépendance de sortie et dépendance d’itération. Dans le cas où on a une dépendance de flux d’une instruction S1 à une instruction S2(voir le fragment de programme ci-dessous), on constate que S2 a besoin de la valeur de Aproduite par S1avant qu’elle ne commence son exécution. S1: A = B + C S2: D = A – E De ce fait, on dit que «S2 dépend par flux de S1» vu que S1 doit être exécutée avant S2,car elle assigne une valeur à une variable A qui est utilisée par S2. 43 43
  • 5 Modélisation Des Dépendances Deux instructions écrivant dans la même location (cellule) de stockage provoquent unedépendance de sortie. Autrement dit, une dépendance de sortie implique que deux instructionsassignent des valeurs à une même variable, et entre ces deux instructions, il n’y a aucuneutilisation de cette variable. Dans ce cas, la suppression de la première instruction n’altère pasle résultat final. Soit le fragment de programme suivant : S1: X = Y + Z S2: C = X * 22 S3: X = A – B L’instruction S1 doit s’exécuter avant S3 vu que l’instruction intervenante S2 utilise lerésultat produit par S1, donc il y a une dépendance de flux de S1 à S2. Dans cet exemple, une anti-dépendance se produit entre S2 et S3 vu que S2 lit la valeurde X qui sera écrasée par S3. Par conséquent, S2 doit s’exécuter avant S3. Autrement, S3assigne une valeur à une variable qui a été utilisée par S2. Les dépendances de flux sont les dépendances les plus fréquentes, dans lesquelles unrésultat produit par une instruction, est utilisé par une autre. Les anti-dépendances et les dépendances de sortie se produisent quand le programmeurou le compilateur réutilisent les cellules de stockage afin de réduire les besoins en mémoire duprogramme. On peut noter que la renominalisation de variables peut être utilisée pour éliminer cesdeux types de dépendances. Par exemple, au lieu de réutiliser un seul tableau pour deuxcalculs indépendants dans de différents endroits du programme, le programmeur aurait puallouer deux tableaux différents (séparés). Le tableau qu’on a rajouté va éliminer ladépendance de sortie et les anti-dépendances pour le premier tableau. Cela permetd’augmenter le degrés du parallélisme, mais ça vient à l’encontre du surcoût en espacemémoire pour le tableau additionnel. En examinant les instructions de boucles (While, Repeat, …), chacune de sesinstructions peut être exécutées plusieurs fois, ce qui peut engendrer des relations dedépendances entre les différentes itérations et c’est ce qu’on appelle les dépendancesd’itération. Soit le fragment de programme suivant : S1: Do I = 2,n S2: a[I] = a[I] + c S3: b[I] = a[I - 1] * b[I] EndDo Dans cet exemple, il n’y a pas de dépendance entre les instructions S2 et S3 au sein dechaque itération, mais il y a une dépendance d’itération entre les instructions S3 et S2 quiappartiennent respectivement à deux itérations successives. En effet, quand I = k, l’instruction S3 utilise la valeur de a[k-1] assignée par S2 durantl’itération k – 1. De ce fait, on dit qu’il y a une dépendance d’itération si une variable estmodifiée par une itération et utilisée par une autre. Intuitivement, une dépendance de contrôle d’une instruction Si à une instruction Sjexiste quand l’instruction Sj doit être exécutée seulement si l’instruction Si génère unecertaine valeur. Ce type de dépendance se produit, par exemple, quand Si est une instructionconditionnelle et Sj ne sera exécutée que si la condition est satisfaite. Les dépendances de contrôle peuvent limiter le parallélisme en s’attardant dans uneboucle. Ferrant & al définissent formellement les dépendances de contrôle telles que: «lesdépendances de contrôle sont un concept clé dans l’optimisation des programmes et leparallélisme. Une instruction w reçoit une dépendance de contrôle d’une instruction u si u estune condition qui affecte l’exécution de w». 44 44
  • 5 Modélisation Des Dépendances Programme Extraction des dépendances Dépendances multiprocédurales Dépendances de ressources Dépendances d’appel Dépendances de contrôle Dépendances résumées Dépendances de données Dépendances de sortie Dépendances d’itération Dépendances de flux Anti – dépendances Caractéristiques générales. Caractéristiques des programmes multiprocéduraux. Fig. III-1: Schématisation des types de dépendances existantes au sein d’un programme Les tests symboliques de la dépendance de données peuvent déterminer s’il existe desdépendances ou non entre des instructions d’un programme qui accèdent à un tableau(variables indicées) avec des indices complexes. Par exemple, considérons la boucle suivante: Do I = L,H M[a * I + b] = X[I] + Y[I] Z[I] = 2 * M[c * I + d] EndDo Les itérations de cette boucle peuvent être exécutées en parallèle en utilisant unestratégie d’ordonnancement, s’il n’y a pas des dépendances d’itération croisées dû auxréférences dans le tableau M[]. Pour déterminer si une telle dépendance existe, l’analyseursymbolique de la dépendance de données doit résoudre l’équation de «Diophantine»aI1+b=cI2+d. Cette équation est sous la contrainte que: L <= I1 <= I2 <= H, où I1 et I2 sontdeux valeurs spécifiques de l’indice de la boucle, L et H sont les bornes inférieure et 45 45
  • 5 Modélisation Des Dépendancessupérieure sur l’indice de la boucle et a, b, c, et d sont des entiers. S’il n’existe aucunesolution alors il n’y a pas de dépendance entre les deux instructions dans cette boucle. Des techniques pour résoudre ces équations ont été étendues pour analyser autresindices et qui sont plus complexes. Dans le cas où le programme contient des appels de procédures (programmemultiprocédural), on peut trouver deux autres formes de dépendances: dépendances d’appel etdépendances résumées. La première modélise l’instruction d’appel et le passage deparamètres. La seconde représente l’influence d’exécution des paramètres effectifs d’entée surles paramètres effectifs de sortie, en faisant abstraction de la procédure.VI- Représentation des dépendances:Définition: Un programme est dit monolitique s’il ne contient pas de procédures, sinon il est ditmultiprocédural.Pour un programme monolitique, les dépendances sont représentées par ungraphe orienté appelé Graphe de Dépendance de Programme (GDP). Les nœuds de ce graphesont les éléments de base du programme qui sont en général les instructions. Ces nœuds sontliés par des arcs représentant les dépendances extraites de ce programme. Un élément de basepeut être une instruction d’affectation, d’écriture, d’alternance ou d’itération. A chacun de ceséléments, on fait correspondre un nœud particulier. La racine du GDP est un nœud particulierappelé Entrée (ou Entry en anglais ) représentant l’entête du programme. Les arcsreprésentent les dépendances de données et de contrôle. L’extrémité initiale d’un arc dedépendance de contrôle est obligatoirement le nœud Entrée ou un nœud de contrôle. Les arcsissus du nœud Entrée sont toujours libellés à vrai, sachant que chaque arc est libellé soit parvrai ou faux. Pour un programme multiprocédural, les dépendances sont représentées par unGraphe de Dépendances de Système (GDS). Il est composé d’un ensemble de GDP reliésentre eux par des arcs. Chacun des GDP d’un GDS représente les dépendances entre lesinstructions d’une procédure donnée. Les arcs de connexion modélisent les dépendancesd’appel et les dépendances résumées. Une dépendance d’appel est représentée soit par un arc reliant un nœud d’appel à unnœud d’entrée (le nom de la procédure), soit par des arcs reliant des nœuds effectifs à desnœuds formels. Il y a un nœud effectif d’entée (de sortie) pour chaque paramètre formeld’entrée (de sortie). Les variables globales sont, en général, traitées comme étant desparamètres effectifs supplémentaires. Les dépendances résumées sont représentées par desarcs reliant les nœuds effectifs d’entrée à ceux de sortie. Dans une approche proposée par Jackson et Rollins[Jackson 94], on représente, au seinde chaque GDP, les actions sur les variables par un nœud et les dépendances entre variablespar les arcs. Les instructions d’appel sont modélisées par des arcs résumées. Notez qu’un arc de dépendance de données d’un nœud v à un nœud u signifie que lecomportement du système peut changer si l’ordre relatif des composants représentés par v et uest inversé. Cependant, un arc de dépendance de contrôle d’un nœud v à un nœud u signifieque durant l’exécution, en cas où le prédicat représenté par v est évalué et sa valeur relie lelibellé de l’arc à u, donc la composante du programme représentée par u sera éventuellementexécutée et fournira au système une terminaison normale. Une autre vision de nos arcs de dépendances de données partage ces derniers en deuxtypes : les arcs de dépendances de flux et les arcs de dépendances def-ordre. Un arc de dépendance de flux relie un nœud v, qui représente une affectation d’unevariable x, au nœud u représentant l’ensemble des utilisations possibles de cetteaffectation. Un arc def-ordre relie deux nœuds v et u qui représentent des affectations de la variablex et où ces deux affectations atteignent une utilisation commune et v précède lexicalement u. 46 46
  • 5 Modélisation Des Dépendances Dans un GDS, les arcs résumés représentent une dépendance transitive dûe aux effetsdes appels de procédures. Une instruction d’appel est représentée en utilisant un nœud d’appelet quatre types de nœuds paramètres qui représentent le passage des paramètres. Du point de vue appel, le passage de paramètres est représenté par les nœuds «Actual-in» et «Actual-out», ou tout court «A-in» et «A-out» respectivement, et qui sont un contrôledépendant du nœud d’appel. Dans la procédure appelée, le passage des paramètres est représenté par les nœuds«Formal-in» et «Formal-out», ou tout court «F-in» et «F-out» respectivement, et qui sont uncontrôle qui dépend du nœud Entrée de la procédure. Les nœuds «A-in» et «F-in» inclus pour tout paramètre et variable globale et quipeuvent être utilisés ou modifiés comme un résultat de l’appel. Les nœuds «F-out» et «A-out» sont inclus pour tout paramètre et variable globale quipeuvent être modifiés comme un résultat de l’appel. La difficulté majeure dans la troncature inter-procédurale est la prise en charge correctedu contexte d’appel de la procédure appelée. Pour résoudre le problème du contexte d’appel, le GDS inclut les arcs résumés. Un arcrésumé relie un nœud v «A-in» à un nœud u «A-out» s’il y a une liaison dans le GDS de v à uet qui respecte le contexte d’appel en liant des retours aux appels. Trois types d’arcs inter-procéduraux sont nécessaires: 1. Un arc d’appel reliant chaque nœud d’appel au nœud Entrée de la procédure correspondante. 2. L’arc «Parameter-in» reliant chaque nœud «A-in» dans un endroit d’appel au nœud «F-in» correspondant dans la procédure appelée. 3. L’arc «Parameter-out» reliant chaque nœud «F-out» au nœud «A-out» correspondant dans chaque position d’appel dans le programme. Les variables globales sont généralement traitées comme des paramètres courants supplémentaires.NB. Notre définition du GDS modélise un langage ayant les propriétés suivantes: Un système complet consiste en une seule procédure principale (main) et une collection de procédures auxiliaires. Les paramètres sont passés par valeur. On n’admet pas des appels de la forme P(x,x) ou bien P(g) où g est une variable globale, afin d’éviter les problèmes de conflits de copie-arrière et pour considérer les variables globales comme des paramètres additionnels pour chaque procédure.V- Exemple d’extraction des dépendances d’un programme: Soit le programme suivant: Procedure Main; Procedure A(x,y) Procedure Add(a,b) Procedure Increment(z) Sum:=0; Call Add(x,y); a:= a + b; Call Add(z,1); I:=1; Call Increment(y); return; return; While i < 11 do return; Call A(Sum,I); Od Output(Sum); End. 47 47
  • 5 Modélisation Des Dépendances En voici le GDS correspondant : Entrée main Sum:=0 I:=1 While i < 11 Output (Sum) Call A xin:=Sum yin:=i Sum:=xout I:=yout Entrée A x:=xin y:=yin Call Add Call Inc xout :=x yout:=y ain:=x bin:=y x:=aout zin:=y y:=zout Entrée Inc z:=zin Entrée Add Call Add zout:=z aout :=aa:=ain b:=bin a:=a+b ain:=z bin:=1 z:=aout Clé des arcs: Contrôle Appel Résumé 48 48
  • 49C 3 Concepts De l’Orienté ObjetConcepts de l’approche objet:I-Introduction: L’approche objet est une méthodologie de programmation permettant la maîtrise de lacomplexité des systèmes, ainsi que la possibilité et la souplesse dans la réutilisation descomposants d’un logiciel. C’est un moyen efficace dans la structuration de programme,permettant ainsi la mise au point d’applications facilement testées, efficacement améliorées,souplement réutilisées et simplement maintenues. Elle est mise en œuvre afin de résoudre le problème de la séparation entre les structuresde données manipulées et les procédures définies là-dessus. En définitive, l’approche objet est caractérisée par : La structuration de l’univers manipulé en terme d’entités. La modélisation du raisonnement humain. La conception et la maintenance de logiciels immenses.II- Notions et concepts de base:II-1-Objet: L’objet représente l’entité de base dans la programmation orientée objet, regroupantdeux partie qui sont les données (partie statique de l’objet) et les procédures (appeléesméthodes, représentant la partie dynamique de l’objet ). La communication avec l’objet se fait à travers une interface, masquant ainsi les détailsde son implémentation et organisation interne. Un objet étant caractérisé par son comportement et non pas par sa structure, assurantainsi l’abstraction de données.II-2- Classe: Une classe est la concrétisation d’une famille d’objets ayant même structure etcomportement. Elle regroupe un ensemble de données et procédures (et/ou fonctions). Chaque classe possède une paire de composantes : Une première statique, les données, qui sont des champs nommés ayant une valeur représentant l’état des objets pendant l’exécution du programme. Une deuxième dynamique, les procédures, appelés aussi méthodes, représentant le comportement commun des objets d’une même classe. Elle définit l’ensemble des manipulations possibles à produire sur les données. 49
  • 50C 3 Concepts De l’Orienté Objet Une classe permet de définir des instances d’objets qu’elle contient.II-3- Instanciation: L’instanciation consiste à définir un objet particulier en se référant à une classe donnée.L’objet ainsi définit reçoit l’architecture que fournit la classe dont il est issu (champs dedonnées et méthodes). De ce fait, l’instanciation et un moulage permettant la productiond’objets, avec autant d’exemplaires que nécessaires.II-4- Envoi de message: L’envoi de message est le seul moyen permettant la communication entre les objets. Tout message doit comporter : Le nom de l’objet destinataire. Le nom de la méthode à activer (Sélecteur). Les arguments des méthodes à appliquer. Une fois le message est reçu, l’objet destinataire exécute la méthode désignée dans lemessage, avec un éventuel traitement des erreurs qui peuvent survenir soit au niveautransmission, ou bien concernant le passage des paramètres.II-5- Héritage: Une propriété principale de l’approche objet est la possibilité d’étendre les propriétésd’une classe et de construire des classes plus spécifiques à partir d’une ou de plusieurs autresqui existent déjà. L’héritage est une technique permettant la définition d’un nouveau type d’objet à partird’un type existant, auquel on adjoint de nouveaux champs de données et/ou de nouvellesméthodes. La conception d’un nouveau type d’objet (qui hérite ainsi des propriétés et desaptitudes de l’ancien type ), peut alors s’appuyer sur des réalisations antérieurs que l’onspécialise à son gré, c’est à dire qu’on définit des classes plus spécifiques à partir d’autres quisont générales qu’on appelle classes mères(ou classes parentes), en complétant lesconnaissances de ces dernières. Les connaissances les plus générales sont ainsi mises en commun dans des classes, quisont ensuite spécialisées par définition de sous-classes successives, de façon à aboutir à unehiérarchie de classes liées par la relation d’héritage appelée graphe d’héritage, dans lequelchaque sous-classe hérite des données et des méthodes de ses classes mères. 50
  • 51C 3 Concepts De l’Orienté Objet La génération de classes spécifiques peut se faire de deux manières: L’enrichissement: qui consiste à doter la sous-classe avec de nouvelles variables et/ou nouvelles méthodes représentant les caractéristiques propres au sous-ensemble d’objets ainsi décrits. La substitution: qui consiste à redéfinir une ou plusieurs méthodes héritées. L’héritage peut être: Simple: une classe ne peut hériter que d’une seule autre classe. Par conséquent, la relation d’héritage est représentée par une arborescence. Multiple: une classe peut hériter de plusieurs classes. Elle comprend alors l’union des variables et des méthodes de toutes ses classes mères. La relation d’héritage se bascule ainsi en un graphe orienté sans circuit. Cette alternative permet la décomposition des systèmes et de les représenter avec unminimum de symboles des structures complexes. Cependant, l’héritage multiple pose de nombreux problèmes difficiles à résoudre,surtout lorsqu’il s’agit de l’héritage de propriétés homonymes. Bien entendu, l’héritage facilite grandement la réutilisation de produits existants.D’autre part, l’héritage s’avère très utile pour la structuration et le développement de logiciels,car il s’agit d’une méthode efficace de partage de connaissances où il n’est plus nécessaire dedupliquer le code pour une éventuelle réutilisation future, ce qui rend aisé la lisibilité et lacompréhensibilité des programmes.II-6-Polymorphisme: Le polymorphisme définit la capacité, pour une entité, de prendre plusieurs formes, etpar conséquent, elle prend des valeurs de différents types durant l’exécution du programme oùelle est définie. Ça revient à dire qu’un même identificateur peut désigner, en l’utilisant à plusieursreprises, une variable, une classe ou une méthode.III- Caractéristiques principales de l’approche objet: La programmation orientée objet est basée sur les concepts suivants :III-1- Abstraction des données: 51
  • 52C 3 Concepts De l’Orienté Objet Il n’est plus nécessaire de connaître l’implantation physique et la représentation interned’un objet pour qu’on puisse communiquer avec ce dernier, en lui adressant un message.C’est à l’objet de décider avec quel procédé il exécute l’opération demandée en fonction deson implémentation physique. Bien évidemment, l’accès à un objet se fait à travers une interface qui cache sonorganisation interne assurant ainsi l’abstraction des données (manipulation loin del’organisation).III-2- Encapsulation: Le principe d’encapsulation consiste en l’abstraction de la définition des objets en vuede leurs modifications. Un objet étant un ensemble de données et de procédures qui les manipulent, qui sontregroupées dans une seule entité. L’interface définie sur cet objet nous permet d’accéder à ses données mais en n’ayantaucune information concernant son implémentation physique. De ce fait, l’encapsulation facilite la production de programmes robustes, résistants auxchangements des représentations des objets, et elle représente un moyen de protection et demaîtrise de la complexité des systèmes par leur décomposition en composants élémentaires.III-3- Modularité: L’héritage permet le partage du code entre différentes classes, sans avoir à le dupliquer,assurant ainsi une modularité par différenciation permettant la description d’un nouvel objet,en exprimant ce que le différencie de celui qu’il spécialise, ce qui assure un minimumd’interaction avec les autres objets.III-4- Réutilisation: Une propriété importante de l’approche objet permet l’introduction d’objets ou classesdans une bibliothèque offrant à tout programmeur la possibilité de les utiliser afin de définirdes objets de même type, ou de construire des objets plus spécifiques par spécialisation oucomposition des objets existants, ou faire appel à l’héritage pour la fabrication de classesspécifiques à partir de celles déjà fournies. 52
  • 6 Les Dépendances Orientées ObjetsReprésentation des programmes orientés objets (les dépendances orientées objets):I-Introduction: Les caractéristiques orientées objets, telles que les classes et les objets, l’héritage, lepolymorphisme, la liaison dynamique et les portées, interviennent dans le développementd’une représentation efficace d’un programme orienté objet. Une classe définit les attributs qu’une de ses instances va posséder. Les attributs d’uneclasse se composent de: 1. Instance de variables qui implémentent l’état de l’objet. 2. Méthodes qui implémentent les opérations sur l’état de l’objet. On a souvent conçu, implémenté et testé les classes sans connaître les environnementsd’appel. Par conséquent, une représentation graphique efficace, pour les logiciels orientésobjets, doit se composer d’une représentation des classes qui peuvent être réutilisées dans laconstruction de d’autres classes et applications utilisant ces dernières. Les classes dérivées sont définies à travers l’héritage, qui permet à la classe dérivéed’hériter des attributs à partir de leurs classes parentes, et étendre, restreindre, redéfinir ou deles remplacer en quelque sorte. Le fait que l’héritage facilite la réutilisation de code, une représentation graphiqueefficace d’une classe dérivée doit permettre la réutilisation des informations d’analyse. Laconstruction de la représentation d’une classe dérivée doit réutiliser les informations d’analysecalculées pour les classe de base, et ne détermine que les informations qui sont définies dansla classe dérivée. Le polymorphisme est une caractéristique importante des langages orientés objets, quipermet à l’exécution (runtime) de choisir l’un des appels aux méthodes faisant partie del’ensemble des destinations possibles. Une représentation statique d’un choix dynamique exige que toutes les destinationspossibles soient incluses, à moins que le type peut être déterminé statiquement. Une représentation doit prendre en considération les dépendances des instances devariables entre les appels aux méthodes de l’objet par un programme d’appel, même si cesinstances ne sont pas visibles à ce programme.II- Applications orientées objets et leurs modèles de représentations: Afin de pouvoir modéliser les caractéristiques orientées objets, on doit développer desGDS pour les applications orientées objets, sur lesquels un algorithme de troncature inter-procédurale [14,23] peut être appliqué. On construit ces GDS pour des classes uniques,groupes de classes interactives et des programmes orientés objets complets. Pour chaque classe C dans le système, on construit un GDC (Graphe de Dépendancesde la Classe), qu’on réutilise dans la construction des classes qui dérivent de C et celles quil’instancient. Pour un Système Incomplet (SI) se composant d’une seule classe ou un nombre declasses interactives, on construit un Graphe de Dépendance de Procédure (GDP), qui simuletous les appels possibles aux méthodes publiques dans la classe. Pour un Système orienté objet Complet (SC), on construit un GDP à partir duprogramme principal dans le système. L’approche adoptée dans la représentation s’intéresse à l’efficacité dans la constructionet le stockage pour réutilisation des composantes précédemment calculée dans unereprésentation. 46
  • 6 Les Dépendances Orientées Objets Un GDS [4] est une collection de GDP, un pour chaque procédure. Un GDP [10]représente une procédure comme un graphe, dans lequel les nœuds sont les instructions ou lesexpressions prédicatives. Les arcs de dépendances de données représentent un flux de donnéesentre des instructions ou des expressions, et les arcs de dépendances de contrôle représententdes conditions de contrôle, sur lesquelles l’exécution d’une instruction ou une expression endépend. Chaque GDP contient un nœud Entrée qui représente l’entrée dans la procédure. Pour modéliser le passage des paramètres, un GDS associe, à chaque nœud d’entréed’une procédure, les nœuds «Formal-in» et «Formal-out». Un GDS comporte un nœud «Formal-in» pour chaque paramètre formel de laprocédure, et un nœud «Formal-out» pour chaque paramètre formel qui peut être modifié[17]par la procédure. Un GDS associe, à chaque position d’appel dans la procédure, un nœud d’appel et unensemble de nœuds «Actual-in» et «Actual-out». Un GDS contient un nœud «Actual-in» pour chaque paramètre effectif à la positiond’appel, et un nœud «Actual-out» pour chaque paramètre effectif qui peut être modifié par laprocédure appelée. A l’entrée de la procédure et aux positions des appels, les variables globales sonttraitées comme des paramètres. Par conséquent, il y a des nœuds «Actual-in»,«Actual-out»,«Formal-in» et «Formal-out» pour ces variables globales. Notons aussi que les GDS relient les GDP aux positions des appels. Un arc d’appel relie un nœud d’appel de la procédure au nœud Entrée du GDP de laprocédure appelée. Les arcs «Parameter-in» et «Parameter-out» représentent le passage des paramètres. Lesarcs «Parameter-in» relient «Actual-in» et «Formal-in», et les arcs «Parameter-out» relient lesnœuds «Formal-out» et «Actual-out». Pour faciliter le calcul d’une tranche interprocédurale qui considère le contexte d’appel,un GDS représente le flux des dépendances à travers des endroits d’appel. Un flux transitif de dépendance se produit entre un nœud «Actual-in» et un nœud«Actual-out», si la valeur associée au nœud «Actual-in» affecte celle associée au nœud«Actual-out». Le flux transitif de dépendance peut être généré par des dépendances dedonnées et/ou de contrôle. Un arc résumé modélise le flux transitif de dépendances à traversun appel de procédure.III-Les GDS des programmes orientés objets:III-1-Graphe de Dépendances des Classes: Cette section décrit la construction du GDC pour des classes singulières, des classesdérivées, et des classes en interaction. De plus, elle discutera la manière avec laquelle onreprésente le polymorphisme.III-1-1-Représentation des classes de base: Pour faciliter l’analyse et la réutilisation, on représente chaque classe dans un systèmepar un Graphe de Dépendances de la Classe (GDC).[25] Un GDC capture les relations de dépendances de données et de contrôles qui peuventêtre déterminées à propos d’une classe sans connaître les environnements d’appel. Chaque méthode dans un GDC est représentée par un GDP. Chaque méthode a unnœud Entrée de la méthode représentant son entrée. Un GDC contient aussi un nœud Entrée de la Classe qui est relié au nœud Entrée de laméthode, pour chaque méthode dans la classe par un arc membre de la classe. 47
  • 6 Les Dépendances Orientées Objets Les nœuds d’entrées et les arcs membres des classes nous permettent d’accéderrapidement aux informations des méthodes, quand une classe est combinée avec une autreclasse ou système. Notre construction du GDC étend chaque entrée de méthode par l’ajout de nœuds«Formal-in» et «Formal-out». On ajoute de nœuds «Formal-in» pour chaque paramètre formeldans la méthode, et les nœuds «Formal-out» pour chaque référence à un paramètre formel quiest modifié par la méthode. De plus, on ajoute les paramètres «Formal-in» et «Formal-out»pour les variables globales qui sont référencées dans la méthode. Enfin, tant que les instances des variables d’une classe sont accessibles à toutes lesméthodes dans la classe, on les traite comme globales aux méthodes dans la classe, et onajoute des nœuds «Formal-in» et «Formal-out» pour toutes les instances des variables qui sontréférencées dans la méthode. L’exception dans cette représentation, pour les instances des variables, est que notreconstruction omet les nœuds «Formal-in» pour les instances des variables dans leconstructeur de la classe, et les nœuds «Formal-out» pour les instances des variables dans ledestructeur de la classe. Vu que les méthodes dans une classe peuvent s’interagir, un GDC doit inclure unereprésentation des effets d’appel de méthodes par le nœud d’appel. A chaque nœud d’appel, ily a des nœuds «Actual-in» et «Actual-out» à lier au nœuds «Formal-in» et «Formal-out»présents à l’entrée de la méthode appelée. Un GDC doit représenter les effets des instructions de retours, qui signifient qu’uneméthode retourne une valeur à son appelant. Dans un GDC, chaque instruction de retour estliée à son nœud d’appel correspondant en utilisant un arc «Parameter-out». De plus, pour toutparamètre «Formal-in» qui peut affecter la valeur de retour, les arcs résumés sont rajoutésentre les nœuds «Formal-in» et le nœud d’appel. Ces arcs résumés facilitent la troncatureinterprocédurale.III-1-2-Représentation des classes dérivées: On construit un GDC pour une classe dérivée par construction d’une représentationpour chaque méthode définie par la classe dérivée, et réutilisation des représentations detoutes les méthodes qui sont héritées des classes de base. On crée un nœud d’Entrée de Classe pour la classe dérivée, et on rajoute des arcsmembres de classe, reliant ce nœud d’Entrée de classe au nœud d’Entrée de méthode dechaque méthode dans la définition de la classe dérivée. On crée aussi des arcs membres declasse pour relier le nœud d’Entrée de classe aux nœuds d’Entrée de méthode de n’importequelle des méthodes, définies dans la classe de base et qui sont héritées par la classe dérivée. Les nœuds «Formal-in» pour une méthode, représentent les paramètres formels de laméthode, les instances de variables dans la classe dérivée ou les classes de base qui peuventêtre référencées par un appel à cette méthode, et les variables globales qui peuvent êtreréférencées par cette méthode. De manière similaire, les nœuds «Formal-out» pour une méthode, représentent lesparamètres formels de cette méthode, les instances des variables dans des classes de base oudérivées, qui peuvent être modifiées par un appel à cette méthode, et les variables globales quipeuvent être modifiées par un appel à cette méthode.III-1-3-Représentation des classes en interaction: Dans les logiciels orientés objets, une classe peut instancier une autre classe, soit àtravers une déclaration, ou par utilisation d’un opérateur tel que new. Quand une classe C1 instancie une classe C2, il y a un appel implicite au constructeurde C2. Pour représenter cet appel implicite au constructeur, notre construction du GDCrajoute un nœud d’appel dans C1 à la location de l’instanciation. Un arc d’appel relie ce nœud d’appel au constructeur de la méthode de C2. 48
  • 6 Les Dépendances Orientées Objets Notre construction du GDC rajoute aussi des nœuds « Actual-in » et « Actual-out » aunœud d’appel pour relier les nœuds «Formal-in» et «Formal-out» dans le constructeur de C2. Quand il y a une position d’appel d’une méthode M1 de C1 à la méthode M2appartenant à l’interface publique de C2, notre construction rajoute un arc d’appel entre lenœud d’appel dans C1 et le nœud d’entrée de M2, sans oublier le rajout des arcs duparamétrage. Le chaînage de ces deux GDC forme un nouveau GDC représentant un système partiel.III-1-4-Représentation du polymorphisme: Un GDC doit représenter les appels polymorphiques de méthodes, qui se produisentquand un appel de méthode est lancé, et la destination de l’appel est inconnue au moment dela compilation. Un GDC utilise un nœud Choix Polymorphique pour représenter le choix dynamiqueparmi les destinations possibles. Un nœud d’appel correspondant à un appel polymorphiquepossède un arc d’appel incidant à un nœud de choix polymorphique. Un nœud de choix polymorphique a des arcs d’appel incidant aux sous-graphesreprésentant les appels pour chaque destination possible. Le nœud de choix polymorphique représente la sélection dynamique d’une destination.Une analyse statique, à l’encontre, doit considérer toutes les possibilités.III-2-Systèmes Incomplets: Les classes et ses bibliothèques sont souvent développées indépendamment desprogrammes d’application qui les utilisent. Pour représenter ces systèmes incomplets pour analyse, on simule les environnementsd’appels possibles en utilisant un frame.[12] Un frame représente un pilote universel pour une classe, qui nous permet de simulerl’appel des méthodes publiques dans n’importe quel ordre. En premier lieu, un frame appelle le constructeur de la classe, et entre par la suite dansune boucle qui possède des appels à chaque méthode publique dans la classe. Pour chacunedes itérations de cette boucle, le contrôle peut passer à n’importe quelle méthode publique. Ala fin de cette boucle, le frame appelle le destructeur de la classe. Un frame est le programme main d’un GDS pour un système incomplet. Parconséquent, on l’utilise pour construire un GDP. L’appel au constructeur, la boucle du frameet l’appel au destructeur sont tous en dépendance de contrôle avec le nœud Entrée du frame.La boucle du frame est aussi en dépendance de contrôle avec elle même. Finalement, l’appeldu frame est en dépendance de contrôle avec sa boucle. L’appel du frame est remplacé par des appels aux méthodes publiques dans la classe, etles nœuds paramètres sont rajoutés aux endroits des appels. Pour créer un GDP d’un frame d’une classe particulière, on remplace le nœud d’appeldu frame par les nœuds d’appel pour chaque méthode publique dans la classe. Notez que, vu que les variables gardent leurs valeurs entre les appels des méthodes, ilpeut y avoir des dépendances de données entre les endroits des appels, même si les variablesne sont pas visibles dans le programme d’appel. pour expliquer ces dépendances de données,notre construction rajoute des arcs de dépendances de données entre les nœuds « Actual-out »de chaque appel de méthode et les nœuds « Actual-in » correspondant à tout autre appel deméthode. On doit signaler qu’on ne peut avoir un flux (propagation) de valeurs à travers leconstructeur de la classe, à l’exception des paramètres formels, vu qu’il n’existe aucunevaleur des instances de variables précédemment utilisées. De même, on ne reçoit aucun flux 49
  • 6 Les Dépendances Orientées Objetsde valeur à partir du destructeur, tant que les instances des variables ne sont pas disponiblespour longtemps.III-2-Systèmes Complets: On construit un GDS pour un programme complet en connectant des appels, dans leGDS partiel, aux méthodes dans le GDC pour chaque classe. Cette construction implique qu’on relie les nœuds d’appel aux nœuds d’entrées desméthodes, les nœuds «Actual-in» aux nœuds «Formal-in», et les nœuds «Formal-out» auxnœuds «Actual-out». Les arcs résumés des méthodes, d’une classe précédemment analysée,sont rajoutés entre les nœuds «Actual-in» et «Actual-out» aux endroits des appels. Cette construction du GDS, pour un système orienté objet, maximise la réutilisation deportions des représentations précédemment construites. L’introduction de variables dans la portée du programme d’application, telle qu’unevariable globale, n’affecte pas la représentation dans n’importe quelle partie du GDC.N’importe laquelle des variables globales, référencée ou modifiée par une classe, doit êtredéclarée extern dans la classe, donc cette information doit être incluse durant la constructiondu GDC de la classe.IV- Algorithme de construction du GDS: La procédure de construction du GDS reçoit en entrée le flux de contrôle pour chaqueprocédure ou méthode dans un programme, et fournit en sortie le GDS de ce denier. Cetteprocédure construit le GDP pour l’ensemble des méthodes dans chaque classe. Pour calculer le GDP des méthodes d’une classe, la procédure de construction identifieen premier lieu les méthodes qui ont besoin de nouveaux GDP. Ensuite, pour chaque méthodeM définie dans C, l’algorithme construit le GDP de M. Pour une méthode M définie dans uneclasse de base, si M appelle directement ou indirectement une méthode virtuelle redéfiniedans C, l’algorithme construit le GDP à partir de celui de M qui a été construit pour la classede base. Si M n’appelle aucune méthode virtuelle redéfinie dans C, l’algorithme réutilise leGDP de M avec la classe de base. Après construction du GDP pour chacune des méthodes, la procédure de constructionappelle la procédure de connexion, avec des arcs de liaison, chaque site d’appel dans ces GDPavec l’entrée de la méthode appelée. 50
  • 6 Les Dépendances Orientées Objets Algorithme ConstructGDS; Entrée: graphe du flux de contrôle du programme P; Sortie: GDS de P; Déclaration: Début ConstructGDS; 1. Pour chaque classe C 2. Identifier les méthodes qui ont besoin d’une nouvelle présentation; 3. Pour chaque méthode M déclarée dans C 4. Calculer les dépendances de contrôle de M; 5. Prétraitement de M avec l’analyse du flux de données; 6. Etendre les objets dans M; 7. Calculer les dépendances de données pour les objets; 8. Fin Pour; 9. Pour chaque méthode M dans les classes de base 10. Si M est marquée alors 11. Copier l’ancien GDP 12. Ajuster les sites d’appel; 13. Sinon 14. Réutiliser l’ancien GDP de M; 15. Fin Si;. 16. Fin Pour; 17. Fin Pour; 18. Connecter(); 19. Construct_Arcs_Résumés(); Fin ConstructGDS. 51
  • 7 Les Tranches – Concepts De BaseLes tranches – Concepts généraux-I-Introduction: La troncature des programmes est une opération qu’on effectue sur les relations dedépendances et qui a plusieurs applications telles que le débogage, la compréhension de code,tests des programmes et l’analyse des métriques. Elle permet d’extraire des tranches dont lecomportement est indiscernable du programme initial en respectant un critère de troncaturecomposé d’un point p du programme et d’un sous-ensemble de variables V de ce programme.II-Définition d’une tranche: Les tranches sont des programmes exécutables qui sont construits par élimination(suppression) de zéro ou plusieurs instructions du programme initial. Une tranche de programme, par rapport à un point p et une variable v, consiste en desinstructions du programme et de ses prédicats qui peuvent affecter la valeur de v au point p.Son comportement est identique à celui du programme d’origine par rapport à un critèredonné, c’est à dire qu’une tranche est un fragment du programme d’entrée, isolé par rapport àune instruction critique dans le programme. La variable v et le point p définissent le critère de troncature noté C=<p,v>. En d’autrestermes, une tranche de programme est un programme de taille réduite dont le comportementpar rapport à un critère donné est identique à celui du programme source.III-Extraction des tranches de programmes – Procédés et Algorithmes-: Les algorithmes utilisés pour l’extraction des tranches se basent sur l’analyse du flux dedonnées et de contrôle en déterminant ainsi les tranches inter et intra-procédurales. Ottenstein et Ottenstein [ ] définissent un algorithme efficace utilisant une méthode deparcours de graphe sur GDP. Horwitz, Reps et Binkley utilisent aussi les graphes dedépendances et ils ont développé une représentation interprocédurale du programme qui est leGDS et un algorithme de parcours du graphe en deux passes exploitant ce GDS. Notez que le type de parcours du GDS définit le type de la tranche, de ce fait, on a deuxtypes de tranches: 1. Une tranche arrière [Weiser 84]: c’est une tranche composée de toutes les instructions et prédicats dont dépend le calcul de la valeur de v au point p. 2. Une tranche avant [Binkley95 – Jackson94 – Reps95]: c’est une tranche composée de toutes les instructions et prédicats qui peuvent dépendre de la valeur de v au point p. Autrement dit, la tranche avant est le dual de la tranche arrière. D’après [Binkley93], une tranche interprocédurale d’un GDS par rapport à un nœud vest calculée en utilisant deux passes sur le graphe. Les arcs résumés sont utilisés pourpermettre de passer d’un nœud d’appel à un autre sans avoir à descendre vers la procédureappelée. Par conséquent, ceci n’a pas besoin de garder une trace explicite du contexte d’appelpour s’assurer que les liaisons d’une exécution légale se sont traversées. Les deux passes opèrent sur le GDS, en traversant les arcs afin de trouver l’ensembledes instructions qui peuvent atteindre (affecter) un ensemble donné de nœuds, tout au long decertains types d’arcs. Le parcours dans la première passe commence à partir de tout nœud v et va en marchearrière (depuis la cible jusqu’à la racine) à travers les arcs de flux, arcs de contrôle, arcsd’appel, arcs résumés et les arcs «Parameter-in» des paramètres d’entrée, mais non plus àtravers les arcs «def-ordre» ou «Parameter-out» des paramètres de sortie. Le parcours dans la deuxième passe commence à partir de tous les nœuds atteints dansla première passe et part en marche arrière à travers les arcs de flux, arcs de contrôle, arcs 52
  • 7 Les Tranches – Concepts De Baserésumés et les arcs «Parameter-out» des paramètres de sortie, mais non plus à travers les arcs«def-ordre» ou les arcs «Parameter-in» . Le résultat d’une tranche interprocédurale se compose des ensembles de nœudsrencontrés (parcourus) durant les deux phases (c’est un sous-graphe du graphe de départ). Pour la troncature intra-procédurale, la tranche d’un graphe de dépendances peut êtreutilisée pour produire un programme exécutable par restriction du système initial auxéléments dont les nœuds sont dans la tranche du graphe de dépendances. Il est totalement faux de considérer le même raisonnement sur une tranche directementproduite à partir d’un GDS vu qu’on peut trouver des instructions syntaxiquement illégales,parce qu’elles contiennent des paramètres incompatibles. Ça est dû au fait que deuxinstructions d’appel, représentant des appels d’une procédure, contiennent des sous-ensemblesdifférents de paramètres de la procédure. Il y a deux problèmes relatifs à l’incompatibilité: 1. Deux endroits d’appel pour la même procédure peut inclure des nœuds «Actual-in» différents. 2. Deux endroits d’appel pour la même procédure peut inclure des nœuds «Actual-out» différents. L’extraction de tranche (troncature) a grandement évolué depuis sa naissance dansWeiser[1984], et plusieurs nouveaux algorithmes destinés à résoudre ce problème ont vu lejours. Le plus connu est celui utilisant le concept des graphes de dépendances desprogrammes (GDP)[Ferrante et Ottenstein 1987, Horwitz et al 1990, Ottenstein et Ottenstein1984]. Le GDP est une structure de données adéquate principalement pour la troncature, parcequ’il intègre l’ensemble des flux de données et de contrôle en un seul graphe, et parconséquent, réduit la troncature de programme en un problème de parcours d’ungraphe[Ottenstein et Ottenstein 1984]. Dans le contexte des application temps réel, on admet les hypothèses suivantesconcernant la structure des programmes: Toute condition contient seulement une variable booléenne simple. Les instructions de saut inconditionnel tel que Goto et break ne sont pas présentes dans le code de la tâche.Algorithme de la troncature des programmes: On va s’intéresser à la troncature exécutable, arrière et statique des programmes, c’est àdire que: Chaque tranche est exécutable comme un programme propre. Les tranches sont calculées selon des données statiques disponibles, données arrières et les informations du flux de contrôle. Conceptuellement, une tranche arrière d’un programme P, par rapport à un point p etune expression e, est composée des instructions de P et les prédicats de contrôle qui peuventaffecter la valeur de e au point p. Le couple (p,e) est généralement appelé le critère de la troncature et la tranche associéeest notée P/(p,e). L’idée est que pour déterminer la valeur de e à p, on a besoin seulementd’exécuter la tranche P/(p,e). L’algorithme d’extraction a besoin de considérer les trois types de dépendances dedonnées, de flux, anti-dépendances et dépendances de sortie. Ça peut être effectué de manièredirecte par extension de la définition du GDP (ou GDS) pour avoir un GDPE (Graphe deDépendances de Programme Etendu). 53
  • 7 Les Tranches – Concepts De Base Les nœuds d’un GDPE représentent les instructions de la tâche, avec un nœudparticulier Entrée, qui est la racine de la tâche. Les arcs d’un GDPE sont de deux types: 1. N1 c N2 qui signifie une dépendance de contrôle entre N1 et N2, et on a: soit N1 est le nœud Entrée et N2 ne faisant pas de références dans une boucle ou condition. ou bien N1 représente un prédicat de contrôle et N2 est immédiatement introduit dans une boucle ou une condition dont le prédicat est représenté par N1. 2. N1 d N2 dénotant soit une dépendance de flux, de sortie ou une anti- dépendance. De ce fait, un contrôle peut atteindre N2 après N1 à travers une liaison, sur laquelle il n’y a aucune définition de variable v et : N1 définit v et N2 l’utilise (dépendance de flux). N2 définit v et N1 l’utilise (anti-dépendance). N1 et N2 définissent v (dépendance de sortie). On définit (p⇒*q) pour signifier que le nœud p peut atteindre le nœud q à travers zéroou plusieurs arcs de dépendances de contrôle et de données. Notez qu’on ne considère pas lesdépendances d’itération concernant les structures périodiques des tâches, vu qu’on ne passepas entre deux instances de tâches successives. Une tranche d’un programme P, en se référant à un point p de P et une expression e(c’est à dire P/(p,e)), qui peut être obtenue en parcourant le GDP de P. Vu que p dénote un nœud du GDPE, l’association d’un nœud dans le GDPE à uneseule ligne source simplifie énormément le processus d’isolation d’une tranche d’unprogramme. Pour cela, le programme source subit un prétraitement afin que toutes lesinstructions d’affectation et les prédicats de contrôle se trouvent sur des lignes de texteséparées. Par conséquent, dans notre problème, le critère de troncature (p,e) n’a pas besoind’inclure l’expression e vu que e est complètement du côté droit dans p, ce qui revient à direque le point du programme <p> seul peut servir comme un critère de troncature. On peut étendre la définition d’une tranche de programme par un ensemble de critèresde troncature C d’une manière générale et on la définit telle que : P/C=U<p>∈c P/<p>.Algorithme calculant la tranche P/<n> : Etape1: calculer la tranche par un parcours arrière du GDPE tel que: P/<n>={m/m⇒*n}. Etape2: marquer tous les nœuds dans P/<n>. L’ensemble ainsi obtenu représente latranche recherchée. Un de nos objectifs essentiels est de fournir le critère de troncature le plus adéquat pourl’algorithme de telle sorte que la tranche temporelle de la tâche couvre tous lescomportements observables de la tâche en cours d’étude.IV- Considérations pratique: La troncature des STR dépend des analyses imprécises et statiques des flux de donnéespour calculer les tranches de programme. En pratique, on suppose l’existence d’une relationde dépendance de données entre n’importe quelles deux instructions, à moins qu’on puisseprouver statiquement qu’une n’a pas modifié des variables que d’autres accèdent pour lesconsulter. Cela a un grand impact quand on est confronté aux appels de fonctions. Quand unefonction modifie les données des pointeurs, les analyseurs contemporains sont souvent forcéspour supposer que l’opération peut être sur n’importe quelle variable globale dans leprogramme. Ceci va naturellement se tromper sur le côté conservatif et va supposer qu’un 54
  • 7 Les Tranches – Concepts De Baseappel de fonction provoque des relations de dépendances où ça n’existe pas. Au pire des cas,on va finir avec un code qui semble être intranchable, alors qu’on doit se ramener à latroncature. Pour les dépendances de sortie et les anti-dépendances, notez qu’ils sont introduitescomme un résultat de la réutilisation de variables, et elles peuvent être éliminées par unprétraitement du code. Par conséquent, chacun peut utiliser deux étapes de l’approche afin de s’adapter auconstructions temporelles. Un analyseur de temps statique peut être utilisé pour uneestimation initiale et grossière. Ensuite, après avoir compléter la troncature du programme, lerésultat peut être vérifié avec une description plus sophistiquée qui exécute actuellement leprogramme. L’amélioration des performances de telles temporisations est importante dans lastructure des mémoires câches, où l’ordonnancement de code va toujours changerl’alignement des instructions. 55
  • 8 Les Tranches Orientées ObjetsLes tranches dans les Systèmes Orientés Objets:I-Introduction: La troncature des programme a plusieurs applications telles que le déboggage, lacompréhension de code, tests des programmes et analyses des métriques. Weiser [20] définit une tranche en respectant un critère de troncature qui consiste en unpoint p et un sous-ensemble de variables V du programme. Ces tranches sont des programmesexécutables qui sont construits par suppression de zéro ou plusieurs instructions duprogramme original. Son algorithme utilise l’analyse du flux de données et les graphes de flux de contrôlepour calculer les tranches inter et intra-procédurales. Ottestein & Ottenstein [20]définissent un critère de troncature en se référant à un point pdu programme et une variable v qui est définie ou utilisée au point p. Ils utilisent unalgorithme de parcours de graphe sur le GDP pour calculer une tranche qui se compose detoutes les instructions et prédicats du programme qui peuvent affecter la valeur de v au pointp. Horwitz, Reps et Binkley [14] utilisent aussi les graphes de dépendances pour calculerles tranches. Ils ont développé la représentation interprocédurale du programme qui est leGDS et un algorithme de parcours du graphe en deux passes qui exploite ce GDS. L’algorithme des deux phases calcule des tranches inter-procédurales plus précisesparce qu’il utilise les informations résumées aux endroits d’appels en considérant le contexted’appel des procédures appelées.II-Environnement de l’algorithme et son application : Pour dresser les caractéristiques orientées objets, on a développé des GDS pour lesapplications orientées objets sur lesquels un algorithme de troncature interprocédurale [14,23] sera appliqué. On doit noter que la technique adoptée permet le calcul de tranches pour des classesuniques (seules) ainsi que les tranches pour des systèmes complets. Les GDS définis pour les programmes orientés objets sont adéquats pour l’applicationde l’algorithme d’atteinte du graphe de deux phases afin de calculer les tranches. Cetalgorithme utilise un critère de troncature <p,x> dans lequel p est une instruction et x est unevariable qui est définie ou utilisée au point p. Les développeurs de logiciels orientés objets empêchent les utilisateurs d’une classe demanipuler de manière directe les instances des variables à l’intérieur d’un objet (l’état del’objet), en fournissant des méthodes comme une interface afin de situer et observer l’état del’objet. Par conséquent, les systèmes orientés objets substituent plusieurs références devariables avec des appels de méthodes qui retournent simplement une valeur. Pour nous permettre de tronquer sur les valeurs retournées par une méthode, on utiliseun critère de troncature peu modifié. Notre critère de troncature <p,x> se compose d’uneinstruction et une variable ou un appel de méthode x. Si x est une variable, elle doit être définie ou utilisée à p. Si x est un appel de méthode,cette dernière doit être appelée à p. Tant que notre construction du GDS crée des arcs résumés, qui sont utilisés pourpréserver le contexte de l’appel, on calcule les tranches qui satisfont notre critère sur nos GDSen utilisant l’algorithme des deux phases. Durant la première phase de l’algorithme de troncature, les arcs résumés facilitent latroncature à travers les nœuds d’appel (de l’un à l’autre), qui ont des dépendances transitivessur des nœuds «Actual-in». 56
  • 8 Les Tranches Orientées Objets Durant la deuxième phase de l’algorithme, on descend dans les méthodes appelées(procédures) à travers les arcs «Parameter-out». Vu qu’on calcule une tranche, comme si toutes les séquences possibles des appels auxméthodes publiques étaient possibles, le calcul peut inclure dans ses résultats plusd’instructions par rapport à une même tranche prise à partir d’un programme d’applicationqui spécifie une séquence d’appels particulière de méthodes publiques. Cependant, durant le développement, ce type de tranches peut être utile tant qu’ellesindiquent les dépendances qui peuvent exister entre les instructions dans la classe, et peutaider dans la compréhension , le déboggage ou le test de la classe. Notez bien que les notions de tranche avant et tranche arrière se conservent pour lesapplications orientées objets de même que pour une application classique simple.III- Extraction de tranche (Tranche Arrière): La première phase de l’algorithme de troncature interprocédurale traverse en marchearrière le long de tous les arcs du GDS à l’exception des arcs «Parameter-out» et marque lesnœuds atteints. La deuxième phase traverse en arrière, à partir de tous les nœuds marqués durant lapremière phase, le long de tous les arcs à l’exception de ceux d’appel et «Parameter-in», etmarque les nœuds atteints. La tranche est l’union des nœuds marqués durant les deux phases.III- Troncature d’objet: Dans un programme orienté objet, quand un objet est instancié à partir d’une classe, lesmembres de données et méthodes de la classe sont instanciés pour cet objet. Le fait qu’on utilise une seule représentation pour toutes les instances d’une méthode,toutefois, l’ensemble des instructions dans une méthode identifié par un algorithme detroncature, tel que Horwitz & al[7], inclut les instructions dans des différentes instances de laméthode. Pour l’étude des tâches, on doit s’accentuer sur un seul objet à la fois. Pour cela, on veutidentifier l’ensemble des instructions dans les méthodes d’un objet particulier, qui peutaffecter le critère de troncature. C’est la troncature d’objet. L’extraction d’une tranche d’un objet O, par rapport à un critère (v,p), on doit enpremier lieu avoir la tranche complète à partir du GDS par rapport à (v,p). Ensuite, onidentifie les endroits d’appel (envoi de message), qui ont été marqués par l’algorithme detroncature. Les méthodes invoquées par ces sites d’appels sont les seules méthodes de O quipeuvent affecter (v,p). Par la suite, on identifie les instructions dans ces méthodes qui sontincluses dans la tranche vu l’invocation des endroits d’appel sélectionnés. On appelle cesinstructions la tranche de O. Pour identifier les endroits d’appel et d’envoi de message, qui ont été marqués parl’algorithme de troncature, on examine les nœuds, le sous graphe de flux de l’objet O dans laméthode ou la procédure dans laquelle O est construit. Si O est passé comme un paramètre àune autre méthode ou procédure, on traverse l’arc de liaison à l’endroit d’appel , et oncontinue à examiner le sous graphe de flux de l’objet paramètre formel dans la méthode ou laprocédure appelée. Le parcours se poursuit jusqu’à ce que tous les sites d’appel de l’objetsoient examinés. Une instruction S dans une méthode d’un objet peut affecter (v,p) de plusieurs manières.Premièrement, S peut affecter un paramètre «Actual-out» Aout dans un endroit d’appel (envoide message) de l’objet O, qui appelle M, et Aout à son tour peut affecter (v,p). Ce cas seproduit quand l’exécution de P doit se passer après le retour de l’appel. l’ensemble des Aoutest l’ensemble des nœuds «Actual-out», qui sont marqués par les deux phases de l’algorithme 57
  • 8 Les Tranches Orientées Objetsde troncature, lorsqu’on calcule la tranche pour le programme tout entier. Etant donné un Aout,S est une instruction qui peut atteindre Fout, le nœud « Formal-out » qui est contraint à Aout, àtravers un chemin composé seulement de nœuds dans M. On identifie ce type d’instruction enutilisant la marche arrière dans M, commençant par Fout. En deuxième lieu, si p est aussi dans M, S peut affecter (v,p) à travers un chemin secomposant des nœuds qui sont dans M seulement. On identifie ce type d’instruction enutilisant la marche arrière dans M, commençant par p. Troisièmement, S peut affecter (v,p) en affectant un paramètre «Actual-in» Ain au sited’appel c dans M, dans le cas où Ain peut atteindre p à travers des chemins qui ne traversentaucun arc «Parameter-out». Cela veut dire que p est exécutée avant le retour de l’appel c. Pouridentifier ce type d’instruction, on doit au départ marquer l’ensemble des Ain. Ce marquagepeut être fait à l’aide d’un parcours en arrière à partir de p, sans traverser aucun des arcs«Parameter-out». Le marquage peut aussi être accompli par le rajout d’une marque aux nœudsparamètres «Actual-in», à la fin de la première phase de l’algorithme de troncature. Dans cecas, l’ensemble des Ain va contenir, en plus de ses valeurs précédentes, les marques d’appeldans M. Après le marquage des Ain, on identifie l’ensemble des S par un parcours arrière, encommençant par les nœuds paramètres «Actual-in» marqués. Il est facile de voir que si une instruction dans une méthode d’un objet peut affecter(v,p), alors elle doit être marquée par l’un des trois cas. De ce fait, le processus ci-dessus peutêtre utilisé pour calculer la tranche de l’objet O. 58
  • 9 L’Instrumentation Des ProgrammesInstrumentation des programmes–Méthodologies générales, application sur les systèmesorientés objets et implémentation:NB. Le compilateur du langage adopté doit être réalisé et l’instrumentation est baséeessentiellement su les résultats de ce compilateur.I-Définition: L’instrumentation consiste en la réécriture du programme source suivant uneformalisation particulière. Chaque ligne du programme instrumenté est définie par le couple<n°d’instruction:,instruction>. L’instrumentation consiste à séparer les instructions du programme source et générerune autre écriture de ce programme dont chaque ligne de ce dernier correspond à uneinstruction simple. L’instrumentation étant une phase primordiale dans la compréhension du code source enfacilitant la génération du graphe de dépendances. C’est une technique de séparation d’entitésqui vont jouer le rôle de nœuds du GDS durant la phase de génération du graphe dedépendances.II- Concepts de la mise en œuvre de l’instrumentation: On signale que dans le code instrumenté, on a: Chaque ligne correspond à une instruction simple (instruction de calcul, appel de procédure, d’affectation) ou un prédicat (boucle ou alternance). Chaque ligne est étiquetée par un numéro de séquence initialisé à zéro. Les délimiteurs d’ouverture des blocs d’instructions sont considérés comme étant des instructions vides et sont associées à leurs initiateurs.III- L’instrumentation d’un programme orienté objet: Le concept de l’instrumentation se conserve pour les applications orientées objets.Malgré l’apparition de nouvelles constructions et formats d’instruction (définition de classes,définition des méthodes et attributs, constructeur de classe, ..etc.), la manière d’extraction desentités et instructions élémentaires semble être inchangée. Cependant, on peut noter les pointssuivants: Chaque ligne du code instrumenté définit une instruction du programme d’origine écrite sous la forme d’un couple composé du numéro de l’instruction et l’instruction elle même. Une définition d’une classe est considérée comme étant une instruction, et donc fera partie du code instrumenté (on va lui faire correspondre une ligne dans le code instrumenté). Toute déclaration d’attributs, instruction de calcul, appel de méthode, constructeur de classe, ou autre à l’exception des instructions prédicatives, sont des instructions élémentaires qu’on va leur associer une ligne de code dans le code instrumenté. On ne fait aucun traitement particulier entre le corps d’une méthode et celui de la partie main de l’application en cours d’étude. Les instructions prédicatives (if, while, ..etc.) se traiteront d’une manière particulière. Le prédicat sera dans une seule ligne du code instrumenté vu qu’il joueront le rôle de nœuds de contrôle dans le GDS. On appliquera par la suite les règles décrites ci-dessus sur la partie restante de l’instruction en cours. 59
  • 9 L’Instrumentation Des ProgrammesIV- Mise en œuvre du processus d’instrumentation: La réalisation d’un processus automatique de génération d’un programme instrumenté, àpartir du code source, semble être une opération simple à implémenter. Elle est d’autant facileet sûre lorsqu’on introduit un programme correct (passé par la phase de compilation), afin dele décharger du rôle de vérification et correction des erreurs de programmation. Le processus de génération du code instrumenté consiste en le parcours du programmed’entrée, et une fois il détecte un point virgule, accolade ouvrant, fermante, ou un prédicat, ilgénère la ligne du code instrumenté correspondante. Ce processus se poursuit jusqu’à arriver àla fin du programme traité. 60
  • 10 Restructuration Des Programmes Orientés Objets (Java)Restructuration des programmesConcepts de base – Application aux Programmes Orientés Objets:I-Introduction: La restructuration de programmes est une méthodologie de transformation etmodification de la structure interne de codes, tout en conservant leurs sémantiques.L’adoption de cette technique a grandement facilité la compréhension des programmes et lamaintenance des logiciels, elle permet de plus d’avoir un code optimisé, améliorerl’ordonnançabilité, la décomposition, la conversion et la réutilisation de composantes deprogrammes. Elle est un moyen efficace pour l’étude comportementale des programmes. Dans notre étude, cette technique sera appliquée aux programmes temps réels, où lefacteur temps représente un paramètre essentiel pour l’analyse du comportement du système.L’évolution de tels systèmes peut importer des modifications sur les caractéristiques tempsréels des tâches (échéances, temps d’exécution,…)[POS92], ou surcharger les ressources. Dece fait, la restructuration devient une nécessité devant le développement dun programmed’une application temps réel qui tend à devenir peu structuré. De plus, la restructurationsemble être le moyen adéquat et une option importante pour le contrôle des coûts de lamaintenance des logiciels. Il existe d’autres raisons pour la restructuration telles que : Faciliter les tests. Réduction potentielle de la complexité des programmes. Etendre la durée de vie des programmes en maintenant une flexibilité à travers une bonne structure. Mise en place de standards pour les structures des programmes. Préparer les programmes pour faire l’objet d’entrée à des outils (parallélisme, test,..). Préparer les programmes pour la conversion. Préparer pour ajouter de nouvelles caractéristiques au logiciel. La restructuration est aussi appliquée en cours de développement des logiciels, surtouten cas de non possession de méthodes de programmation rigoureuses, en ayant commeobjectif l’amélioration des performances du logiciel. On en déduit que la restructuration n’estune fin d’autant qu’elle ne soit un moyen pour réaliser des objectifs fixés tels que : Rendre le code en cours d’étude plus facile à comprendre, sans altérer ses dépendances de données ou de contrôle. Formatage du code (restructuration textuelle). Souplesse dans la détermination du flux de contrôle. Durant la phase de développement d’une application, on peut être amené à concevoirdes tâches non ordonnançables. Cela peut entraîner l’échec du système dans l’exécution àtemps d’une tâche temps réel, causé par une violation d’échéance[STE97]. Pour palier à cetype de problème, les programmeurs procèdent manuellement, à d’intenses activités demodifications, de déplacement de portions de codes, de prise de mesure et de restructuration.Un tel processus est lent, coûteux et non contrôlable[CHU95,GER97]. Il se pourrait que danscertains cas, que tout un système doit être reconçu.II-Approche de restructuration: Nous savons déjà que la restructuration est un moyen de changement de la structureinterne d’un programme en gardant sa sémantique intacte. En cas de l’application de ce concept pour améliorer l’ordonnançabilité, on obtientcomme résultat, des échéances flexibles. Nous pouvons assurer la flexibilité en restructurant 61
  • 10 Restructuration Des Programmes Orientés Objets (Java)une tâche afin d’avoir deux fragments. Le premier est un fragment temps contraint (noté FT),qui doit satisfaire son échéance. Le second est un fragment non temps contraint (noté FnT),qui correspond à un calcul interne. Ce dernier fragment peut tolérer un certain retard. Ensuite,les fragments seront séquentiellement recomposés, pour constituer un nouveau programme dela tâche en question, qui est sémantiquement équivalent au programme initial. La figure X-1 représente le comportement d’exécution d’une tâche périodique nonrestructurée. Les sections hachurées représentent les composants temps contraint duprogramme de la tâche. A la (K+1)ième période, l’exécution de cette tâche dépasse sonéchéance et devient par conséquent, non ordonnançable. Toutefois dans la figure X-2, lesactions temps contraint s’effectuent à l’intérieur de la fenêtre de temps prescrite, l’exécutionde la tâche entière est acceptable, sans avoir à provoquer d’erreurs fatales. (K)ième (K+1)ième (K+2)ième Fig. X-1:Exécution d’une tâche périodique non restructurée FT FnT (K)ième (K+1)ième (K+2)ième Fig. X-2:Exécution d’une tâche périodique après restructuration temporel Non temporelIII- Processus de restructuration: Nous savons déjà que la restructuration d’une tâche temps réel consiste à reformuler sonécriture, en extrayant son FT et FnT. Cependant, le processus d’extraction des fragments doit répondre au critère disant que,dans le cas où une instruction de contrôle est incluse dans le premier fragment, et qui contrôleun ensemble non vide d’instructions se trouvant dans le deuxième, alors on doit inclure cesinstructions dans le premier, afin de préserver la sémantique du programme initial. Il est à 62
  • 10 Restructuration Des Programmes Orientés Objets (Java)noter que la décomposition du programme de la tâche se fait d’une manière récursive, commemontré dans la figure X-3. Fragment I-1 Fragment I-2 Programme Fragment II Fig. X-3:Fragmentation de programme En voici en détail le processus de restructuration avec adaptation pour les applicationorientées objets: Phase1: Elle consiste à générer le GDS entier du système en cours d’étude. Il va servir pourl’étape suivante, et en appliquant l’algorithme de troncature, à extraire les tranches et parconséquent, l’obtention des fragments recherchés. Phase2: Ayant comme objectif le calcul du premier fragment (temporel),et en se servant durésultat de la première phase, elle se déroulera comme suit sur la partie main de notreprogramme: On efface dans le programme toutes les lignes (instructions) correspondantes aux nœuds non marqués. On obtient par conséquent l’ensemble des instructions temporelles. En cas d’une instruction d’appel à une méthode, on effectue sur le corps de cette méthode le même traitement décrit dans le premier point. Cela nous permettra d’obtenir deux sous méthodes, SM1qui représente la partie temporelle de la méthode M appelée, et sa partie restante forme la deuxième sous méthode SM2. Si SM1 n’est pas vide, on remplace chaque appel de M avec un appel de SM1. Le résultat ainsi obtenu, constitue le fragment temporel noté FT. Phase 3 : Elle a pour rôle le calcul du deuxième fragment (non temporel), en appliquant les étapessuivantes : A partir du programme (forme instrumentée), on efface les lignes qui correspondent aux nœuds marqués, sauf les instructions de contrôle (if, while,..) et les appels aux méthodes. On efface les lignes des instructions de contrôle ayant comme cible des ensembles vides d’instructions. 63
  • 10 Restructuration Des Programmes Orientés Objets (Java) Si le bloc de SM2 est vide, on efface les lignes d’appel de méthodes correspondantes aux nœuds marqués. On effectue les trois étapes précédentes à la méthode M afin d’obtenir la sous procédure SM2. Dans le programme principal, si le corps de SM2 n’est pas vide, on remplace tout appel de M marqué par un appel un appel de SM2, sinon on efface tout appel de M marqué. De même, si le corps de SM2 n’est pas vide, on remplace tout appel de M non marqué par un appel de SM1 suivi d’un appel de SM2, dans le but d’avoir seulement deux nouvelles déclarations obtenues à partir de M (SM1 et SM2), au lieu de trois déclarations (M, SM1 et SM2). Le résultat ainsi obtenu, constitue le fragment non temporel FnT.Remarques: On peut résumer notre objectif dans l’utilisation de la technique de restructuration, parla possibilité de générer deux partie de code complémentaires et indépendantes, dont l’unedépend du facteur temps, et son exécution passera comme prioritaire devant la partie nontemporelle, qui peut s’exécuter même en dehors de son échéance sans la moindre crainte. Deux questions peuvent se poser : 1. Est ce qu’on est toujours contraint par la génération de deux et deux fragments seulement ? 2. A quel point on est sûr d’avoir des fragments et qui sont totalement indépendants? On peut répondre disant que tout dépend de la complexité du système en cours, lamanière avec laquelle, il a été conçu et développé et la nature de l’application cible. De cefait, on peut obtenir une séquence de fragments, dont le facteur d’indépendance intervientpour la détermination de leurs nombres, c’est à dire que le nombre de fragment diminuejusqu’à atteindre la valeur deux, tant que le degré d’indépendance entre les instructionstemporelles et le calcul interne est important. 64
  • 11 Conception Du Système De Restructuration Des Programmes Orientés Objets (Java)Partie I:Structure du Système de Restructuration des Programmes Orientés Objets Temps Réel: Le système se compose des modules suivants:1. Un compilateur:permettant: La détection des erreurs. La réalisation de l’instrumentation. L’extraction des dépendances entre les différentes instructions. Ce module est aussi dit Analyseur.2. Un générateur: il a comme tâche de générer le GDS du programme en entrée à partir de données fournies par le compilateur.3. Un extracteur: il permet l’extraction de tranches du programme à partir de son GDS.4. Un reconstructeur: il permet la génération du nouveau code du programme en entée de telle sorte que ce programme soit restructuré. entrée Compilateur : Programme A.Léxicale Erreurs de oui en entée A.Syntaxique programmation A.Sémantique non Instrumentation du Extraction Programme des dépendances source Générateur: Génération du GDS Fragment temporel Extracteur: Extraction des Fragment non tranches temporel Reconstructeur: Réorganisation des fragments extraits Sortie Cette représentation architecturale du Programme système de restructuration est universelle. Dans ce restructuréprojet, ce processus sera appliqué sur les programmes temporels orientés objets développésavec le langage Java. Fig IX-1 : Processus de restructuration 65
  • 11 Conception Du Système De Restructuration Des Programmes Orientés Objets (Java)Ce module est basé sur les résultats offerts par l’extracteur. Ce dernier permet l’extraction dufragment temporel et du fragment non temporel du programme source. De ce fait, lereconstructeur va tenter de placer le fragment non temporel après celui du temporel. Parconséquent, le code produit représente un programme restructuré qui permet de respecter leséchéances des tâches et assurant ainsi une exécution correcte et sûre.On peut schématiser le fonctionnement de ce système ainsi:Partie II:Approche De Restructuration Modèle Basé Tranches pour la Restructuration d’Applications Temps Réel ObjetsI- Introduction: Le monde du temps réel s’est élargi considérablement ces dernières années, ce qui apermis par conséquent d’améliorer les méthodes d’ingénierie. Plus particulièrement, lesméthodes orientées objets ont été étendues et couplées avec les propriétés temps réel, enfournissant des mécanismes au modèle d’activité temporel[Ishik92][Kim97]. On va considérer le domaine des applications temps réel, où les tâches sont accompliesrégulièrement afin de contrôler des processus physiques ou un fonctionnement de moniteur. Ilest extrêmement important de rencontrer des contraintes de temps dans de tels systèmes. Poursatisfaire leurs échéances, les tâches doivent être ordonnancées d’une manière appropriée. Lesalgorithmes d’ordonnancement des tâches dans les systèmes temps réel [Liu73][Klein94]permettent de s’assurer que toutes les tâches peuvent être accomplies au bout de leurséchéances de telle sorte qu’aucune d’elles ne dépasse son temps d’exécution dans le plus piredes cas. Une tâche qui dépasse son temps prévu, peut mener à la perte de l’échéance et l’échecde tout le système. Notons qu’une violation d’une échéance rend les tâches non ordonnançables. Dans cecas, on fait appel à des techniques manuelles et de force brute pour remettre les tâches dansune situation d’ordonnaçabilité. Les développeurs accomplissent des opérations intensives etmanuelles telles que l’instrumentation, prise de mesure, déplacement de fragments deprogrammes et éventuellement une reconception du système. Malgré ce que fournissent lescaractéristiques du modèle orienté objet, telles que l’héritage et le polymorphisme, en termede réutilisabilité et flexibilité, elles rendent le système plus difficile pour l’étude et unprocessus pénible et coûteux[Wilde92]. Les développeurs doivent extraire et comprendrel’interdépendance du comportement temporel d’objet, dans le but d’analyser et réarranger soncode interne. Dans plusieurs applications, les objets sont rassemblés dans des groupes pourdonner le service du temps réel afin de répondre à quelques buts. Avec ce groupe, les objetsforment les relations Client-Serveur. De plus, le nombre relativement important et la petitetaille des méthodes dans des programmes orientés objets typiques augmentent le nombre deces relations[Bihari92][Wilde92]. Dans la perspective de l’ordonnanceur rate-monotonic, Gerber et Hong[Gerber97] ontmontré qu’ils peuvent améliorer l’ordonnançabilité en divisant une tâche de programme endeux fragments. Le premier dépend d’un événement observable, et le deuxième concerne lecalcul interne, qui peut être retardé. Cependant, la présente approche traite seulement lesprogrammes monolitiques et procéduraux simples, indépendamment des contraintes desynchronisation introduites en augmentant le nombre de tâches. Afin d’achever l’ordonnançabilité, on propose une approche semi-automatique qui estl’extension de solutions précédentes et qui est adaptée au modèle temps réel objet. D’une 66
  • 11 Conception Du Système De Restructuration Des Programmes Orientés Objets (Java)manière spécifique, quand on trouve un ensemble de tâches surchargé et non ordonnançable,un analyseur d’ordonnancement choisit les tâches appropriées pour les restructurer. On met enœuvre le module de restructuration en faisant appel au concept de l’analyse de dépendance dusystème orienté objet. Par conséquent, notre approche de restructuration est basée sur deux concepts :lestranches de programme et la technique d’ordonnancement à priorité fixe. Les tranches deprogramme, définies en premier lieu par Weiser[Weiser84], sont basées sur l’analyse du fluxde données statique sur le graphe de flux du programme. C’est une technique d’isolation desThreads de calcul dans les programmes. Une tranche de programme consiste en les parties duprogramme qui affectent potentiellement les valeurs calculées par rapport à quelques pointsd’intérêt. Un point d’intérêt de tranche est généralement spécifié par une position dans leprogramme avec un sous ensemble de variables du programme. Par exemple, on peut isolerune tranche par rapport à une instruction critique ou une méthode dans un programme, uneinstruction qui émet une commande à un actionneur ou une instruction d’une alarme dans unetâche de contrôle. Les tranches statiques d’un programme ont été appliquées avec succès dansles outils de programmation pour les langages non orientés objets tels que Pascal[Horwitz90][Ben97], pour le déboggage, le test, ou la maintenance des logiciels. Mais avec quelquesextensions, elles sont toujours efficaces dans le domaine de l’orientéobjet[Larsen96][Lang97][Hang98]. En utilisant le concept des tranches de programme, notre méthode de restructurationpermet d’améliorer l’ordonnançabilité d’un ensemble de tâches de deux façons. D’abord, onrespecte toujours les différentes dépendances dans le code d’une tâche non ordonnançable, ons’assure que les instructions qui affectent l’échéance (fragment temporel) soient exécutées enpremier lieu. Le fragment de code qui correspond au calcul interne (fragment non temporel)peut être différé. De plus, elle permet la décomposition d’une ou plusieurs tâches en soustâches, de telle sorte qu’on puisse utiliser des méthodes d’ordonnancement à priorité fixegénéralisées[Härbour94], qui peuvent augmenter l’ordonnançabilité d’un ensemble de tâches,mieux qu’appliquer l’algorithme rate-monotonic. En restructurant une tâche choisie parmil’ensemble de tâches d’origine, on peut augmenter l’ordonnançabilité totale. On a appliqué notre solution sur les applications temps réel Java, vu qu’il estactuellement le langage le plus utilisé et qui est purement objet, ressemblant au langagepopulaire C++, mais plus simple. En effet, en combinant les conventions spéciales du tempsréel de la machine virtuelle de Java avec les facilités de ce dernier, Java autant qu’un langageobjet pur, permet le traitement d’activités temps réel (ramasse miette, multithread, protection,simplicité et portabilité)[Hamilton96].II- Modèle Temps Réel Objet: Le modèle de calcul uniforme du paradigme orienté objet permet d’avoir une bonnereprésentation des entités du temps réel, du point de vu physique ou logique[Bihari92]. Parexemple, dans un logiciel de contrôle d’un manipulateur, les objets du logiciel représentent lemanipulateur soit même, les actionneurs et les entités conceptuelles du planificateur. Lescontraintes de temps[Das85] peuvent être représentées dans le modèle du temps réel objet, quioffre des constructions au développeur permettant de spécifier les implémentations d’objetsspécifiques et des messages d’efficience et de prévision acceptables[Bihari92][Ish92].II-1- Approches d’ordonnancement: Le problème le plus fondamental et classique dans les systèmes temps réel estl’ordonnancement d’un ensemble de tâches périodiques, qui s’exécutent sur un seulCPU[Gerber97]. Ce modèle peut être décrit par : (1)une tâche est un programme ayant un seulThread (bloc temporel), qui s’exécute indéfiniment avec une périodicité positive, où ce type 67
  • 11 Conception Du Système De Restructuration Des Programmes Orientés Objets (Java)de programme est la construction de bloc commune trouvée dans les applications temps réel,et (2) un ensemble de tâches est une collection de tâches périodiques. Une tâche périodique, notée t, est une séquence infinie d’instances de tâches demandéeavec un taux fixe dans un environnement temps réel. Considérons un ensemble de n tâchespériodiques t1, t2, …, tn. Chaque tâche est caractérisée par trois composantes (Ci, Ti, Di),1<=i<=n. Ci est le temps d’exécution dans le plus pire des cas de la tâche ti (chacune desinstances de tâche a le même taux de calcul). Ti est la période de la tâche. Di est l’échéance dela tâche ti, par lequel elle doit être complétée. Un ordonnanceur temps réel[Klein94] décidequand est ce que chaque tâche requisitionne le processeur. Un traitement théorique del’ordonnancement avec priorité fixe, apparue en 1973, quand Liu et Layland[Liu73] ontintroduit l’algorithme rate-monotonic pour des tâches périodiques et indépendantes. Dans [Härbour94], Harbour et al, a considéré une classe de problèmes plus générale, etfournit une structure pour l’analyse de l’ordonnançabilité dans le contexte de l’algorithmed’ordonnancement avec priorité fixe d’un ensemble de tâches composées de sous tâches, quiont des niveaux de priorité différents. Comparé avec la technique rate-monotonic, il a étédémontré que cette méthode offre une meilleure ordonnançabilité.II-2- Application temps réel en Java: Evidemment, les développeurs temps réel ont besoin de langages orientés objets simplessupportant le développement rapide, la portabilité, la robustesse, la reconfiguration rapide, lasécurité et une haute performance. Java, comme étant un système orienté objet pur, possèdedes caractéristiques avancées telles qu’une efficace fonction de ramasse miettes, lemultithreads et l’absence du type pointeur afin d’améliorer la sécurité[Hamilton96]. Quelques problèmes particuliers du domaine des systèmes temps réel embarqués sontadressés par la conception d’un environnement de programmation temps réel Java. Lesimplémentations temps réel Java sont devenues utiles pour la programmation des applicationstemps réel www distribuées (exemple : gestion de stock et commerce, animation interactive,les jeux, et la téléconférence), et pour l’implémentation d’applications temps réel embarquéesplus traditionnelles (exemple : dans les systèmes de navigation, interface de traitement vocalet graphique, contrôle du trafic aérien, environnement de la réalité virtuelle et les systèmes dedéfense à missile).III- Fragmentation de programmes orientés objets: Dans le but d’avoir des échéances de tâches flexibles, vu que l’ordonnançabilité estaméliorée tant que la flexibilité des échéances augmente, on effectue une transformation sur leprogramme de la tâche, de telle sorte que cette dernière puisse aller au delà de son échéance.On peut procurer cette avantage en ramenant le fragment non temporel à s’exécuter après lefragment temporel. Ensuite, les fragments sont recomposés séquentiellement, afin deconstituer un nouveau programme de la tâche en question, qui est sémantiquement équivalentà celui d’origine. La figure 1.a représente le comportement d’exécution d’une tâche périodique. Lesparties ombrées dans les figures 1.a et 1.b représentent les composants temporels duprogramme de la tâche. Dans la (k+1)ième période, l’exécution de cette tâche va au delà deson échéance et devient, par conséquent, non ordonnançablecas où les instructions temporelles devraient s’achever au bout de la période prescrite,l’exécution de la tâche entière est acceptableIII-1- Représentation des dépendances: 68
  • 11 Conception Du Système De Restructuration Des Programmes Orientés Objets (Java) On calcule un fragment de programme en utilisant le concept de tranche de programme,basé sur la représentation du programme. Les chercheurs ont considéré plusieurs manièrespour la représentation des programmes orientés objets[Larsen96][Lang97][Hang98]. Lescaractéristiques orientées objets, telles que les classes et les objets, l’héritage, lepolymorphisme et la liaison dynamique interviennent dans le développement d’unereprésentation efficace d’un programme orienté objet. Une classe définit les attributs qu’uneinstance d’une classe (objet) va posséder. Les attributs d’une classe consiste en l’instance desvariables qui implémentent l’état de l’objet, et des méthodes modélisant les opérations surl’état de l’objet. Un bon graphe de représentation d’une application orientée objets doit inclure lareprésentation de classes qui peuvent être réutilisées dans la construction de d’autres classes etapplications utilisant ces dernières. Les classe dérivées sont définies à travers l’héritage, quipermet à la classe dérivée d’hériter des attributs provenant de ses classes parentes, de lesétendre, restreindre, redéfinir ou les remplacer en quelque sorte. Tout comme ce que fournitl’héritage en facilitant la réutilisation de code, un bon graphe de représentation pour uneclasse dérivée doit faciliter la réutilisation des informations des classes. Le polymorphisme estune caractéristique importante pour les langages orientés objets qui permet durant l’exécutionle choix d’une des destinations parmi celles de l’ensemble des appels de méthode. Une représentation statique d’un choix dynamique exige que toutes les destinationspossibles doivent être incluses, à moins que le type puisse être déterminé statiquement.Malgré la limite de la visibilité des variables d’une instance d’objet (état), ces variablesd’instance retiennent ses valeurs entre les appels de méthode à l’objet. Une représentation doit compter pour les dépendances des variables des instances entreles appels aux méthodes de l’objet par un programme d’appel, même si les variablesd’instance ne sont pas visibles au programme d’appel. Pour pouvoir le réaliser, on construitun Graphe de Dépendance Etendu du Système (EGDS:Extended System Dependance Graph),basé sur la représentation des différents concepts orientés objets, principalement ceuxproposés dans [Hang98], avec quelques adaptations qu’on introduit, et qui sont nécessairespour notre processus de restructuration.Méthode d’Objet. Contrairement aux travaux décrits dans [Larsen96][Hang98], dans chacunedes méthodes de l’objet, on a besoin de considérer tous les trois types de dépendances dedonnées:flux, sortie et anti-dépendance, car les transformations modifient l’ordre desinstructions. Cela peut être fait directement par un Graphe de Dépendance de Méthode(MDG:Method Dependance Graph): Le MDG est formé de (N,E) avec: Les nœuds N représentent les instructions, i.e., assignation, prédicat de contrôle, appel de méthode, ou une instruction temporisée (telle qu’une entrée ou une sortie). De plus, il y a un nœud particulier « Entry » qui représente la racine de la tâche. Les arcs E, qui sont de deux types: un arc v1 v2, qui indique une dépendance de contrôle entre v1 et v2. De ce fait, soit (1)v1 est un Entry, et v2 n’est pas lié ni à une boucle ou une condition, ou bien, (2) v1 représente un prédicat de contrôle, et v2 est immédiatement dans une boucle ou une condition dont le prédicat est représenté par v1. un arc v1 v2 dénote un flux, une sortie ou une anti-dépendance. Pour cela, un contrôle peut atteindre v2 après v1 via une trajectoire au long de laquelle il n’y a aucune définition d’une variable m : v1 définit m, et v2 l’utilise (dépendance de flux). v2 définit m, et v1 l’utilise (anti-dépendance). v1 et v2 définissent tous les deux m (dépendance de sortie). 69
  • 11 Conception Du Système De Restructuration Des Programmes Orientés Objets (Java) En outre, on traite l’action de construction d’objet (new) comme une instruction d’appel.On la représente par la suite par un nœud Entry, relié par des arcs de dépendance de contrôleaux nœuds représentant ses membres de données.Membres de Données d’Objet. On suppose de plus que les membres d’un objet peuvent êtreaccédés seulement à travers une méthode. Enfin, on traite les membres de données statiquescomme étant des variables globales et les méthodes statiques comme des méthodes globales,parce qu’elles ne s’associent à aucun objet particulier durant l’exécution. Pour pouvoirreprésenter un objet récepteur de message, on poursuit le schéma de Larsen etHorrold[Larsen98]. Un site d’appel contient des nœuds de membres de données «Actual-in»représentant les membres de données qui sont référencés, et des nœuds de membres dedonnées «Actual-out» représentant les membres de données modifiables par une méthodeappelée. Pour pouvoir supporter cette représentation, un nœud «Method Entry» contient lesnœuds de membres de données «Formal-in» représentant les membres de données référencéesdans la méthode, et les nœuds de membres de données «Formal-out» représentant lesmembres de données modifiables dans la méthode. Les nœuds de membres de données«Formal-in» sont libellés par des assignations qui copient la valeur des membres de donnéesd’un objet dans la portée de la méthode au début de cette dernière, et les nœuds des membresde données «Formal-out» sont libellés avec des assignations qui copient la valeur desmembres de données à partir de la portée de la méthode dans l’objet, à la fin de cette dernièreencore. Suivant cette approche, les dépendances de données relatives aux membres dedonnées de la classe dans une méthode sont calculées de la même manière que celles pour uneprocédure [Horwitz90][Hang98].Objets Paramètres. Comme situé dans [Hang98], pour obtenir plus de précision quand unobjet est utilisé comme étant un paramètre, un objet paramètre est représenté comme unarbre : la racine représente l’objet lui même, les fils de la racine représentent les membres dedonnées de l’objet, et les branches de l’arbre représentent les dépendances de données entrel’objet et ses membres de données. Afin de pouvoir calculer des dépendances de données, quand un arbre est utilisé dans lareprésentation d’un objet, les utilisations ou les définitions sont associées aux nœuds desmembres de données.Objet Polymorphique. Un objet polymorphique est représenté par un arbre[Hang94], dont laracine représente cet objet et les fils de la racine représentent les objets de tout type possible.Classe dans la Hiérarchie. Comme dans [Hang94], à travers une hiérarchie d’une classe, ongarde une copie de la représentation pour une méthode, et cette représentation peut êtrepartagée par différentes classes dans cette hiérarchie. Un nœud d’entrée de classe regroupe lesméthodes appartenant à une classe et utilisant ensemble les arcs des relations membres. Pouridentifier la classe d’origine, dans laquelle une méthode à été déclarée, on fait précéder le nomd’une méthode par le nom de la classe d’origine.Construction du ESDG. Comme dans Java, toute méthode ou variable fait partie d’une classe,notons que les méthodes et variables statiques sont en dépendance de contrôle au nœudd’entrée du programme P. Pour la construction du ESDG d’un programme, on poursuit lesétapes suivantes:Etape 1- Construction des Graphes de Dépendance des Méthodes (MDG): 70
  • 11 Conception Du Système De Restructuration Des Programmes Orientés Objets (Java)On construit en premier lieu un MDG pour chaque méthode invoquées d’une manière directeou indirecte dans le programme. La construction est faite d’une manière ascendante (figure 2),suivant la hiérarchie de la classe (une méthode statique va appartenir à la classe spécialecorrespondante à P). Le constructeur de classe est représenté comme une méthode avec lesvariables formelles et effectives correspondantes seulement aux attributs de la classe qui sontréférencées dans le programme de la tâche.Etape 2- Calcul des arcs résumés dans les endroits d’appel:L’endroit d’appel d’une méthode est représenté par (1)un nœud d’entrée, relié par un arc decontrôle au paramètre effectif, (2)les arcs résumés. Ensuite, on relie les MDG à leurs endroitsd’appel correspondants.Etape 3- Construction des arcs de dépendances de données.III-2- Les tranches dans les Systèmes Objets: Nous sommes concernés par les tranches arrières. Pour plus de clarification, et afin depermettre l’extraction de tranches par rapport à une valeur retournée par une méthode, onreformule la définition d’une tranche comme suit : « une tranche d’un programme P parrapport à un point p et une variable ou un appel de méthode m (si m est une variable, elle doitêtre définie ou utilisée au point p), consiste en les instructions et prédicats de P, qui peuventaffecter m au point d’exécution p ». Une paire <m,p>est généralement appelée le critère de latroncature, et la tranche associée est notée P/<m,p>. Horwitz et al[Horwitz90] calculent les tranches interprocédurales en résolvant unproblème d’atteinte de graphe sur le graphe de dépendance du système (SDG). Vu que leESDG qu’on calcule pour un programme orienté objet appartient à une classe du SDG définiepar Horwitz et al, on peut utiliser cette technique pour calculer une tranche, avec une petitemodification. La première passe de l’algorithme de troncature traverse en marche arrière àtravers tous les arcs, à l’exception des arcs «Parameter-out», et marque tous les nœudsatteints. La deuxième passe traverse en marche arrière à partir de tout les nœuds marquésdurant la première passe, à travers tous les arcs, à l’exception des arcs d’appel et «Parameter-in», et marque les nœuds atteints. La tranche est l’union des nœuds marqués durant les deuxpasses. La figure 3 schématise la tranche calculée par rapport au critère <<31>, <b>>, quicorrespond à la ligne 31 dans le programme Java de l’exemple, et la variable b. Enaccomplissant les deux passes, la tranche est formée des nœuds ombrés dans le ESDG. Laligne de numéro 31 indique que l’instruction qui émet (envoie) la variable b à l’actionneur.Suivant l’événement basé paradigme [Hang98], l’échéance de la tâche est placé sur cetteaction de sortie. Par conséquent, on détermine toutes les instructions qui influencent de telleaction pour former le fragment temporel. Le reste des instructions forment le fragment nontemporel, qui sera coller à la fin du temporel, afin d’obtenir un nouveau programme qui estsémantiquement équivalent à celui d’origine.IV- Processus de Restructuration: Après la construction du ESDG suivant la procédure décrite précédemment, ondétermine la tranche par un marquage arrière des nœuds atteints, commençant à partir desnœuds déterminés par le critère de troncature. De plus, on classe les méthodes en deuxcatégories : (1) les méthodes finales qui n’appellent aucune autre méthode, notée F, (2) lesméthodes intermédiaires qui sont appelées par d’autres méthodes et appellent autresméthodes, notée I. Le processus de restructuration consiste en: 71
  • 11 Conception Du Système De Restructuration Des Programmes Orientés Objets (Java) Le calcul du fragment temporel et celui non temporel de chaque méthode. Chaque corps de sous méthode calculé sera inséré dans la classe correspondante. Le calcul du fragment temporel et celui du non temporel du programme P. La disposition du fragment non temporel à la fin du fragment temporel dans le programme P. Comme montré dans la figure 2, et d’une manière ascendante, on accomplit de telprocessus suivant les phases suivantes :Phase1 :Calcul du fragment temporel et non temporel des méthodes finales.Pour chaque méthode dans F :1. A partir du corps de la méthode notée M, supprimer toutes les lignes correspondant aux nœuds non marqués dans le ESDG.2. Construire le corps de la méthode notée MT, qui inclut le reste des instructions. MT :M’s Temporal fragment.3. A partir du corps de la méthode M, supprimer toutes les lignes correspondant aux nœuds marqués dans le ESDG, à l’exception des lignes conditionnelles ou de boucle.4. Supprimer les lignes conditionnelles et de boucle contrôlant un ensemble vide d’instructions.5. Construire le corps de la méthode notée MN, qui inclut le reste des instructions. MN:M’s Non Temporal fragment.Phase2:Calcul des fragments temporel et non temporel des méthodes intermédiaires.Pour chaque méthode dans I, et d’une manière ascendante appliquée sur la hiérarchie del’appel de méthode :1. A partir du corps de la méthode M, supprimer toutes les lignes correspondant aux nœuds non marqués dans le ESDG.2. Si MNi-1 n’est pas vide, remplacer chaque appel de méthode Mi-1 par l’appel de la méthode MTi-1 (i est le numéro du niveau dans la hiérarchie de l’appel de méthode décrit dans la figure 2).3. Construire le corps de la méthode MT, qui inclut le reste des instructions.4. A partir du corps de la méthode M, supprimer toutes les lignes correspondant aux nœuds marqués dans le ESDG, à l’exception des lignes d’appel, conditionnelles ou de boucle.5. Si MNi-1 est vide, supprimer les lignes d’appel.6. Supprimer les lignes d’appel et de condition qui contrôlent un ensemble vide d’instructions.7. Remplacer chaque appel de méthode Mi-1 par l’appel de la méthode MNi-1.8. Construire le corps de méthode MN, contenant le reste des instructions. La première phase calcule les fragments temporel et non temporel des méthodes finales.Elle introduit le schéma de l’appel de méthode (figure 2a), et produit pour chaque méthode Mdans F, son fragment temporel (MT) et son fragment non temporel (MN). Une fois les sousméthodes MT et MN de la méthode M sont construites, on insert MT et MN dans leur classeafin de remplacer la méthode M. Quand la classe correspondante est une superclasse d’uneautre classe, on insert les sous méthodes dans la classe de base sans suppression de la méthoded’origine.Phase3:Restructuration de classe.Pour chaque méthode M dans F et I :1. Si MN n’est pas identique à M et est non vide, insérer le corps de MN dans la classe d’origine de M. 72
  • 11 Conception Du Système De Restructuration Des Programmes Orientés Objets (Java)2. Si MT n’est pas identique à M et est non vide, insérer le corps de MT dans la classe d’origine de M.Phase4:Restructuration de P (calcul des fragments temporel et non temporel de P).1. A partir du corps du programme P, supprimer toutes les lignes correspondant aux nœuds non marqués dans le ESDG.2. Si MN n’est pas vide, remplacer chaque appel de méthode M par l’appel de la méthode MT.3. Le reste des instructions du fragment temporel de P est noté PT.4. A partir du corps du programme P, supprimer toutes les lignes correspondant aux nœuds marqués dans le ESDG, à l’exception des lignes de condition, boucle ou d’appel.5. Supprimer les lignes d’appel et de condition qui contrôlent un ensemble vide d’instructions.6. Si MN est vide, supprimer les lignes d’appel.7. Remplacer tout appel de méthode M par l’appel de la méthode MN.8. Le reste des instructions du fragment non temporel de P est noté PN.9. Placer PN à la fin de PT.Enfin, après le calcul des deux fragments de P, on obtient notre tâche transformée, en plaçantle fragment non temporel à la fin du fragment temporel (figure 3), via une compositionséquentielle. Programme P Méthode M1 -- M2+ Méthode M2 M1+ -- -- -- -- M2+ -- M1+ -- -- -- -- M1+ -- a) Schéma d’appel de méthode avant restructuration Programme P Méthode MT1 -- -- MT2+ -- -- -- -- MT1+ MT2+ -- MT1+ Méthode MT2 -- Méthode MN1 MN1+IV- Exemple d’application : -- Méthode MN2 -- SoitMN1+ -- le programme suivant écrit en Java : MN2+ -- -- MN2+ -- -- b) Schéma d’appel de méthode après restructuration 73 Figure 2 : Schéma de restructuration
  • 11 Conception Du Système De Restructuration Des Programmes Orientés Objets (Java) public class plan{ static float t, p ;//Temperat & Pression float a, b ; static void sense(){….}//(t, p) (a, b) public void vm(){ a=a+b ;} public void mbi(int i){ b=b+i ; } public void mbvm(){ if(a>0){ vm() ;} b=b+1 ; } //envoi de commande à l’actionneur static void signal(float com){} //programme main dans le thread public class planMvt extends Thread{ int delay ; planMvt(int dealy){ this.dealy=delay ; start() ;} public void run(){ while (true){ new sense() ;//lecture à partir du capteur plan o = new plan() ; plan ba =new plan() ; ba.mbvm() ; o.mbi(1) ; ba.mbi(1) ; ba.signal(b) ;//émission à l’actionneur sleep(delay) ; }}}//création du thread new planMvt(60) ;//60 est la période de la tâche Programme Temps Réel en Java 74
  • 11 Conception Du Système De Restructuration Des Programmes Orientés Objets (Java) Il s’agit d’un programme concernant une application temps réel développée sous Java. Nous sommes maintenant concernés par la restructuration de ce code et générer un autreplus sûr en exécution (générer une tâche ordonnancée). Les étapes qu’on va suivre sont les suivantes, une fois qu’on est certain de la correctiondu code en entrée: Génération du code instrumenté. Génération du GDS de notre système orienté objet. Extraction de la tranche temporelle et par conséquent l’obtention du fragment du code temporel. Le code restant est le fragment non temporel.Génération du code restructuré par composition des deux fragments obtenus de l’étapeprécédente, et en déplacement le fragment temps contraint au début du code à générer. Notezque la sémantique est préservée.Phase1:Génération du code instrumenté.En voici le programme instrumenté correspondant à celui présenté ci-dessus. Code Instrumenté de la Tâche 1 public class plan{ 2 static float t, p ;//Temperat & Pression 3 float a, b ; 4 static void sense(){….}//(t, p) (a, b) 5 public void vm(){ 6 a=a+b ;} 7 public void mbi(int i){ 8 b=b+i ; 9 } 10 public void mbvm(){ 11 if(a>0){ 12 vm() ;} 13 b=b+1 ; 14 } 15 //envoi de commande à l’actionneur 16 static void signal(float com){} 17 //programme main dans le thread 18 public class planMvt extends Thread{ 19 int delay ; 20 planMvt(int dealy){ 21 this.dealy=delay ; 22 start() ;} 23 public void run(){ 24 while (true){ 25 new sense() ;//lecture à partir du capteur 26 plan o = new plan() ; 27 plan ba =new plan() ; 28 ba.mbvm() ; 29 o.mbi(1) ; 30 ba.mbi(1) ; 31 ba.signal(b) ;//émission à l’actionneur 32 sleep(delay) ; 33 }}}//création du thread 75 34 new planMvt(60) ;//60 est la période de la tâche
  • 11 Conception Du Système De Restructuration Des Programmes Orientés Objets (Java) Phase2:Génération du GDS. En voici le GDS de notre application temps réel et orientée objet. planMvt plan o plan ba sense() ba.mbvm p t p t F1-out F2-out a b b a ba.signal() ba.mbi(i) F1-in mbvm() () A3-in b b b b o.mbi(1) F2-in a>0 b=b+1 F2-out F1-outA3-in b b mbi(i) vm() F3-in F2-in F2-out A1-in A2-in A1-out b=b+i vm() Flux de contrôle F1-in F2-in a=a+b F1-out Flux de données Arcs d’appel Arcs résumés Génération du GDS 76
  • 11 Conception Du Système De Restructuration Des Programmes Orientés Objets (Java) Phase3: Extraction des tranches (Recherche du fragment temporel). En appliquant l’algorithme de troncature sur ce GDS orienté objet, par rapport à l’instruction ba.signal(b) et en considérant la variable b, on trouve ce qui suit: planMvt plan o plan ba sense() ba.mbvm p t p t F1-out F2-out a b b a ba.signal() ba.mbi(i) F1-in mbvm() A3-in b b b b o.mbi(1) F2-in a>0 b=b+1 F2-out F1-outA3-in b b mbi(i) vm() F3-in F2-in F2-out A1-in A2-in A1-out b=b+i vm() F1-in F2-in a=a+b F1-out Extraction de Tranche 77
  • 11 Conception Du Système De Restructuration Des Programmes Orientés Objets (Java) Les nœuds hachurés représentent la tranche extraite à partir de ce GDS. A partir de cettetranche , on peut extraire le fragment temporel, qui doit être exécuté en premier lieu, et qui estindépendant du reste du programme. On note, dans ce qui concerne l’extraction d’une tranche orientée objet, que La tranche ne concerne que l’objet dans lequel il y avait l’instruction du critère de troncature, même s’il existe d’arcs reliant des objets différents appelant la même méthode. On peut expliquer ce résultat par la caractéristique d’encapsulation dans le concept de l’orienté objet. Les concepts de l’extraction des tranches connues dans les programmes multiprocéduraux se conservent pour le cas de l’orienté objet (passage de paramètres, les appels …etc.). Une instruction d’instanciation dans le programme source implique l’existence d’un nœud d’instanciation d’un objet , ayant des arcs de contrôle vers sa partie statique(attributs). Les éléments de cette partie ne feront partie que d’un flux de données ou d’une paramétrisation.Phase4: Extraction du Fragment Temporel et du Fragment Non Temporel. Le fragment temporel est constitué des instructions du programme source (partie main),qui s’est trouvée dans la tranche extraite.Le reste des instructions constitue le fragment non temporel. Dans le code instrumenté, les instructions temporelles (éléments du fragment temporel)sont écrites en gras.Phase5: Génération du code restructuré plus sûr en exécution.On génère le nouveau code comme suit : Conservation de la partie déclaration et de toute définition externe. Dans la partie main, on met en premier lieu le fragment temporel, suivi du fragment non temporel.Par cela, on parvient à produire un code restructuré d’une application temps réel orientéeobjet, dont la probabilité de commettre une erreur d’exécution, en cas de commutation, soitminimale, vu que la partie critique, qui dépend du facteur temps, va s’exécuter dès lelancement de notre thread. Programme Restructuré de la Tâche1 public class plan{ 19 planMvt(int dealy){2 static float t, p ; 20 this.dealy=delay ;3 float a, b ; 21 start() ;}4 static void sense(){….} 22 public void run(){5 public void vm(){ 23 while (true){6 a=a+b ;} 24 new sense() ;7 public void mbi(int i){ 25 plan ba =new plan() ;8 b=b+i ; 26 ba.mbvmT() ;9 } 27 ba.mbi(1) ;10 //mbvm est subdivisée en deux fragments 28 ba.signal(b) ;11 public void mbvmT(){//fragm temporel 29 plan o = new plan() ;12 b=b+1 ;} 30 o.mbi(1) ;13 public void mbvmN(){//non temporel 31 ba.mbvmN() ;14 if(a>0){ 32 sleep(delay) ;15 vm() ;}} 33 }}}//création du thread16 static void signal(float com){}17 public class planMvt extends Thread{ 34 new planMvt(60) ;//60 est la période de la18 int delay ; tâche 78
  • 11 Conception Du Système De Restructuration Des Programmes Orientés Objets (Java)V- Conclusion: Dans notre modèle, on a présenté une approche étendue pour améliorerl’ordonnançabilité des applications temps réel. Elle est basée sur deux concepts : la tranched’objet et la théorie de l’ordonnancement avec priorité fixe. Par conséquent, on a montréqu’on peut augmenter l’ordonnançabilité à priorité fixe d’une tâche de deux manières :premièrement, on décompose le programme d’une tâche non ordonnançable en deuxfragments, ensuite on placera le fragment non temporel après le fragment temporel dans lenouveau code de la tâche. Et en deuxième lieu, par décomposition d’une ou de plusieurstâches en sous tâches qui sont exécutées à niveaux de priorités modifiables, on peutaugmenter l’ordonnançabilité totale au delà de celle fournie par l’algorithmed’ordonnancement rate-monotonic simple. Par conséquent, appliquée aux programmes temps réels orientés objets, la naturecomplémentaire de notre approche de restructuration pour l’analyse de l’ordonnançabilité,sera une base pour d’autres outils qui adoptent la prévision temporelle sans sacrifier debonnes pratiques en ingénierie. Ces deux techniques constitue une partie du processus dedéveloppement de logiciels temps réel. Pour terminer sur les systèmes temps réel, on a utilisé des constructions qui sont trèsutilisées dans les langages de programmation temps réel. A présent, nous sommes entraind’implémenter notre technique de restructuration pour Java, pour l’expérimenter avec desapplications utiles dans le domaine du temps réel. 79