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.
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. |
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 |
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.
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.
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.
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 |