• Aucun résultat trouvé

Comme le montre la figure 46, il existe un intergiciel «minimal» qui présente un ensemble d’inter-faces qui permettent de mettre en œuvre l’application TR2E.

Les travaux menés par [Zal08] ont montré que si l’architecture de l’intergiciel minimal était statique, une partie de celle-ci pouvait être configurée pour correspondre au mieux aux besoins de l’application en exploitant sa spécification AADL. En effet, si les protocoles de communications mis en œuvre par l’intergiciel sont eux complètement indépendants de l’application, ce n’est pas le cas des routines d’envoi de messages.

Intergiciel Minimal Spécification

AADL Application TR²E

Configuration Spécification Services canoniques Scenarii de mise en oeuvre Spécification formelle Intergiciel Minimal Opérations de manipulation (formelles)

FIGURE46 – Relations entre l’exécutif AADL, sa spécification formelle et la spécification de l’applica-tion TR2E

L’intergiciel propose donc une bibliothèque de services mis en œuvre par l’application, ainsi que différents points de configuration pour répondre à ses besoins.

Nous proposons une approche identique pour la spécification formelle de l’exécutif AADL : elle pro-pose une bibliothèque de service (ceux de l’intergiciel), ainsi que des points de configuration (semblables à ceux de l’intergiciel).

Procéder à la vérification formelle de l’exécutif se fera en plusieurs étapes, comme nous l’avons mentionné :

1. la spécification formelle de l’intergiciel minimal, proposant une bibliothèque de services, doit être cohérente.

2. la spécification formelle de l’intergiciel, une fois configurée en accord avec la spécification AADL, doit être cohérente : le respect d’invariants exprimés sur la spécification générique par la spéci-fication configurée montre que la configuration élaborée par l’utilisateur peut être supportée par l’exécutif AADL.

3. des scenarii de mise en œuvre des services de la spécification formelle peuvent être élaborés, pour vérifier certaines contraintes dans le contexte particulier de l’application.

5.2 Z : une notation formelle pour la spécification

Cette notation a été proposée par Jean-Raymond Abrial et son équipe du «Programming Research Group», au laboratoire d’informatique de l’Université d’Oxford (OUCL), dans les années 70. Elle tire son nom de la théorie des ensembles de Zermelo-Frankel [SAEF68]

J-R. Abrial la fait apparaître pour la première fois dans «Data Semantics» [Abr74] en 1974. Elle est l’objet de travaux au cours des années suivantes, et il présente la notation Z avec l’aide de S. Schuman et de B. Meyer dans [ASM80].

Cette notation définit rigoureusement des opérateurs logiques, des opérations ensemblistes, des types complexes et leur combinaison, et la notion d’algèbre sur les schémas («schema-calculus»), sur lesquels nous allons revenir dans ce chapitre.

Un premier effort de standardisation a été mené par M. Spivey [Spi89a] en 1989. Il a ainsi proposé un manuel de référence, y présentant les notions mathématiques à la base de cette notation (et donc utile pour faire de la preuve), le langage en lui-même, ainsi que les outils mathématiques mis à la disposition de la notation. Cela a été fait en utilisant des exemples et des tutoriels, aidant à la compréhension du lecteur. Plus récemment, en 2002, la notation Z a été standardisée selon la norme ISO/IEC [13502].

Nous allons présenter les différents éléments d’une spécification Z, de façon à clarifier la lecture de la suite de ce chapitre.

5.2.1 Syntaxe

La syntaxe de la notation Z repose sur la notion de sections et de paragraphes. Une spécification peut contenir plusieurs sections (introduisant une hiérarchie nommée). Chaque section contient des pa-ragraphes. On peut faire une spécification dite «anonyme» en utilisant directement un ensemble de para-graphes pour construire la spécification.

Chaque paragraphe représente une entité Z de la spécification, qui peut correspondre à : – Des types de base,

– Un axiome,

– Un «schéma» (générique ou non), – Une définition d’opérateur,

– Un type dit «libre» (ou FreeType, par opposition aux types de base), – Une conjonction.

Types de base : On utilise la notation suivante pour définir un type de base : [TYPE1, TYPE2]

Un type est, sémantiquement, un ensemble d’objets non vide. Cet ensemble peut être aussi bien fini qu’infini. La représentation réelle d’un objet de l’ensemble n’est pas considérée, car cela permet de spécifier rigoureusement les contraintes d’un système quelle que soit son implantation : un objet est donc vu comme une entité typée et abstraite.

La notion de type permet, lors de l’analyse d’une expression, de savoir si elle est cohérente. Ainsi, une expression de la forme :

(1, 2) = {1, 2, 3}

n’est pas cohérente, car le membre gauche est une paire ordonnée, tandis que le membre droit est un ensemble. Ce processus de vérification de type est appliqué pour toutes les expressions de la spécification. Les axiomes : Ils sont notés de la façon suivante4:

