Guía de seguimiento dinámico de Solaris

Capítulo 22 Proveedor sdt

El proveedor Seguimiento definido estáticamente (SDT) crea sondeos en lugares anteriormente designados por un programador de software. El mecanismo SDT permite a los programadores escoger conscientemente ubicaciones de interés para los usuarios de DTrace y facilitar cierto conocimiento semántico acerca de cada ubicación, todo ello a través del nombre del sondeo. El núcleo de Solaris ha definido un puñado de sondeos SDT, y probablemente añada más a medida que pase el tiempo. DTrace también proporciona un mecanismo para desarrolladores de aplicaciones de usuarios para definir sondeos estáticos, que se describe en el Capítulo 34Seguimiento definido estáticamente para las aplicaciones de los usuarios.

Sondeos

Los sondeos SDT definidos por el núcleo de Solaris se enumeran en la Tabla 22–1. La estabilidad de nombre y la estabilidad de datos de estos sondeos son Private, ya que su descripción refleja de este modo la implementación del núcleo, y no debe inferirse que es una obligación de la interfaz. Para obtener más información acerca del mecanismo de estabilidad de DTrace, consulte Estabilidad.

Tabla 22–1 Sondeos SDT

Nombre del sondeo 

Descripción 

arg0

callout-start

Sondeo que se activa inmediatamente antes de ejecutar una llamada (consulte <sys/callo.h>). Las llamadas se ejecutan según el reloj de sistema periódico, y representan la implementación de timeout(9F).

Puntero a la callout_t (consulte <sys/callo.h>) correspondiente a la llamada que debe ejecutarse.

callout-end

Sondeo que se activa inmediatamente antes de ejecutar una llamada (consulte <sys/callo.h>).

Puntero a la callout_t (consulte <sys/callo.h>) correspondiente a la llamada que se acaba de ejecutar.

interrupt-start

Sondeo que se activa inmediatamente antes de llamar al manejador de interrupción de un dispositivo. 

Puntero a la estructura dev_info (consulte <sys/ddi_impldefs.h>) correspondiente al dispositivo que realiza la interrupción.

interrupt-complete

Sondeo que se activa inmediatamente después de volver desde el manejador de interrupción del dispositivo. 

Puntero a la estructura dev_info (consulte <sys/ddi_impldefs.h>) correspondiente al dispositivo que realiza la interrupción.

Ejemplos

El siguiente ejemplo es una secuencia de comandos para observar la conducta de una llamada en base a cada segundo:

#pragma D option quiet

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

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

La ejecución de este ejemplo revela los usuarios frecuentes de timeout(9F) en el sistema, tal y como se muestra en la siguiente salida:


# 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

La interfaz timeout(9F) sólo provoca la caducidad de un temporizador. Los consumidores de timeout() que requieren la función de temporizador de intervalos suelen reinstalar el tiempo de espera desde su manejador timeout(). El siguiente ejemplo muestra esta conducta:

#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);
}

La ejecución de esta secuencia de comandos esperando varios segundos antes de pulsar Control-C devuelve una salida similar al siguiente ejemplo:


# 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 salida muestra que uhci_handle_root_hub_status_change() en el controlador uhci(7D) representa el temporizador de intervalo más breve del sistema: se llama cada pulso del reloj del sistema.

El sondeo interrupt-start puede utilizarse para comprender la actividad de interrupción. El siguiente ejemplo muestra cómo cuantificar el tiempo empleado ejecutando un manejador de interrupción por nombre de controlador:

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);
}

La ejecución de esta secuencia de comandos devuelve una salida similar a la que se muestra en el siguiente ejemplo:


# 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 

Creación de sondeos SDT

Si usted es desarrollador de controladores de dispositivos, puede que esté interesado en crear sus propios sondeos SDT en su controlador Solaris. El efecto de sondeo deshabilitado de SDT es básicamente el coste de diversas instrucciones de sistema que no realizan ninguna operación. Por lo tanto, le animamos a que añada sondeos SDT a sus controladores de dispositivo según los necesite. A menos que estos sondeos afecten de forma negativa al rendimiento, puede dejarlos en el código que envíe.

Declaración de sondeos

Los sondeos SDT se declaran utilizando las macros DTRACE_PROBE, DTRACE_PROBE1, DTRACE_PROBE2, DTRACE_PROBE3 y DTRACE_PROBE4 de <sys/sdt.h>. El nombre de módulo y el nombre de función de un sondeo basado en SDT corresponde al módulo del núcleo y a la función del sondeo. El nombre del sondeo depende del nombre proporcionado en la macro DTRACE_PROBEn. Si el nombre contiene dos guiones bajos no consecutivos (__), el nombre del sondeo es tal y como aparece escrito en la macro. Si el nombre contiene dos guiones bajos consecutivos, el nombre del sondeo convierte los guiones bajos consecutivos a un único guión (-). Por ejemplo, si una macro DTRACE_PROBE especifica transaction__start, el nombre del sondeo SDT será transaction-start. Esta sustitución permite al código C proporcionar nombres de macro que no son identificadores C válidos sin necesidad de especificar una cadena.

DTrace incluye el nombre del módulo del núcleo y el nombre de función como parte de la tupla que identifica un sondeo, por lo que no es necesario que incluya esta información en el nombre del sondeo para evitar la colisión de espacio de nombre. Es posible utilizar el comando dtrace -l -P sdt -m module en su controlador module para visualizar una lista de los sondeos que ha instalado y los nombres completos que verán los usuarios de DTrace.

Argumentos de sondeos

Los argumentos para cada SDT son los argumentos especificados en la referencia de macro DTRACE_PROBEn. El número de argumentos depende de la macro utilizada para crear el sondeo: DTRACE_PROBE1 especifica un argumento, DTRACE_PROBE2 especifica dos argumentos, y así, sucesivamente. A la hora de declarar sus sondeos SDT, puede minimizar su efecto de sondeo deshabilitado no cancelando los punteros de referencia y no cargándolos a partir de variables globales en los argumentos del sondeo. Tanto la cancelación de referencia del puntero como la carga de variables locales pueden hacerse de forma segura en acciones D que habiliten sondeos, de forma que los usuarios de DTrace pueden solicitar estas acciones sólo cuando sean necesarias.

Estabilidad

El proveedor SDT utiliza el mecanismo de estabilidad de DTrace para describir sus estabilidades, tal y como se muestra en la tabla siguiente. Para obtener más información sobre el mecanismo de estabilidad, consulte el Capítulo 39Estabilidad.

Elemento 

Estabilidad del nombre 

Estabilidad de los datos 

Clase de dependencia 

Proveedor 

Evolutivo 

Evolutivo 

ISA

Módulo 

Privado 

Privado 

Desconocido 

Función 

Privado 

Privado 

Desconocido 

Nombre 

Privado 

Privado 

ISA

Argumentos 

Privado 

Privado 

ISA