Manuel de suivi dynamique Solaris

Chapitre 22 Fournisseur sdt

Le fournisseur SDT (Statically Defined Tracing) crée des sondes sur les sites qu'un programmeur de logiciels a formellement désignés. Le mécanisme du fournisseur SDT permet aux programmeurs de choisir consciemment les emplacements convenant aux utilisateurs de DTrace et de transmettre certaines connaissances sémantiques sur chaque emplacement par le biais du nom de la sonde. Le noyau de Solaris a défini une poignée de sondes SDT et en ajoutera probablement d'autres à l'avenir. DTrace fournit également un mécanisme pour les développeurs d'applications utilisateur de manière à définir les sondes statiques, tel que spécifié dans le Chapitre34Suivi défini statiquement pour les applications utilisateur.

Sondes

Les sondes SDT définies par le noyau de Solaris sont répertoriées dans le Tableau 22–1. La stabilité du nom et des données de ces sondes est Privée car sa description reflète ici l'implémentation du noyau et ne doit pas être influencée par une exécution de l'interface. Pour plus d'informations sur le mécanisme de stabilité de DTrace, reportez-vous à la section Stabilité.

Tableau 22–1 Sondes SDT

Nom de la sonde 

Description 

arg0

callout-start

Sonde qui se déclenche immédiatement avant l'exécution d'une légende (voir <sys/callo.h>). Les légendes sont exécutées au moyen d'une horloge système périodique et représentent l'implémentation de timeout(9F).

Pointez la sonde callout_t (voir <sys/callo.h>) correspondant à la légende à exécuter.

callout-end

Sonde qui se déclenche immédiatement avant l'exécution d'une légende (voir <sys/callo.h>).

Pointez la sonde callout_t (voir <sys/callo.h>) correspondant à la légende qui vient juste d'être exécutée.

interrupt-start

Sonde qui se déclenche immédiatement avant d'appeler une routine d'interruption du périphérique. 

Pointez la structure dev_info (voir <sys/ddi_impldefs.h>) correspondant au périphérique d'interruption.

interrupt-complete

Sonde qui se déclenche immédiatement après l'arrêt d'une routine d'interruption du périphérique. 

Pointez la structure dev_info (voir <sys/ddi_impldefs.h>) correspondant au périphérique d'interruption.

Exemples

L'exemple suivant est un script d'observation du comportement des légendes seconde par seconde :

#pragma D option quiet

sdt:::callout-start
{
	@callouts[((callout_t *)arg0)->c_func] = count();
}

tick-1sec
{
	printa("%40a %10@d\n", @callouts);
	clear(@callouts);
}

Cet exemple permet de savoir qui utilise fréquemment timeout(9F) dans le système, comme illustré dans la sortie suivante :


# dtrace -s ./callout.d
                                    FUNC      COUNT
                            TS`ts_update          1
              uhci`uhci_cmd_timeout_hdlr          3
                          genunix`setrun          5
                     genunix`schedpaging          5
                         ata`ghd_timeout         10
 uhci`uhci_handle_root_hub_status_change        309

                                    FUNC      COUNT
              ip`tcp_time_wait_collector          1
                            TS`ts_update          1
              uhci`uhci_cmd_timeout_hdlr          3
                     genunix`schedpaging          4
                          genunix`setrun          8
                         ata`ghd_timeout         10
 uhci`uhci_handle_root_hub_status_change        300

                                    FUNC      COUNT
              ip`tcp_time_wait_collector          0
                        iprb`mii_portmon          1
                            TS`ts_update          1
              uhci`uhci_cmd_timeout_hdlr          3
                     genunix`schedpaging          4
                          genunix`setrun          7
                         ata`ghd_timeout         10
 uhci`uhci_handle_root_hub_status_change        300

L'interface timeout(9F) ne produit qu'une seule expiration d'horloge. Les utilisateurs de timeout() qui ont besoin d'une fonction d'horloge d'intervalle, appliquent généralement leur délai d'attente à partir de leur routine timeout(). L'exemple suivant présente ce comportement :

#pragma D option quiet

sdt:::callout-start
{
	self->callout = ((callout_t *)arg0)->c_func;
}

fbt::timeout:entry
/self->callout && arg2 <= 100/
{
	/*
	 * In this case, we are most interested in interval timeout(9F)s that
	 * are short.  We therefore do a linear quantization from 0 ticks to
	 * 100 ticks.  The system clock's frequency — set by the variable
	 * "hz" — defaults to 100, so 100 system clock ticks is one second. 
	 */
	@callout[self->callout] = lquantize(arg2, 0, 100);
}

sdt:::callout-end
{
	self->callout = NULL;
}

END
{
	printa("%a\n%@d\n\n", @callout);
}

Exécuter ce script et patienter quelques secondes avant d'appuyer sur Control-C entraîne une sortie similaire à l'exemple suivant :


# dtrace -s ./interval.d
^C
genunix`schedpaging

           value  ------------- Distribution ------------- count    
              24 |                                         0        
              25 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 20       
              26 |                                         0        


ata`ghd_timeout

           value  ------------- Distribution ------------- count    
               9 |                                         0        
              10 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 51       
              11 |                                         0        


uhci`uhci_handle_root_hub_status_change

           value  ------------- Distribution ------------- count    
               0 |                                         0        
               1 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 1515     
               2 |                                         0

La sortie montre que uhci_handle_root_hub_status_change() dans le pilote uhci(7D) représente l'horloge d'intervalle la plus courte du système : elle est appelée à chaque top d'horloge du système.

