Manuel de suivi dynamique Solaris

Chapitre 4 Structure de programme D

Les programmes D sont constitués d'un ensemble de clauses décrivant des sondes à activer, ainsi que des prédicats et des actions à associer à ces sondes. Les programmes en D peuvent également contenir des déclarations de variables, comme le décrit le Chapitre3Variables, ainsi que des définitions de nouveaux types, comme le décrit le Chapitre8Définitions des types et des constantes. Ce chapitre décrit la structure générale d'un programme D ainsi que les fonctions de développement de descriptions de sondes correspondant à plusieurs sondes. Nous aborderons également l'utilisation du préprocesseur C, cpp, avec des programmes D.

Clauses et déclarations de sondes

Tel qu'illustré dans les exemples jusqu'ici, un fichier source de programme D comprend une ou plusieurs clauses de sonde décrivant l'instrumentation à activer par DTrace. Chaque clause de sonde présente la forme générale suivante :

descriptions de sondes 
/ prédicat / {	instructions d'action}

Le prédicat et la liste d'instructions d'action peuvent être omis. Toute directive rencontrée en dehors des clauses de sonde sont appelées des déclarations. Les déclarations ne peuvent être utilisées qu'en dehors des clauses de sonde. Aucune déclaration placée entre { } n'est autorisée et les déclarations ne peuvent pas s'intercaler entre les éléments de la clause de sonde illustrée ci-dessus. Un espace peut être utilisé pour séparer les éléments d'un programme D et pour indenter des instructions d'action.

Les déclarations peuvent être utilisées pour déclarer des variables D et des symboles C externes, tel que décrit dans le Chapitre3Variables, ou pour définir de nouveaux types d'utilisation dans D, tel que décrit dans le Chapitre8Définitions des types et des constantes Des directives de compilateur C spéciales appelées instructions pour compilateur peuvent également se trouver n'importe où dans un programme D, y compris à l'extérieur de clauses de sonde. Les instructions de compilateur D sont spécifiées sur les lignes commençant par #. Les instructions pour compilateur D sont utilisées, par exemple, pour définir des options d'exécution DTrace ; pour plus d'informations, reportez-vous au Chapitre16Options et paramètres réglables.

Descriptions de sonde

Chaque clause de programme D commence par une liste d'une ou plusieurs descriptions de sonde, chacune prenant la forme habituelle suivante :

nom:fonction:module:fournisseur

Si un ou plusieurs champs de la description de sonde sont omis, les champs spécifiés sont interprétés de droite à gauche par le compilateur D. Par exemple, la description de sonde foo:bar correspondrait à une sonde dont la fonction est foo et le nom bar quelle que soit la valeur du fournisseur de la sonde et des champs de module. Une description de sonde est donc plus considérée comme un modèle pouvant être utilisé pour correspondre à une ou plusieurs sondes en fonction de leur nom.

Vous devez rédiger vos descriptions de sonde D en spécifiant les quatre délimiteurs de champ afin de pouvoir spécifier le fournisseur souhaité à gauche. Si vous ne spécifiez pas de fournisseur, des résultats inattendus sont possibles si plusieurs fournisseurs proposent des sondes du même nom. De même, des versions futures de DTrace peuvent inclure de nouveaux fournisseurs dont les sondes correspondent involontairement à vos descriptions de sonde partiellement définies. Vous pouvez spécifier un fournisseur mais faire correspondre l'une de ses sondes en laissant les champs de module, fonction et nom vides. Par exemple, la description syscall::: peut être utilisée pour faire correspondre chaque sonde proposée par le fournisseur syscall DTrace.

Les descriptions de sonde prennent également en charge une syntaxe de correspondance de modèle similaire à celle du globbing de shell décrite dans sh(1). Avant de faire correspondre une sonde et une description, DTrace analyse chaque champ de description à la recherche des caractères *, ? et [. Si l'un de ces caractères est présent dans un champ de description de sonde et qu'il n'est pas précédé de \, le champ est considéré comme un modèle. Le modèle de description doit correspondre à l'ensemble du champ correspondant d'une sonde donnée. La description de sonde entière doit correspondre champ par champ pour une correspondance totale et une activation de la sonde. Un champ de description de sonde qui n'est pas un modèle doit correspondre exactement au champ correspondant de la sonde. Un champ de description vide correspond à n'importe quelle sonde.

Les caractères spéciaux du tableau suivant sont reconnus dans des modèles de nom de sonde :

Tableau 4–1 Caractères de correspondance de modèle de nom de sonde

Symbole 

Description 

*

Correspond à toute chaîne, y compris la chaîne nulle. 

?

Correspond à un caractère unique. 

[ ... ]

Correspond à l'un des caractères entre crochets. Une paire de caractères séparée par - correspond à tout caractère situé entre la paire. Si le premier caractère après [ est !, tout caractère non inclus dans l'ensemble est mis en correspondance.

\

Interprète le caractère suivant tel quel, sans signification particulière. 

Les caractères de correspondance de modèle peuvent être utilisés dans l'un ou les quatre champs de vos descriptions de sonde. Vous pouvez également utiliser des modèles pour répertorier des sondes correspondantes à l'aide des modèles de la ligne de commande dtrace - l. Par exemple, la commande dtrace -l -f kmem_* répertorie toutes les sondes DTrace dans des fonctions dont le nom commence par le préfixe kmem_.

Pour spécifier le même prédicat et les mêmes actions pour plusieurs descriptions ou modèles de sonde, vous pouvez créer une liste de descriptions séparée par une virgule. Par exemple, le programme D suivant permettrait de suivre un horodatage chaque fois que des sondes associées à une entrée d'appels système contenant les mots lwp ou sock sont déclenchées :

syscall::*lwp*:entry, syscall::*sock*:entry
{
	trace(timestamp);
}

Une description de sonde peut également spécifier une sonde à l'aide de son ID entier. Par exemple, la clause :

12345
{
	trace(timestamp);
}

pourrait être utilisée pour activer l'ID de sonde 12345, tel que renvoyé par la commande dtrace -l -i 12345. Vous devez toujours rédiger vos programmes D à l'aide de descriptions de sonde compréhensibles. Les ID de sonde entiers ne sont pas nécessairement cohérents car les modules de noyau du fournisseur DTrace sont chargés et déchargés ou suivent une réinitialisation.

Prédicats

Les prédicats sont des expressions comprises entre barres obliques / / et évaluées au déclenchement d'une sonde afin de déterminer si les actions associées doivent être exécutées. Les prédicats constituent la base conditionnelle principale du développement d'un flux de commande plus complexe d'un programme D. Vous pouvez omettre la section des prédicats de la clause de chaque sonde, auquel cas les actions sont toujours exécutées au déclenchement de la sonde.

Les expressions de prédicat peuvent utiliser l'un des opérateurs D décrits précédemment et peuvent faire référence à des objets de données D comme des variables et des constantes. L'expression de prédicat doit évaluer une valeur de type entier ou pointeur afin de pouvoir être déterminée comme vraie ou fausse. Comme pour toutes les expressions D, une valeur de zéro est interprétée comme fausse et une valeur autre que zéro est interprétée comme vraie.

Actions

Les actions de sonde sont décrites par une liste d'instructions séparée par un point-virgule(;) et placée entre { }. Pour ne noter qu'une sonde particulière déclenchée sur une CPU donnée sans suivre de données ou exécuter des actions supplémentaires, vous pouvez spécifier un ensemble d'accolades vides sans instructions.

Utilisation du préprocesseur C

Le langage de programmation C utilisé pour définir des interfaces de système Solaris comprend un préprocesseur qui exécute un ensemble d'étapes initiales dans la compilation de programme C. Le préprocesseur C est fréquemment utilisé pour définir des substitutions de macro dans lesquelles un jeton de programme C est remplacé par un autre jeu de jetons prédéfini ou pour inclure des copies de fichiers d'en-tête système. Vous pouvez utiliser le préprocesseur C avec vos programmes D en spécifiant l'option dtrace -C. Cette option amène dtrace à exécuter tout d'abord le préprocesseur cpp(1) sur votre fichier source de programme, puis à transmettre les résultats au compilateur D. Le préprocesseur C est décrit plus en détails dans The C Programming Language.

Le compilateur D charge automatiquement l'ensemble de descriptions du type C associé à la mise en œuvre du système d'exploitation, mais vous pouvez utiliser le préprocesseur pour inclure d'autres définitions de types comme ceux utilisés dans vos programmes C. Vous pouvez également utiliser le préprocesseur pour exécuter d'autres tâches comme la création de macros devenant des éléments de code D et d'autres éléments de programme. Si vous utilisez le préprocesseur avec votre programme D, vous ne pouvez inclure que des fichiers contenant des déclarations D valides. Les fichiers d'en-tête C classiques n'incluent que des déclarations externes de types et de symboles, qui seront interprétées correctement par le compilateur D. Le compilateur D ne peut pas analyser les fichiers d'en-tête C comprenant d'autres éléments de programme comme du code source de fonction C et renverra un message d'erreur.