Las acciones de registro de datos son las acciones principales de DTrace. Cada una de estas acciones registra datos de forma predeterminada en la memoria intermedia principal, aunque también es posible que se utilicen para registrar datos en memorias intermedias especulativas. Consulte el Capítulo 11Memorias intermedias y almacenamiento en memoria intermedia para obtener más información sobre la memoria intermedia principal. Consulte el Capítulo 13Seguimiento especulativo para obtener más información sobre las memorias intermedias especulativas. Las descripciones incluidas en esta sección sólo hacen referencia a la memoria intermedia dirigida, lo que indica que los datos se registran en la memoria intermedia principal o en una memoria intermedia especulativa si la acción sigue una especulación().
void trace(expression)
La acción más básica es trace(), que utiliza una expresión del lenguaje D como argumento y realiza un seguimiento del resultado en la memoria intermedia dirigida. Las siguientes instrucciones son ejemplos de acciones trace():
trace(execname); trace(curlwpsinfo->pr_pri); trace(timestamp / 1000); trace(`lbolt); trace("somehow managed to get here");
void tracemem(address, size_t nbytes)
La acción tracemem() utiliza una expresión del lenguaje D como primer argumento, address, y una constante como segundo argumento, nbytes. tracemem() copia la memoria de la dirección especificada por addr en la memoria intermedia dirigida para la longitud especificada por nbytes.
void printf(string format, ...)
Al igual que trace(), la acción printf() realiza un seguimiento de las expresiones del lenguaje D. Sin embargo, printf() acepta un formato del estilo printf(3C) más elaborado. Al igual que printf(3C), los parámetros están formados por una cadena format seguida de un número variable de argumentos. De forma predeterminada, se realiza un seguimiento de los argumentos en la memoria intermedia dirigida. Más adelante, se da formato a los argumentos para la salida mediante dtrace(1M) en función de la cadena de formato especificada. Por ejemplo, los dos primeros ejemplos de trace() de trace() pueden combinarse para formar una única acción printf():
printf("execname is %s; priority is %d", execname, curlwpsinfo->pr_pri);
Para obtener más información sobre printf(), consulte el Capítulo 12Formato de salida.
void printa(aggregation) void printa(string format, aggregation)
La acción printa() permite mostrar y dar formato a las adiciones. Consulte el Capítulo 9Adiciones para obtener más información sobre las adiciones. Si no se especifica ninguna cadenaformat, printa() sólo realiza un seguimiento de una directiva en el consumidor de DTrace que indica que la adición especificada debería procesarse y mostrarse utilizando el formato predeterminado. Si, por el contrario, se especifica una cadena format, se le dará formato a la adición de la forma en la que se especifique. Consulte el Capítulo 12Formato de salida para obtener una descripción más detallada de la cadena de formato printa().
printa() sólo realiza el seguimiento a una directiva que indica que el consumidor de DTrace debe procesar la adición. No procesa la adición en el núcleo. Por lo tanto, el tiempo entre el seguimiento de la directiva printa() y el procesamiento real de la directiva depende de los factores que afecten al procesamiento de la memoria intermedia. Ente estos factores, se incluyen la velocidad de adición y la directiva de almacenamiento en la memoria intermedia, y si esta directiva es switching, la velocidad a la que se conmutan las memorias intermedias. Consulte el Capítulo 9Adiciones y el Capítulo 11Memorias intermedias y almacenamiento en memoria intermedia para obtener descripciones detalladas de estos factores.
void stack(int nframes) void stack(void)
La acción stack() registra el seguimiento de la pila del núcleo en la memoria intermedia dirigida. La pila del núcleo tendrá una profundidad de nframes. Si no se especifica el valor de nframes, el número de marcos de pila registrados será el número especificado por la opción stackframes. Por ejemplo:
# dtrace -n uiomove:entry'{stack()}' CPU ID FUNCTION:NAME 0 9153 uiomove:entry genunix`fop_write+0x1b namefs`nm_write+0x1d genunix`fop_write+0x1b genunix`write+0x1f7 0 9153 uiomove:entry genunix`fop_read+0x1b genunix`read+0x1d4 0 9153 uiomove:entry genunix`strread+0x394 specfs`spec_read+0x65 genunix`fop_read+0x1b genunix`read+0x1d4 ... |
La acción stack() es un poco diferente de las otras acciones, ya que puede utilizarse como clave en una adición:
# dtrace -n kmem_alloc:entry'{@[stack()] = count()}' dtrace: description 'kmem_alloc:entry' matched 1 probe ^C rpcmod`endpnt_get+0x47c rpcmod`clnt_clts_kcallit_addr+0x26f rpcmod`clnt_clts_kcallit+0x22 nfs`rfscall+0x350 nfs`rfs2call+0x60 nfs`nfs_getattr_otw+0x9e nfs`nfsgetattr+0x26 nfs`nfs_getattr+0xb8 genunix`fop_getattr+0x18 genunix`cstat64+0x30 genunix`cstatat64+0x4a genunix`lstat64+0x1c 1 genunix`vfs_rlock_wait+0xc genunix`lookuppnvp+0x19d genunix`lookuppnat+0xe7 genunix`lookupnameat+0x87 genunix`lookupname+0x19 genunix`chdir+0x18 1 rpcmod`endpnt_get+0x6b1 rpcmod`clnt_clts_kcallit_addr+0x26f rpcmod`clnt_clts_kcallit+0x22 nfs`rfscall+0x350 nfs`rfs2call+0x60 nfs`nfs_getattr_otw+0x9e nfs`nfsgetattr+0x26 nfs`nfs_getattr+0xb8 genunix`fop_getattr+0x18 genunix`cstat64+0x30 genunix`cstatat64+0x4a genunix`lstat64+0x1c 1 ... |
void ustack(int nframes, int strsize) void ustack(int nframes) void ustack(void)
La acción ustack() registra un seguimiento de la pila del usuario en la memoria intermedia dirigida. La pila del usuario tendrá una profundidad de nframes. Si no se especifica el valor de nframes, el número de marcos de pila registrados será el número especificado por la opción ustackframes. Aunque ustack() puede determinar la dirección de los marcos de llamada cuando se activa el sondeo, los marcos de pila no se convertirán en símbolos hasta que el consumidor de DTrace no procese la acción ustack() a nivel de usuario. Si se especifican strsize y un valor diferente a cero, ustack() asignará la cantidad especificada de espacio de cadena y la utilizará para convertir las direcciones en símbolos directamente desde el núcleo. Esta traducción directa de símbolos de usuario está sólo disponible actualmente para la versión 1.5 y superior de la Máquina virtual de Java. La función de traducción de direcciones en símbolos de Java anota las pilas de usuarios que contienen marcos de Java con la clase de Java y el nombre del método. Si no es posible traducir esos marcos, aparecerán sólo como direcciones hexadecimales.
El siguiente ejemplo realiza un seguimiento de una pila sin espacio de cadena y, por lo tanto, sin traducción de direcciones en símbolos de Java:
# dtrace -n syscall::write:entry'/pid == $target/{ustack(50, 0); exit(0)}' -c "java -version" dtrace: description 'syscall::write:entry' matched 1 probe java version "1.5.0-beta3" Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta3-b58) Java HotSpot(TM) Client VM (build 1.5.0-beta3-b58, mixed mode) dtrace: pid 5312 has exited CPU ID FUNCTION:NAME 0 35 write:entry libc.so.1`_write+0x15 libjvm.so`__1cDhpiFwrite6FipkvI_I_+0xa8 libjvm.so`JVM_Write+0x2f d0c5c946 libjava.so`Java_java_io_FileOutputStream_writeBytes+0x2c cb007fcd cb002a7b cb002a7b cb002a7b cb002a7b cb002a7b cb002a7b cb002a7b cb002a7b cb002a7b cb002a7b cb002a7b cb002a7b cb002a7b cb000152 libjvm.so`__1cJJavaCallsLcall_helper6FpnJJavaValue_ pnMmethodHandle_pnRJavaCallArguments_ pnGThread__v_+0x187 libjvm.so`__1cCosUos_exception_wrapper6FpFpnJJavaValue_ pnMmethodHandle_pnRJavaCallArguments_ pnGThread__v2468_v_+0x14 libjvm.so`__1cJJavaCallsEcall6FpnJJavaValue_nMmethodHandle_ pnRJavaCallArguments_pnGThread __v_+0x28 libjvm.so`__1cRjni_invoke_static6FpnHJNIEnv__pnJJavaValue_ pnI_jobject_nLJNICallType_pnK_jmethodID_pnSJNI_ ArgumentPusher_pnGThread__v_+0x180 libjvm.so`jni_CallStaticVoidMethod+0x10f java`main+0x53d |
Tenga en cuenta que los marcos de pila de C y C++ de la Máquina virtual de Java se presentan de forma simbólica mediante nombres de símbolos "corruptos" de C++ y los marcos de pila de Java se presentan únicamente como direcciones hexadecimales. En el siguiente ejemplo, se muestra una llamada a ustack() con un espacio de cadena diferente a cero.
# dtrace -n syscall::write:entry'/pid == $target/{ustack(50, 500); exit(0)}' -c "java -version" dtrace: description 'syscall::write:entry' matched 1 probe java version "1.5.0-beta3" Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta3-b58) Java HotSpot(TM) Client VM (build 1.5.0-beta3-b58, mixed mode) dtrace: pid 5308 has exited CPU ID FUNCTION:NAME 0 35 write:entry libc.so.1`_write+0x15 libjvm.so`__1cDhpiFwrite6FipkvI_I_+0xa8 libjvm.so`JVM_Write+0x2f d0c5c946 libjava.so`Java_java_io_FileOutputStream_writeBytes+0x2c java/io/FileOutputStream.writeBytes java/io/FileOutputStream.write java/io/BufferedOutputStream.flushBuffer java/io/BufferedOutputStream.flush java/io/PrintStream.write sun/nio/cs/StreamEncoder$CharsetSE.writeBytes sun/nio/cs/StreamEncoder$CharsetSE.implFlushBuffer sun/nio/cs/StreamEncoder.flushBuffer java/io/OutputStreamWriter.flushBuffer java/io/PrintStream.write java/io/PrintStream.print java/io/PrintStream.println sun/misc/Version.print sun/misc/Version.print StubRoutines (1) libjvm.so`__1cJJavaCallsLcall_helper6FpnJJavaValue_ pnMmethodHandle_pnRJavaCallArguments_pnGThread __v_+0x187 libjvm.so`__1cCosUos_exception_wrapper6FpFpnJJavaValue_ pnMmethodHandle_pnRJavaCallArguments_pnGThread __v2468_v_+0x14 libjvm.so`__1cJJavaCallsEcall6FpnJJavaValue_nMmethodHandle _pnRJavaCallArguments_pnGThread__v_+0x28 libjvm.so`__1cRjni_invoke_static6FpnHJNIEnv__pnJJavaValue_pnI _jobject_nLJNICallType_pnK_jmethodID_pnSJNI _ArgumentPusher_pnGThread__v_+0x180 libjvm.so`jni_CallStaticVoidMethod+0x10f java`main+0x53d 8051b9a |
La salida del ejemplo anterior muestra la información de marcos de pila simbólicos para los marcos de pila de Java. Aún hay varios marcos hexadecimales en esta salida, ya que algunas funciones son estáticas y no tienen entradas en la tabla de símbolos de la aplicación. Por lo tanto, no se puede realizar la traducción para estos marcos.
La traducción en símbolos de ustack() para los marcos que no son de Java se produce después de registrar los datos de la pila. Por lo tanto, es posible que se cierre el proceso de usuario antes de que se realice la traducción en símbolos, por lo que la traducción de los marcos de pila no se podría realizar. Si el proceso de usuario se cierra antes de que se realice la traducción en símbolos, dtrace emitirá un mensaje de advertencia, seguido de los marcos de pila hexadecimales, como se muestra en el siguiente ejemplo:
dtrace: failed to grab process 100941: no such process c7b834d4 c7bca85d c7bca1a4 c7bd4374 c7bc2628 8047efc |
Las técnicas para solucionar este problema se describen en el Capítulo 33Seguimiento de procesos de usuario.
Por último, dado que los comandos del depurador de DTrace postmortem no pueden realizar la traducción de los marcos, el uso de ustack() con una directiva de memoria intermedia ring siempre generará datos de ustack() sin formato.
El siguiente programa D muestra un ejemplo de ustack() en el que se deja sin especificar strsize:
syscall::brk:entry /execname == $$1/ { @[ustack(40)] = count(); }
Para ejecutar este ejemplo en el explorador Web de Netscape, .netscape.bin en las instalaciones predeterminadas de Solaris, utilice el siguiente comando:
# dtrace -s brk.d .netscape.bin dtrace: description 'syscall::brk:entry' matched 1 probe ^C libc.so.1`_brk_unlocked+0xc 88143f6 88146cd .netscape.bin`unlocked_malloc+0x3e .netscape.bin`unlocked_calloc+0x22 .netscape.bin`calloc+0x26 .netscape.bin`_IMGCB_NewPixmap+0x149 .netscape.bin`il_size+0x2f7 .netscape.bin`il_jpeg_write+0xde 8440c19 .netscape.bin`il_first_write+0x16b 8394670 83928e5 .netscape.bin`NET_ProcessHTTP+0xa6 .netscape.bin`NET_ProcessNet+0x49a 827b323 libXt.so.4`XtAppProcessEvent+0x38f .netscape.bin`fe_EventLoop+0x190 .netscape.bin`main+0x1875 1 libc.so.1`_brk_unlocked+0xc libc.so.1`sbrk+0x29 88143df 88146cd .netscape.bin`unlocked_malloc+0x3e .netscape.bin`unlocked_calloc+0x22 .netscape.bin`calloc+0x26 .netscape.bin`_IMGCB_NewPixmap+0x149 .netscape.bin`il_size+0x2f7 .netscape.bin`il_jpeg_write+0xde 8440c19 .netscape.bin`il_first_write+0x16b 8394670 83928e5 .netscape.bin`NET_ProcessHTTP+0xa6 .netscape.bin`NET_ProcessNet+0x49a 827b323 libXt.so.4`XtAppProcessEvent+0x38f .netscape.bin`fe_EventLoop+0x190 .netscape.bin`main+0x1875 1 ... |
void jstack(int nframes, int strsize) void jstack(int nframes) void jstack(void)
jstack() es un alias de ustack() que utiliza la opción jstackframes para el valor de número de marcos de pila especificado y para el valor de tamaño de espacio de cadena especificado por la opción jstackstrsize. jstacksize se establece de forma predeterminada en un valor diferente a cero. Como resultado, el uso de jstack() generará una pila con una traducción de marcos de Java.