Vous pouvez utiliser la sonde interrupt-start pour comprendre l'activité d'interruption. L'exemple suivant illustre comment quantifier le temps accordé à l'exécution d'une routine d'interruption par le nom du pilote :

interrupt-start
{
	self->ts = vtimestamp;
}

interrupt-complete
/self->ts/
{
	this->devi = (struct dev_info *)arg0;
	@[stringof(`devnamesp[this->devi->devi_major].dn_name),
	    this->devi->devi_instance] = quantize(vtimestamp - self->ts);
}

Exécuter ce script engendre une sortie identique à l'exemple suivant :


# dtrace -s ./intr.d
dtrace: script './intr.d' matched 2 probes
^C
 isp                                                       0
           value  ------------- Distribution ------------- count    
            8192 |                                         0        
           16384 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 1        
           32768 |                                         0        

  pcf8584                                                   0
           value  ------------- Distribution ------------- count    
              64 |                                         0        
             128 |                                         2        
             256 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@         157      
             512 |@@@@@@                                   31       
            1024 |                                         3        
            2048 |                                         0        

  pcf8584                                                   1
           value  ------------- Distribution ------------- count    
            2048 |                                         0        
            4096 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@          154      
            8192 |@@@@@@@                                  37       
           16384 |                                         2        
           32768 |                                         0        

  qlc                                                       0
           value  ------------- Distribution ------------- count    
           16384 |                                         0        
           32768 |@@                                       9        
           65536 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@      126      
          131072 |@                                        5        
          262144 |                                         2        
          524288 |                                         0        

  hme                                                       0
           value  ------------- Distribution ------------- count    
            1024 |                                         0        
            2048 |                                         6        
            4096 |                                         2        
            8192 |@@@@                                     89       
           16384 |@@@@@@@@@@@@@                            262      
           32768 |@                                        37       
           65536 |@@@@@@@                                  139      
          131072 |@@@@@@@@                                 161      
          262144 |@@@                                      73       
          524288 |                                         4        
         1048576 |                                         0        
         2097152 |                                         1        
         4194304 |                                         0        

  ohci                                                      0
           value  ------------- Distribution ------------- count    
            8192 |                                         0        
           16384 |                                         3        
           32768 |                                         1        
           65536 |@@@                                      143      
          131072 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@     1368     
          262144 |                                         0 

Création de sondes SDT

En tant que développeur de pilotes de périphériques, vous souhaiterez peut-être créer vos propres sondes SDT dans votre pilote Solaris. Les sondes désactivées du fournisseur SDT se traduisent essentiellement par le coût de plusieurs instructions machine non opérationnelles. Vous êtes, par conséquent, encouragé à ajouter des sondes SDT à vos pilotes de périphérique, au besoin. À moins que ces sondes n'aient une incidence négative sur les performances, vous pouvez les conserver dans votre code de livraison.

Déclaration des sondes

Les sondes SDT sont déclarées à l'aide des macros DTRACE_PROBE, DTRACE_PROBE1, DTRACE_PROBE2, DTRACE_PROBE3 et DTRACE_PROBE4 à partir de <sys/sdt.h>. Le nom du module et le nom des fonctions d'une sonde basée sur le fournisseur SDT correspondent au module du noyau et aux fonctions de la sonde. Le nom de la sonde dépend du nom donné dans la macro DTRACE_PROBEn. Si le nom ne contient pas deux traits de soulignement consécutifs (__), le nom de la sonde est écrit dans la macro. Si le nom contient deux traits de soulignement consécutifs, ils sont convertis en un tiret simple ( -) dans le nom de la sonde. Par exemple, si une macro DTRACE_PROBE spécifie transaction__start, la sonde SDT s'appellera transaction-start. Cette substitution permet au code C de fournir des noms de macro ne constituant pas des identificateurs en C valides sans spécifier de chaîne.

Comme DTrace intègre au tuple identifiant une sonde le nom du module du noyau et des fonctions, vous n'avez pas à ajouter ces informations dans le nom de la sonde pour éviter les collisions d'espace de noms. Vous pouvez utiliser la commande dtrace -l -P sdt -m module sur votre pilote module pour répertorier les sondes que vous avez installées, ainsi que leurs noms complets, tels que les utilisateurs de DTrace pourront les afficher.

Arguments des sondes

Les arguments de chaque sonde SDT sont les arguments spécifiés dans la référence de macro DTRACE_PROBEn correspondante. Le nombre d'arguments dépend de la macro utilisée pour créer la sonde : DTRACE_PROBE1 spécifie un argument, DTRACE_PROBE2 spécifie deux arguments, etc. Lors de la déclaration de vos sondes SDT, vous pouvez réduire l'incidence des sondes désactivées en ne déréférençant pas les pointeurs et en ne chargeant pas les variables globales dans les arguments des sondes. Vous devez effectuer avec précaution le déréférencement des pointeurs et le chargement des variables dans les actions en D qui activent les sondes de sorte que les utilisateurs de DTrace puissent ne demander ces actions que lorsqu'ils en ont besoin.

Stabilité

Le fournisseur SDT utilise le mécanisme de stabilité de DTrace pour présenter sa stabilité, comme illustré dans le tableau suivant. Pour plus d'informations sur le mécanisme de stabilité, reportez-vous au Chapitre39Stabilité.

Élément 

Stabilité des noms 

Stabilité des données 

Classe de dépendance 

Fournisseur 

En cours d'évolution 

En cours d'évolution 

ISA

Module 

Privé 

Privé 

Inconnu 

Fonction 

Privé 

Privé 

Inconnu 

Nom 

Privé 

Privé 

ISA

Arguments 

Privé 

Privé 

ISA