Manuel de suivi dynamique Solaris

Format de sortie

Le suivi d'appels système est une méthode efficace pour observer le fonctionnement de la plupart des processus utilisateur. Si vous avez utilisé l'utilitaire Solaris truss(1) auparavant en tant qu'administrateur ou développeur, vous avez sans doute pu constater qu'il s'agit d'un outil utile qu'il convient de garder à portée de main en cas de problème. Si vous n'avez jamais utilisé truss auparavant, essayez-le dès à présent en tapant cette commande dans l'un de vos shells :


$ truss date

Un suivi formaté de tous les appels système exécutés par date(1) s'affiche, suivi de sa propre ligne de sortie à la fin. L'exemple suivant améliore le programme précédent rw.d en formatant sa sortie sur truss(1) de façon à mieux la comprendre. Tapez le programme suivant et enregistrez-le dans le fichier trussrw.d :


Exemple 1–2 trussrw.d : suivi des appels système avec le format de sortie truss (1)

syscall::read:entry,
syscall::write:entry
/pid == $1/
{
	printf("%s(%d, 0x%x, %4d)", probefunc, arg0, arg1, arg2);
}

syscall::read:return,
syscall::write:return
/pid == $1/
{
	printf("\t\t = %d\n", arg1);
}

Dans cet exemple, la constante 12345 est remplacée par l'étiquette $1 dans chaque prédicat. Cette étiquette vous permet de spécifier le processus d'intérêt en tant qu'argument au script : $1 est remplacé par la valeur du premier argument lorsque le script est compilé. Pour exécuter trussrw.d, utilisez les options dtrace, -q et -s, suivies par l'ID de processus de votre shell en tant qu'argument final. L'option - q indique que dtrace doit être silencieux et doit supprimer la ligne d'en-tête et les colonnes de CPU et d'ID présentées dans les exemples précédents. Ainsi, seul le résultat des données suivies explicitement s'affichera. Tapez la commande suivante (en remplaçant 12345 par l'ID d'un processus de shell) puis appuyez sur Entrée plusieurs fois dans le shell spécifié :


# dtrace -q -s trussrw.d 12345
	                 = 1
write(2, 0x8089e48,    1)                = 1
read(63, 0x8090a38, 1024)                = 0
read(63, 0x8090a38, 1024)                = 0
write(2, 0x8089e48,   52)                = 52
read(0, 0x8089878,    1)                 = 1
write(2, 0x8089e48,    1)                = 1
read(63, 0x8090a38, 1024)                = 0
read(63, 0x8090a38, 1024)                = 0
write(2, 0x8089e48,   52)                = 52
read(0, 0x8089878,    1)                 = 1
write(2, 0x8089e48,    1)                = 1
read(63, 0x8090a38, 1024)                = 0
read(63, 0x8090a38, 1024)                = 0
write(2, 0x8089e48,   52)                = 52
read(0, 0x8089878,    1)^C
#

Examinons plus en détail votre programme D et sa sortie. D'abord, une clause similaire au programme précédent instrumente chacun des appels du shell sur read(2) et write(2). Mais pour cet exemple, une nouvelle fonction, printf(), est utilisée pour effectuer le suivi des données et les afficher dans un format spécifique.

syscall::read:entry,
syscall::write:entry
/pid == $1/
{
	printf("%s(%d, 0x%x, %4d)", probefunc, arg0, arg1, arg2);
}

La fonction printf() combine la capacité de suivi des données comme dans la fonction trace() utilisée précédemment, avec la capacité de sortie des données et d'autres textes dans un format spécifique décrit. La fonction printf() indique à DTrace de suivre les données associées à chaque argument faisant suite au premier argument, puis de formater les résultats en utilisant les règles décrites par le premier argument printf() connu sous le nom de chaîne de format.

La chaîne de format est une chaîne normale contenant n'importe quel nombre de conversions de format, chacune commençant par le caractère % qui décrit comment formater l'argument correspondant. La première conversion dans la chaîne de format correspond au second argument printf(), la seconde conversion au troisième argument, etc. L'ensemble du texte entre les conversions est affiché textuellement. Le caractère suivant le caractère de conversion % décrit le format à utiliser pour l'argument correspondant. Voici la signification des conversions de format utilisées dans trussrw.d :

%d

Imprime la valeur correspondante en tant que nombre entier décimal 

%s

Imprime la valeur correspondante en tant que chaîne 

%x

Imprime la valeur correspondante en tant que nombre entier hexadécimal 

La fonction printf() de DTrace fonctionne de la même façon que la routine de bibliothèque printf(3C) C ou l'utilitaire printf(1) du shell. Si vous n'avez jamais rencontré la fonction printf() auparavant, les formats et options sont expliqués en détails dans le Chapitre12Format de sortie. Vous devez lire ce chapitre attentivement, même si vous connaissez déjà la fonction printf() dans un autre langage. En D, printf() est fourni de façon intégrée et certaines nouvelles conversions de format sont disponibles, conçues spécifiquement pour DTrace.

Pour vous aider à écrire des messages corrects, le compilateur D valide chaque chaîne de format printf() par rapport à sa liste d'arguments. Essayez de modifier probefunc dans la clause précédente en nombre entier 123. Si vous exécutez le programme modifié, un message d'erreur s'affiche, vous informant que la conversion du format de la chaîne %s ne convient pas pour une utilisation avec un argument de nombre entier.


# dtrace -q -s trussrw.d
dtrace: failed to compile script trussrw.d: line 4: printf( )
	   argument #2 is incompatible with conversion #1 prototype:
	        conversion: %s
	         prototype: char [] or string (or use stringof)
	          argument: int
#

Pour afficher le nom de l'appel système de lecture et d'écriture et ses arguments, utilisez l'instruction printf() :

printf("%s(%d, 0x%x, %4d)", probefunc, arg0, arg1, arg2);

pour suivre le nom de la fonction de sonde actuelle et les trois premiers arguments de nombre entier dans l'appel système, disponible dans les variables DTrace arg0, arg1 et arg2. Pour plus d'informations sur les arguments de sonde, reportez-vous au Chapitre3Variables. Le premier argument pour read(2) et write(2) est un descripteur de fichier, imprimé en décimales. Le second argument est une adresse tampon, formatée en tant que valeur hexadécimale. L'argument final est le format tampon, formaté en tant que valeur décimale. Le spécificateur de format %4d est utilisé pour le troisième argument pour indiquer que la valeur doit être imprimée en utilisant la conversion de format %d avec un champ d'une largeur maximale de 4 caractères. Si le nombre entier fait moins de 4 caractères de large, printf() insère des espaces supplémentaires pour aligner le résultat.

Pour afficher le résultat de l'appel système et compléter chaque ligne de sortie, utilisez la clause suivante :

syscall::read:return,
syscall::write:return
/pid == $1/
{
	printf("\t\t = %d\n", arg1);
}

Vous remarquerez que le fournisseur syscall publie également une sonde appelée return pour chaque appel système, en plus de entry. La variable DTrace arg1 pour les sondes syscall return évalue la valeur de retour de l'appel système. La valeur de retour est formatée en tant que nombre entier décimal. Les séquences de caractères commençant par des barres obliques inversées dans la chaîne de format s'étendent à la tabulation (\t) et à la nouvelle ligne (\n) respectivement. Ces séquences d'échappement vous aident à afficher ou à enregistrer des caractères difficiles à saisir. D prend en charge le même ensemble de séquences d'échappement que les langages de programmation C, C++ et Java. Vous trouverez la liste complète des séquences d'échappement au Chapitre2Types, opérateurs et expressions.