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 |