Guía de seguimiento dinámico de Solaris

Capítulo 4 Estructura del programa D

Los programas D consisten en una serie de cláusulas que describen los sondeos que se van a habilitar y predicados y acciones que enlazar a estos sondeos. Los programas D también puede contener declaraciones de variables, como se describe en el Capítulo 3Variables, y definiciones de tipos nuevos, descritas en el Capítulo 8Definiciones de tipos y constantes. Este capítulo describe de modo formal la estructura general de un programa D, así como funciones para la construcción de descripciones de sondeos que coincidan con más de un sondeo. Trataremos también el uso del preprocesador C, cpp, con programas D.

Cláusulas y declaraciones del sondeo

Tal y como hemos podido ver en los ejemplos hasta ahora, los archivos fuente de programa D consisten en una o más cláusulas de sondeo, que describen la instrumentación que DTrace va a habilitar. Cada una de las cláusulas de sondeo tiene este formato general:

descripciones_sondeo / predicado / { declaraciones_de_acción
}

Puede omitirse tanto el predicado como una lista de las instrucciones de acción. A las directivas que se encuentran fuera de las cláusulas de sondeos se les conoce como declaraciones. Las declaraciones sólo deben utilizarse fuera de cláusulas de sondeo. No se permiten declaraciones en el interior de { } de cierre, y no debe intercalarse entre los elementos de la cláusula de sondeo mostrada anteriormente. Los espacios en blanco pueden utilizarse para separar los elementos del programa D, y para sangrar instrucciones de acción.

Es posible utilizar las declaraciones para declarar variables D y símbolos C externos, tal y como se trata en el Capítulo 3Variables, o para definir nuevos tipos para su uso en D, como se describe en el Capítulo 8Definiciones de tipos y constantes. Podrían aparecer también directivas de compilador D especiales, llamadas pragmas en cualquier parte de un programa D, incluyendo el exterior de cláusulas de sondeo. Los pragmas D se especifican en las líneas que comienzan con un carácter #. Los pragmas D se utilizan, por ejemplo, para definir opciones de tiempo de ejecución de DTrace; consulte Capítulo 16Opciones y optimizables para obtener más información.

Descripciones de sondeo

Las cláusulas del programa D comienzan con una lista de una o más descripciones de sondeo, cada una de ellas con el formato habitual:

proveedor:módulo:función:nombre

Si se omite uno o más campos de la descripción del sondeo, el compilador D interpreta los campos especificados de derecha a izquierda. Por ejemplo, la descripción de sondeo foo:bar coincidiría con una sondeo con la función foo y el nombre bar con independencia del valor del proveedor del sondeo y los campos del módulo. Por lo tanto, la descripción de un sondeo se ve con mayor precisión como un patrón que puede utilizarse para que coincida con uno o más sondeos, en base a sus nombres.

Debe escribir sus descripciones de sondeo D especificando los cuatro delimitadores, de forma que pueda especificar el proveedor que desee en la parte izquierda. Si no especifica el proveedor, puede que obtenga resultados no esperados en caso de que varios proveedores publiquen sondeos bajo el mismo nombre. De forma similar, las futuras versiones de DTrace podrían incluir nuevos proveedores, cuyos sondeos coincidan de forma no intencionada con las descripciones de sondeo especificada parcialmente. Puede especificar un proveedor y aún así coincidir con cualquiera de sus sondeos dejando en blanco cualquiera de los campos módulo, función y nombre. Por ejemplo, la descripción syscall::: puede utilizarse para hacer coincidir los sondeos publicados por el proveedor DTrace syscall.

