Actions enable DTrace to interact with the system outside of the DTrace
framework. The most common actions record data to a DTrace buffer. Other actions
can stop the current process, raise a specific signal on the current process,
or cease tracing. Actions that change the system state are considered destructive
actions. Data recording actions record data to the principal
buffer by default. The principal buffer is present in every DTrace
invocation and is always allocated on a per-CPU basis. Tracing and buffer
allocation can be restricted to a single CPU by using the
cpu
option.
See Chapter 11, Buffers and Buffering, in Solaris
Dynamic Tracing Guide
for more information about DTrace
buffering.
The examples in this section use D expressions that consist of built-in D variables. Some of the most commonly used D variables are listed below:
pid
This variable contains the current process ID.
execname
This variable contains the current executable name.
timestamp
This variable contains the time since boot, expressed in nanoseconds.
curthread
This variable contains a pointer to the kthread_t
structure
that represents the current thread.
probemod
This variable contains the module name of the current probe.
probefunc
This variable contains the function name of the current probe.
probename
This variable contains the name of the current probe.
For a complete list of the built-in variables of the D scripting language, see Variables.
The D scripting language also provides built-in functions that perform
specific actions. You can find a complete list of these built-in functions
at Chapter 10, Actions and Subroutines, in Solaris
Dynamic Tracing Guide
. The trace
function
records the result of a D expression to the trace buffer, as in the following
examples:
trace(pid)
traces the current process ID
trace(execname)
traces the name of the
current executable
trace(curthread->t_pri)
traces the t_pri
field of the current thread
trace(probefunc)
traces the function name
of the probe
To indicate a particular action you want a probe to take, type the name
of the action between {}
characters, as in the following
example.
Example 2.10. Specifying a Probe's Action
# dtrace -n 'readch {trace(pid)}'
dtrace: description 'readch ' matched 4 probes
CPU ID FUNCTION:NAME
0 4036 read:readch 2040
0 4036 read:readch 2177
0 4036 read:readch 2177
0 4036 read:readch 2040
0 4036 read:readch 2181
0 4036 read:readch 2181
0 4036 read:readch 7
...
Since the requested action is trace(pid)
,
the process identification number (PID) appears in the last column of the
output.
Example 2.11. Tracing an Executable Name
# dtrace -m 'ufs {trace(execname)}' dtrace: description 'ufs ' matched 889 probes CPU ID FUNCTION:NAME 0 14977 ufs_lookup:entry ls 0 15748 ufs_iaccess:entry ls 0 15749 ufs_iaccess:return ls 0 14978 ufs_lookup:return ls ... 0 15007 ufs_seek:entry utmpd 0 15008 ufs_seek:return utmpd 0 14963 ufs_close:entry utmpd ^C
Example 2.12. Tracing A System Call's Time of Entry
# dtrace -n 'syscall:::entry {trace(timestamp)}' dtrace: description 'syscall:::entry ' matched 226 probes CPU ID FUNCTION:NAME 0 312 portfs:entry 157088479572713 0 98 ioctl:entry 157088479637542 0 98 ioctl:entry 157088479674339 0 234 sysconfig:entry 157088479767243 ... 0 98 ioctl:entry 157088481033225 0 60 fstat:entry 157088481050686 0 60 fstat:entry 157088481074680 ^C
Example 2.13. Specifying Multiple Actions
To specify multiple actions, list the actions separated by the ;
character.
# dtrace -n 'zfod {trace(pid);trace(execname)}'
dtrace: description 'zfod ' matched 3 probes
CPU ID FUNCTION:NAME
0 4080 anon_zero:zfod 2195 dtrace
0 4080 anon_zero:zfod 2195 dtrace
0 4080 anon_zero:zfod 2195 dtrace
0 4080 anon_zero:zfod 2195 dtrace
0 4080 anon_zero:zfod 2195 dtrace
0 4080 anon_zero:zfod 2197 bash
0 4080 anon_zero:zfod 2207 vi
0 4080 anon_zero:zfod 2207 vi
...
The actions in this section record data to the principal buffer by default, but each action may also be used to record data to speculative buffers. See Speculative Tracing for more details on speculative buffers.
void trace(expression
)
The most basic action is the trace
action,
which takes a D expression as its argument and traces the result to the directed
buffer.
void tracemem(address
, size_tnbytes
)
The tracemem
action copies data from an address
in memory to a buffer . The number of bytes that this action copies is specified
in nbytes
. The address that the data is copied
from is specified in addr
as a D expression. The
buffer that the data is copied to is specified in buf
.
void printf(string format
, ...)
Like the trace
action, the printf
action
traces D expressions. However, the printf
action lets
you control formatting in ways similar to the
printf
(
3C
)
function. Like the printf
function, the parameters consists of a format
string
followed by a variable number of arguments. By default, the arguments are
traced to the directed buffer. The arguments are later formatted for output
by the dtrace
command according to the specified format
string.
For more information on the printf
action, see Chapter 12, Output Formatting, in Solaris
Dynamic Tracing Guide
.
void printa(aggregation
) void printa(stringformat
,aggregation
)
The printa
action enables you to display
and format aggregations. See Chapter 9, Aggregations, in Solaris Dynamic Tracing Guide
for more detail
on aggregations. If a format
value is not provided,
the printa
action only traces a directive to the DTrace
consumer. The consumer that receives that directive processes and displays
the aggregation with the default format. See Chapter 12, Output Formatting, in Solaris Dynamic Tracing Guide
for a more
detailed description of the printa
format string.
void stack(int nframes
)
void stack(void)
The stack
action records a kernel stack trace
to the directed buffer. The depth of the kernel stack is given by the value
given in nframes
. If no value is given for nframes
, the stack action records a number of stack frames specified
by the stackframes
option.
void ustack(intnframes
, intstrsize
) void ustack(intnframes
) void ustack(void)
The ustack
action records a user stack trace
to the directed buffer. The depth of the user stack is equal to the value
specified in nframes
. If there is no value for nframes
, the ustack
action records a number
of stack frames that is specified by the ustackframes
option.
The ustack
action determines the address of the calling
frames when the probe fires. The ustack
action does not
translate the stack frames into symbols until the DTrace consumer processes
the ustack
action at the user level. If a value for strsize
is specified and not zero, the ustack
action
allocates the specified amount of string space and uses it to perform address-to-symbol
translation directly from the kernel.
void jstack(intnframes
, intstrsize
) void jstack(intnframes
) void jstack(void)
The jstack
action is an alias for ustack
that uses the value specified by the jstackframes
option
for the number of stack frames. The jstack
action uses
the value specified by the jstackstrsize
option to determine
the string space size. The jstacksize
action defaults to
a non-zero value.
You must explicitly enable destructive actions in order to use
them. You can enable destructive actions by using the
w
option.
If you attempt to use destructive actions in dtrace without
explicitly enabling them, dtrace fails with a message similar
to the following example:
dtrace: failed to enable 'syscall': destructive actions not allowed
For more information on DTrace actions, including destructive actions, see Chapter 10, Actions and Subroutines, in Solaris Dynamic Tracing Guide .
Some actions are destructive only to a particular process. These
actions are available to users with the dtrace_proc
or dtrace_user
privileges. See Chapter 35, Security, in Solaris Dynamic Tracing Guide
for details
on DTrace security privileges.
When a probe fires with the stop
action enabled,
the process that fired that probe stops upon leaving the kernel. This process
stops in the same way as a process that is stopped by a
proc
(
4
)
action.
void raise(int signal
)
The raise
action sends the specified signal
to the currently running process.
void copyout(void *buf
, uintptr_taddr
, size_tnbytes
)
The copyout
action copies data from a buffer
to an address in memory. The number of bytes that this action copies is specified
in nbytes
. The buffer that the data is copied from
is specified in buf
. The address that the data
is copied to is specified in addr
. That address
is in the address space of the process that is associated with the current
thread.
void copyoutstr(stringstr
, uintptr_taddr
, size_tmaxlen
)
The copyoutstr
action copies a string to
an address in memory. The string to copy is specified in str
.
The address that the string is copied to is specified in addr
.
That address is in the address space of the process that is associated with
the current thread.
Some destructive actions are destructive to the entire system. Use these actions with caution. These actions affect every process on the system and may affect other systems, depending upon the affected system's network services.
void breakpoint(void)
The breakpoint
action induces a kernel breakpoint,
causing the system to stop and transfer control to the kernel debugger. The
kernel debugger will emit a string that denotes the DTrace probe that triggered
the action.
void panic(void)
When a probe with the panic
action triggers,
the kernel panics. This action can force a system crash dump at a time of
interest. You can use this action in conjunction with ring buffering and postmortem
analysis to diagnose a system problem. For more information, see Chapter 11, Buffers and Buffering, in Solaris
Dynamic Tracing Guide
and Chapter 37, Postmortem Tracing, in Solaris Dynamic Tracing Guide
respectively.
void chill(int nanoseconds
)
When a probe with the chill
action triggers,
DTrace spins for the specified number of nanoseconds. The chill
action
is useful for exploring problems related to timing. Because interrupts are
disabled while in DTrace probe context, any use of chill
will
induce interrupt latency, scheduling latency, dispatch latency.