Partie Declarative

Predicats

Cette construction permet d’introduire des variables globales dans la spécification. En utilisant la partie «Prédicats», on peut éventuellement en contraindre les valeurs (les prédicats étant optionnels).

5.2. Z : une notation formelle pour la spécification

Les schémas : Ils se représentent ainsi : NomDuSchema

Declarations

Predicats

Ils permettent de regrouper structurellement des variables dans un espace d’état, à la manière des approches orientées objet où les classes permettent de regrouper les attributs d’un même élément.

Un schéma est défini comme l’ensemble des liaisons, ou bindings satisfaisant l’ensemble des pré-dicats de la partie «Prépré-dicats». Il existe une relation de conjonction implicite entre tous les prépré-dicats présents dans un schéma.

Définition 5.1 (Binding) Fonction finie associant des valeurs à des identifiants (noms). Par exemple, considérant le schéma suivant :

S1 a, b : Z a≥ 0 b≤ 4

Le binding h| a == 0, b == 0 |i est un des bindings de S1.

Il est à noter qu’un schéma peut être paramétré (dépendant d’un ou plusieurs types) : NomDuSchema[Parametres]

Declarations

Predicats

L’opérateur θ permet d’écrire des expressions de construction de bindings. L’expression θS, où S est nécessairement un schéma, produit les associations entre les variables de S et leur valeurs respectives.

On l’utilise classiquement dans des expressions comme θS = θS, permettant de spécifier que dans les bindings θS et θS:

– S et S’ ont le même ensemble de variables ;

– quelles que soient les variable de S, celles de S’ portent le même nom (à la décoration près) et sont associées à la même valeur.

Les types «libres» : Ils permettent de définir des types plus complexes, à la manière d’une BNF (Backus-Naur Form[Bac59]) :

NomDuType::= Branche1 | ... | BrancheN Branche1 ::= NomDeLaBranche[hhExpressionii]

On peut par exemple exprimer un type «arbre binaire dont les feuilles sont des entiers» comme suit : ArbreBin::= branchehhArbreBin × ArbreBinii | feuillehhZii

5.2.2 Systèmes séquentiels : opérations, compositions

On peut définir différentes opérations accédant à l’état des schémas précédemment décrits. Nous introduisons la définition suivante :

Définition 5.2

(Précondition) Conditions à satisfaire pour que l’opération puisse être appliquée.

(Postcondition) Modifications apportées à l’espace d’états accédé par l’opération, résultant de son application.

Les opérations sur les schémas sont elles-mêmes définies comme des schémas, liant par des relations les états dits «pre» d’un schéma S (avant application de l’opération) à ses états «post» (après application de l’opération).

Un premier ensemble de prédicats définit les préconditions de l’opération (mettant en jeu les états «pre» de S), tandis qu’un second définit ses postconditions (mettant en jeu les états «post» de S). Par convention en Z, on note l’état «post» de S en décorant S avec une apostrophe : S’. Ce schéma S’ est le schéma S dont les variables sont décorées (notées a’ et b’, toujours par convention).

Ces schémas-opération peuvent avoir des paramètres en entrée et en sortie. Les entrées sont des variables postfixées par un point d’interrogation «?», et les sorties sont notées comme des variables postfixées d’un point d’exclamation «!».

Le schéma suivant illustre cette notation : Operation ∆S i? : Z i? ∈ N (1) a = a + i? (2) b = if i? ≤ 4 then i? else b (3)

∆ (resp. Ξ) permet d’indiquer si l’opération modifie (resp. laisse inchangé) l’espace d’état défini par le schéma S : nous pouvons établir un parallèle avec les conventions de nommage des langages orientés objets, où les setters (resp. les getters) modifient (resp. consultent) la classe à laquelle ils accèdent.

Le prédicat (1) est la précondition de l’opération : elle n’est applicable que si i? ∈ N. Z permet d’accéder aux préconditions d’un schéma avec l’opérateur unaire pre . Définition 5.3 (Précondition) [Spi89b]

Soit S un schéma, x 1, ..., x

nles composants de S qui sont décorés d’une apostrophe, et y1!, ..., yn! les composants de S qui sont décorés d’un point d’exclamation!, alors le schéma pre S est produit en cachant ces variables de S :

pre S = S \ (x 1, ..., x

n, y1!, ..., yn!)

Il contient uniquement les composants de S correspondant à l’état avant opération et aux variables d’entrée.

Ici, nous avons : pre Operation = (i? ∈ N).

Les prédicats (2) et (3) sont les postconditions de l’opération, mettant en jeu les variables de l’état «post» de S (a, b).

5.2. Z : une notation formelle pour la spécification

Séquençage et composition : La notation Z permet le séquençage de schémas-opération, afin de définir des séquences d’opérations complexes. Ceci est réalisé en introduisant l’opérateur ’o