Las descripciones de sondeos admiten también un patrón que coincida con una sintaxis de coincidencia de patrones similar a la sintaxis de coincidencia de patrón globbing descrita en sh(1). Antes de hacer coincidir un sondeo con una descripción, DTrace explora los campos de descripción en busca de los caracteres *, ? y [. Si uno de estos caracteres aparecen en un campo de descripción de sondeo y no está precedido por un \, el campo se considera un patrón. El patrón de descripción debe coincidir con todo el campo correspondiente de un sondeo determinado. La descripción de sondeo completa debe coincidir en todos los campos, para conseguir una coincidencia satisfactoria y habilitar un sondeo. Un campo de descripción de sondeo que no sea un patrón debe coincidir exactamente con el campo correspondiente del sondeo. Los campos de descripción vacíos coinciden con cualquier sondeo.

Los caracteres especiales de la siguiente tabla se reconocen en los patrones de nombre de los sondeos:

Tabla 4–1 Nombre del sondeo Patrón Caracteres coincidente

Símbolo 

Descripción 

*

Coincide con cualquier cadena, incluyendo la cadena null. 

?

Sustituye a un carácter cualquiera. 

[ ... ]

Coincide con cualquiera de los caracteres encerrados. Un par de caracteres separados por - coinciden con cualquier carácter entre el par, incluidos. Si el primer carácter tras el [ es !, se coincidirá con cualquier carácter no encerrado en el conjunto.

\

Interpreta el siguiente carácter como sí mismo, sin ningún tipo de significado especial. 

Los caracteres de coincidencia de patrón pueden utilizarse en uno o en los cuatro campos de sus descripciones de sondeo. Puede también utilizar patrones para mostrar una lista de los sondeos coincidentes mediante la utilización de los patrones en la línea de comandos con dtrace - l. Por ejemplo, el comando dtrace -l -f kmem_* enumera todos los sondeos DTrace en funciones cuyos nombres comienzan por el prefijo kmem_.

Si desea especificar el mismo predicado y las mismas acciones para más de una descripción de sondeo o patrón de descripción, puede colocar las descripciones en una lista separada por comas. Por ejemplo, el siguiente programa D realizaría un seguimiento de una marca horaria cada vez que se activara un sondeo asociado a una entrada a llamadas de sistema que contengan las palabras "lwp" o "sock":

syscall::*lwp*:entry, syscall::*sock*:entry
{
	trace(timestamp);
}

Una descripción de sondeo podría también especificar un sondeo mediante su entero Id. de sondeo. Por ejemplo, la cláusula:

12345
{
	trace(timestamp);
}

podría utilizarse para habilitar el sondeo Id. 12345, según informa dtrace -l -i 12345. Debe escribir siempre los programas D empleando descripciones de sondeo legibles por el ojo humano. No se garantiza que los enteros Id. de sondeo sean siempre los mismos, tras la carga o descarga de los módulos del núcleo del proveedor DTrace, ni después de reiniciar.

Predicados

Los predicados son expresiones encerradas en barras / / que se evalúan en el momento de activación de sondeos para determinar si deben ejecutarse las acciones asociadas. Los predicados son el principal constructor condicional utilizado para la creación de flujo de control más complejo en un programa D. Puede omitir toda la sección de predicado de la cláusula del sondeo para cualquier sondeo, en cuyo caso las acciones se ejecutarán siempre al activar el sondeo.

Las expresiones de predicado pueden utilizar cualquiera de los operadores D anteriormente descritos, y podrían hacer referencia a cualquier objeto de datos D, como pueden ser las variables y las constantes. La expresión del predicado debe evaluarse a un valor de tipo entero o puntero, para que pueda considerarse como true o false. Al igual que en todas las expresiones D, el valor cero se interpreta como false, y los valores que no son cero se interpretan como true.

Acciones

Las acciones de sondeo se describen mediante una lista de instrucciones separadas por puntos y comas(;) y encerradas entre corchetes { }. Si sólo desea anotar que un sondeo determinado se activó en una CPU en concreto, sin realizar un seguimiento de ningún tipo de datos ni realizar ninguna acción adicional, es posible especificar un juego de corchetes vacío sin instrucciones en su interior.

Uso del preprocesador C

El lenguaje de programación C utilizado para la definición de interfaces de sistema Solaris incluye un preprocesador que realiza un conjunto de pasos iniciales en la compilación de un programa C. El preprocesador C suele utilizarse para definir sustituciones de macro en las que un símbolo de un programa C se sustituye por otro juego de símbolos predefinido, o para incluir copias de los archivos de cabecera del sistema. Es posible utilizar el preprocesador C junto con sus programas D mediante la especificación de la opción dtrace -C. La opción provoca que dtrace ejecute en primer lugar el preprocesador cpp(1) en su archivo de programa fuente, para posteriormente trasladar los resultados al compilador D.. El preprocesador C se describe de una forma más detallada en El lenguaje de programación C.

El compilador D carga automáticamente el conjunto de descripciones de tipo C asociadas a la implementación del sistema operativo, pero puede utilizar el preprocesador para incluir otras definiciones de tipo, como por ejemplo tipos utilizados en sus propios programas C. También es posible utilizar el preprocesador para realizar otras tareas, como la creación de macros que se amplíen hasta paquetes de código D y otros elementos de programas. Si utiliza el preprocesador con su programa D, podría incluir sólo archivos que contengan declaraciones D válidas. Los archivos de cabecera C habituales incluyen únicamente declaraciones externas de tipos y símbolos, que interpretará correctamente el compilador D. El compilador D no puede analizar archivos de cabecera C que incluyan elementos de programa adicionales, como código fuente de funciones C, y devolverán el mensaje de error pertinente.