Introduction à l’outil Spin et au langage Promela
Module SDSC Institut Galilée Master 2 PLS
Page web : http://lipn.fr/~rodriguez/teach/sdsc/2015-16/
Enseignant : César Rodríguez
Transparents : préparés par Sami Evangelista, modifiés par César Rodríguez
Présentation de l’outil Spin
2/27Ï
logiciel open source développé initialement par Bell Labs
Ï
permet d’analyser formellement des programmes concurrents
Ï
langage de description : promela (process meta language)
Ï
propriétés analysables : accessibilité, temporelles
Ï
page web : http://spinroot.com/spin/whatispin.html
Ï
cours en ligne avec plus d’informations :
http://lipn.univ-paris13.fr/~petrucci/poly_spin.ps.gz
Plan
3/27Le langage Promela
Utilisation de Spin
Structure d’un programme Promela
4/27Un programme Promela est constitué d’un ensemble de processus.
Ï
Chaque processus est donné par une déclaration proctype .
Ï
Spin transforme chaque proctype vers un automate.
Deux mécanismes de synchronisation entre processus :
Ï
Les variables globales (déclarées hors processus).
Ï
Les canaux de communication permettant l’échange de messages entre
processus.
Structure d’un programme Promela — Exemple
5/27Éléments de base du langage
6/27Ï
beaucoup de points communs avec le C :
Ï le “ ;” pour terminer les instructions
Ï la déclaration des variables
Ï les types de base : int, short, byte, bool
Ï les tableaux
Ï les affectations
Ï le printf
Ï
Mais on ne retrouve pas les instructions de contrôle (if, for, . . . ) du C.
Exemple : i n t i = 1 0 ; short s [ 1 0 ] ; i ++;
s [ 2 ] = 4 ;
p r i n t f ( " i ␣=␣%d␣ e t ␣ s [ 2 ] ␣=␣%d\ n" , i , s [ 2 ] ) ;
Déclaration des processus
7/27proctype p r o c ( t y p e A r g 1 a r g 1 ; . . . ; typeArgN argN ) { /∗ code du processus ∗/
}
Remarques :
Ï
Un processus peut recevoir des arguments à sa création.
Ï
Attention, on utilise ; au lieu de , pour la déclaration d’arguments
Ï
Un processus peut être créé :
Ï statiquement : à l’initialisation du programme (mot-cléactive)
Ï dynamiquement : avec une instructionrunexécutée par un autre processus
Le processus init
8/27i n i t {
/∗ code du processus i n i t ∗/
}
Remarques :
Ï
Le processus init (facultatif) est créé à l’initialisation du programme.
Ï
On l’utilise généralement pour
Ï initialiser des variables globales
Ï et lancer d’autres processus.
Processus créés statiquement
9/27Ï
On les déclare avec le mot-clé active .
Ï
On peut déclarer N processus.
Ï
Les arguments prennent alors une valeur par défaut.
Ï Exemple : 0 pour les arguments de type int.
active [ N ] proctype p r o c ( t y p e A r g 1 a r g 1 ; . . . , typeArgN argN ) { /∗ code du processus ∗/
}
Processus créés dynamiquement
10/27Ï
On les lance avec l’instruction run .
Ï
On doit lui passer tous les arguments déclarés pour le processus.
proctype p r o c ( t y p e A r g 1 a r g 1 ; . . . ; typeArgN argN ) { /∗ code du processus ∗/
} . . .
run p r o c ( x1 , . . . , xN )
. . .
Les processus — Exemple
11/27active [ 2 ] proctype s t a t ( ) { p r i n t f ( " s t a t i q u e \ n" ) ; }
proctype dyn ( i n t x ; i n t y ) {
p r i n t f ( " d y n a m iq u e ␣ : ␣(%d,%d ) \ n " , x , y ) ; }
i n i t {
run dyn ( 1 , 2 ) ; run dyn ( 3 , 4 ) ; }
Simulation du programme :
$ s p i n p r o g . pml
d y n a m i q u e : (1 ,2) s t a t i q u e
s t a t i q u e
d y n a m i q u e : (3 ,4)
Les canaux de communication
12/27Ï
Les canaux sont utilisés par les processus pour s’échanger des messages.
Ï
Il faut se les représenter comme des files FIFO de messages.
Ï
Les messages stockés dans les canaux sont typés.
Ï
Déclaration d’un canal c de N messages contenant des N-uplets.
chan c = [ N ] of { t y p e 1 , . . . , typeN }
Ï
Bonne pratique : mettre un nom symbolique (un mtype ) dans le type des messages pour pouvoir distinguer les messages.
Exemple :
mtype = { r e q u e t e , r e p o n s e , e r r e u r }
chan c = [ 1 ] of { mtype , i n t }
Réception/émission sur un canal
13/27c a n a l ! d o n n e e s /∗ é mission ∗/
c a n a l ? d o n n e e s /∗ r é ception ∗/
Remarques :
Ï
Le récepteur est bloqué si le canal est vide (il attend un message).
Ï
L’émetteur est bloqué si le canal est plein (il attend qu’il se vide).
Ï
Pour un rendez-vous (canal de taille 0) émetteur et récepteur doivent être simultanèment sur les instructions d’émission.
Ï
Côté récepteur :
Ï On affecte aux variables apparaissant après le ’ ?’ les valeurs contenues dans le message.
Ï Si des constantes apparaissent dans les données le message reçu devra contenir ces valeurs (sinon le processus sera bloqué).
Exemple :
c ? i ; /∗ j ’ attends un e n t i e r que j e stocke dans i ∗/
c ? 5 ; /∗ j ’ attends l ’ e n t i e r 5 ∗/
Réception/émission sur un canal — Exemple
14/27chan c = [ 0 ] of { int , i n t } ; active proctype p ( ) {
i n t x , y ;
c ! 1 0 , 1 2 ; c ? x , y ; /∗ p envoie puis re co i t ∗/
p r i n t f ( "p␣ : ␣ j ’ a i ␣ r e c u ␣(%d , ␣%d ) \ n" , x , y ) ; }
active proctype q ( ) { i n t x , y ;
c ? x , y ; c ! 1 7 , 4 4 ; /∗ q re co i t puis envoie ∗/
p r i n t f ( "q␣ : ␣ j ’ a i ␣ r e c u ␣(%d , ␣%d ) \ n" , x , y ) ; }
Simulation du programme :
$ s p i n t e s t . pml
q : j ’ ai r e c u (10 , 12) p : j ’ ai r e c u (17 , 44) 2 p r o c e s s e s c r e a t e d
Expressions = instructions (bloquantes)
15/27A différence du C, chaque expression Promela est aussi une instruction : i = 3 ; /∗ affectation , ne bloque jamais ∗/
i == 3 ; /∗ exé cution bloquée jusqu ’ à que i s o i t 3 ∗/
i < 4 | | t a b [ 7 ] == 4 /∗ s i t u a t i o n analogue ∗/
p r i n t f ( " . . . " ) ; /∗ ne bloque pas (en p r i n c i p e ) ∗/
Ï
Le processus est bloqué tant qu’une condition n’est pas réalisée.
Ï
Dès que la condition se réalise (grâce à l’action d’un autre processus) il peut continuer à exécuter des instructions.
Les opérations sur les canaux peuvent aussi bloquer l’exécution :
Ï
can ! var bloque le processus si can est plein
Ï
can ? var bloque le processus si can est vide
Ï
can ? 5 bloque le processus si can ne contient pas l’entier 5
Instructions bloquantes — Exemple
16/27Séparateurs d’instructions
17/27Ï
On sépare les instructions par des ; ou des
−>
Ï
Tous les deux ont exactement la même sémantique , mais :
Ï −> souvent après une expression pouvant bloquer le processus
Ï ; souvent après une instruction ne pouvant pas bloquer le processus
Ï
Ceci améliore la lisibilité du code.
Exemple :
( p o r t e F e r m e e == 1 )
−> a s c e n c e u r D e m a r r e = 1 ; e t a g e ++
Ï
Dès que la condition se réalise (grâce à l’action d’un autre processus) il
peut continuer à exécuter des instructions.
L’instruction if
18/27i f
: : a l t e r n a t i v e 1 . . . : : a l t e r n a t i v e N
: : e l s e
−> a l t e r n a t i v e E l s e f i
1. Évalue les alternatives 1 à N dont la garde est exécutable.
Ï (La garde est la première instruction de chaque alternative.)
2. Sélectionne de manière indéterministe une alternative parmi celles-ci et exécute cette alternative.
3. Exécute alternativeElse si aucune des gardes n’est exécutable.
4. Si aucune des gardes n’est exécutable et qu’il n’y a pas de else, le processus est bloqué.
Ï Il pourra s’exécuter si une des gardes devient exécutable (ex : en cas de réception d’un message).
B
L’ordre des alternatives n’a pas d’importance :
Ï Les gardes seront toutes évaluées.
Ï On n’exécute pas forcément la première alternative dont la garde est vraie.
L’instruction if — Exemple
19/27i f
/∗ branche exé cutable sur r é ception d ’ un message de type msg contenant une valeur i sur l e canal c ∗/
: : c ?msg , i
−> . . .
/∗ branche exé cutable sur r é ception d ’ un message de type ack contenant une valeur i sur l e canal c ∗/
: : c ? ack , i
−> . . .
/∗ branche exé cutable s i l a v a r i a b l e k vaut 1 ∗/
: : k == 1
−> . . .
/∗ branche exé cutable s i aucune autre ne l ’ est ∗/
: : e l s e
−> . . .
f i
L’instruction do
20/27do
: : a l t e r n a t i v e 1 . . . : : a l t e r n a t i v e N
: : e l s e
−> a l t e r n a t i v e E l s e od
Ï
Même sémantique que le if mais le bloc do est réexécuté après l’exécution d’une des branches.
Ï
Par défaut, on ne sort jamais du do : il faut pour cela placer une
instruction break dans une des branches.
L’instruction do — Exemple
21/27/∗ on f a i t l a somme de dix e n t i e r s r é ceptionn é s sur l e canal c et on termine ∗/
i = 0 ; y = 0 ; do
: : i < 10
−>
c ? x ;
y = y + x ; i = i + 1 : : i == 10
−>
break
od
Les assertions
22/27a s s e r t ( c o n d i t i o n ) ;
Ï
Si la condition n’est pas vérifiée le programme s’arrête.
Exemple :
byte s t a t e = 1 ;
active proctype A ( ) {
( s t a t e == 1)
−> s t a t e = s t a t e + 1 ; a s s e r t ( s t a t e == 2 )
}
active proctype B ( ) {
( s t a t e == 1 )
−> s t a t e = s t a t e
−1 ; a s s e r t ( s t a t e == 0 )
}
Plan
23/27Le langage Promela
Utilisation de Spin
Spin en mode simulation
24/27On appelle spin en lui donnant le programme à simuler.
$ s p i n p r o g r a m m e . pml
Ï
En mode simulation, spin simule une exécution possible du système.
Ï
Les instructions printf sont évaluées.
Ï
La simulation s’arrête en cas d’assertion non vérifiée.
Spin en mode vérification
25/271. On appelle spin avec l’option
−a.
⇒ Spin génère un fichierpan.c(pan = protocol analyser) qui est l’algorithme d’exploration de l’espace des états accessibles.
2. On compile puis exécute pan.c.
3. Si une erreur est trouvée, un fichier avec l’extension trail est créé.
Ï Ce fichier décrit une exécution qui mène à l’erreur trouvée.
4. On utilise alors spin avec l’option -t pour afficher cette exécution.
$ s p i n - a p r o g r a m m e . pml
$ gcc pan . c - o pan
$ ./ pan
$ s p i n - t p r o g r a m m e . pml
Ï
En mode vérification, spin explore l’espace des états accessibles du programme (= simule toutes les exécutions possibles du programme).
Ï
Les instructions printf sont ignorées.
Ï
L’exploration s’arrête en cas d’assertion non vérifiée.
Options de ligne commande
26/27Spin en mode simulation :
Ï
-c : afficher "graphiquement" les émissions et réceptions sur les canaux
Ï
-p : afficher les opérations exécutées
Ï
-l : afficher la valeur des variables locales
Ï
-g : afficher la valeur des variables globales
Ï
-i : simulation interactive, l’utilisateur choisit la transition suivante En mode vérification :
Ï
-search : spin génère, compile et exécute pan.c
Ï