9’, comparable à celui des langages de script comme Shell sous Unix :

OpSeq= Op1b o 9...o

9OpN

Imaginons que ces opérations modifient l’état d’un schéma S. Alors, l’état de S résultant de Op1 (donc «post») devient l’état avant modification de Op2 (donc son état «pre»). Ceci est masqué par un mécanisme de renommage ; pour deux opérations, par exemple, cela revient à :

Op1 S(pre) S′′(post) Op2 S′′(pre) S(post) Alors OpSeq S(pre) S(post)

On voit que le mécanisme de renommage (S” au lieu de S’ dans Op1, S” au lieu de S dans Op2) est transparent.

Comme pour les langages de script comme Shell, il existe un opérateur permettant de combiner les schémas opérations en indiquant que le résultat d’une commande est l’entrée de la suivante (piping). En Shell, cet opérateur est ’|’, tandis qu’en Z, il s’agit de >> :

OpPiping= Op1>>...>>OpNb

Dans ce cas, les mécanismes mis en place sont les mêmes que précédemment, sauf qu’en plus, si un schéma en amont dans la séquence a une variable en sortie (x!), et que le suivant a une variable en entrée de même nom (x?), alors ces deux variables doivent être de même type : la variable x! sera en effet prise comme variable d’entrée dans le second schéma opération.

Le passage de paramètres en Z se fait en utilisant leur nom, et non leur position comme dans les approches classiques de langage de programmation.

Avec Z, nous ne pouvons donc en théorie que spécifier des systèmes séquentiels. Il est cependant possible de spécifier des systèmes concurrents (comme le montre [Eva94]). Dans la spécification en Z de tels systèmes, les canaux de communication, les processus, les ressources partagées sont spécifiés comme des espaces d’états, modifiés par les opérations y accédant (envoi ou réception de messages, écriture ou lecture dans un buffer).

Nous nous intéressons dans le cadre de nos travaux à la spécification de l’intergiciel PolyORB. Les travaux de [Hug05] ont montré que la quasi-totalité des éléments de PolyORB peuvent interagir en utilisant uniquement des mutex. Seule la partie noyau de l’intergiciel est plus complexe : comme elle a été fait l’objet d’analyses lors de sa modélisation en réseaux de Petri, nous sommes en mesure de dire que la notation Z offre donc tous les mécanismes dont nous avons besoin pour l’architecture que nous spécifions, ainsi que pour les propriétés que nous souhaitons vérifier (respect d’invariants, composition d’interfaces).

5.2.3 Outils

Il existe plusieurs outils permettant d’exploiter une spécification en notation Z. Les outils historiques sont FuZZ [Spi] et Z/Eves [MS97]. Ce sont ceux que nous avons utilisés dans le cadre de nos travaux. Nous allons les présenter ici.

Une spécification Z est la plupart du temps écrite en LATEX : les outils permettant d’analyser une spécification prennent donc en entrée un fichier .tex.

Depuis le standard de fait écrit par J. M. Spivey jusqu’à la norme ISO/IEC, les commandes LATEX sont standardisées, de façon à produire une spécification qui respecte la notation (symboles, schémas). FuZZ : vérificateur de types et de cohérence

Introduit par J. M. Spivey, cet outil permet de vérifier la cohérence de typage et de syntaxe d’une spécification. Il est utile pour une première phase de vérification de la spécification. On peut y mélanger spécification formelle et texte explicatif en langage naturel : FuZZ ne prendra en compte que les éléments Z (à l’aide des commandes LATEX déjà mentionnées).

Z/Eves : un prouveur semi-automatique

Z/Eves est en plus un prouveur : il permet d’écrire des théorèmes, sous forme de prédicats et portant sur tout ou partie de la spécification, et de les vérifier. Ce processus de vérification étant souvent com-plexe, Z/Eves n’est pas un prouveur complètement automatisé : il requiert l’intervention d’experts pour le guider dans le cheminement de la preuve (utilisation de théorèmes et axiomes annexes, désambiguïsation de certains prédicats, restriction de domaines de fonctions ou d’ensembles, etc.). Plusieurs mécanismes sont fournis, comme la réécriture sous forme canonique de prédicats et leur simplification par réduction, réécriture ou réarrangement de prédicats.

5.2.4 Discussion

Un des avantages de Z est la façon dont les invariants sont utilisés tout le long de la spécification. Typiquement, dans une spécification Z, l’auteur précise au départ un état abstrait, contraint par de forts invariants. Puis, il spécifie des opérations qui accèdent à cet état en le modifiant ou en le consultant. Elles doivent respecter les invariants spécifiés, et peuvent produire des effets de bord (paramètres en sortie).

L’utilisation de Z permet de faciliter la spécification d’un système en utilisant différentes vues : une vue locale à chaque acteur, une vue opératoire concernant deux acteurs : la notation permet de moduler et de combiner très facilement des éléments de spécification.