Chapter 3 Scripting With the D Language
This chapter discusses the basic information that you need to start
writing your own D language scripts.
Writing D Scripts
Complex sets of DTrace probes can become difficult to manage on the
command line. The dtrace command supports scripts. You
can specify a script by passing the -s option, along with
the script's file name, to the dtrace command. You can
also create executable DTrace interpreter files. A DTrace interpreter file
always begins with the line #!/usr/sbin/dtrace -s.
Executable D Scripts
This example script, named syscall.d, traces the
executable name every time the executable enters each system call:
syscall:::entry
{
trace(execname);
}
Note that the filename ends with a .d suffix. This is the conventional
ending for D scripts. You can run this script off the DTrace command line
with the following command:
# dtrace -s syscall.d
dtrace: description 'syscall ' matched 226 probes
CPU ID FUNCTION:NAME
0 312 pollsys:entry java
0 98 ioctl:entry dtrace
0 98 ioctl:entry dtrace
0 234 sysconfig:entry dtrace
0 234 sysconfig:entry dtrace
0 168 sigaction:entry dtrace
0 168 sigaction:entry dtrace
0 98 ioctl:entry dtrace
^C
You can run the script by entering the filename at the command line
by following two steps. First, verify that the first line of the file invokes
the interpreter. The interpreter invocation line is #!/usr/sbin/dtrace
-s. Then set the execute permission for the file.
Example 3–1 Running a D Script from the Command Line
# cat syscall.d
#!/usr/sbin/dtrace -s
syscall:::entry
{
trace(execname);
}
# chmod +x syscall.d
# ls -l syscall.d
-rwxr-xr-x 1 root other 62 May 12 11:30 syscall.d
# ./syscall.d
dtrace: script './syscall.d' matched 226 probes
CPU ID FUNCTION:NAME
0 98 ioctl:entry dtrace
0 98 ioctl:entry dtrace
0 312 pollsys:entry java
0 312 pollsys:entry java
0 312 pollsys:entry java
0 98 ioctl:entry dtrace
0 98 ioctl:entry dtrace
0 234 sysconfig:entry dtrace
0 234 sysconfig:entry dtrace
^C
D Literal Strings
The D language supports literal strings. DTrace represents strings
as an array of characters terminated by a null byte. The visible part of the
string varies in length depending on the location of the null byte. DTrace
stores each string in a fixed-size array to ensure that each probe traces
a consistent amount of data. Strings cannot exceed the length of the predefined
string limit. The limit can be modified in your D program or on the dtrace command line by tuning the strsize option. Refer
to Chapter 16, Options and Tunables, in Solaris
Dynamic Tracing Guide for more information on tunable
DTrace options. The default string limit is 256 bytes.
The D language provides an explicit string type
rather than using the type char * to refer to strings.
See Chapter 6, Strings, in Solaris Dynamic
Tracing Guide for more information about D literal strings.
Example 3–2 Using D Literal Strings With The trace() Function
# cat string.d
#!/usr/sbin/dtrace -s
fbt::bdev_strategy:entry
{
trace(execname);
trace(" is initiating a disk I/O\n");
}
The \n symbol at the end of the literal string produces
a new line. To run this script, enter the following command:
# dtrace -s string.d
dtrace: script 'string.d' matched 1 probes
CPU ID FUNCTION:NAME
0 9215 bdev_strategy:entry bash is initiating a disk I/O
0 9215 bdev_strategy:entry vi is initiating a disk I/O
0 9215 bdev_strategy:entry vi is initiating a disk I/O
0 9215 bdev_strategy:entry sched is initiating a disk I/O
^C
The -q option of the dtrace command
only records the actions that are explicitly stated in the script or command
line invocation. This option suppresses the default output that the dtrace command normally produces.
# dtrace -q -s string.d
ls is initiating a disk I/O
cat is initiating a disk I/O
fsflush is initiating a disk I/O
vi is initiating a disk I/O
^C
Creating D Scripts That Use Arguments
You can use the dtrace command to create executable
interpreter files. The file must have execute permission. The initial line
of the file must be #!/usr/sbin/dtrace -s. You can specify
other options to the dtrace command on this line. You must
specify the options with only one dash (-). List the s option last, as in the following example.
You can specify options for the dtrace command by
using #pragma lines in the D script, as in the following
D fragment:
# cat -n mem2.d
1 #!/usr/sbin/dtrace -s
2
3 #pragma D option quiet
4 #pragma D option verbose
5
6 vminfo:::
...
|
The following table lists the option names that you can use in #pragma lines.
Table 3–1 DTrace Consumer Options
|
Option Name
|
Value
|
dtrace Alias
|
Description
|
|
aggrate
|
time
|
|
Rate of aggregation reading
|
|
aggsize
|
size
|
|
Aggregation buffer size
|
|
bufresize
|
auto or manual
|
|
Buffer resizing policy
|
|
bufsize
|
size
|
-b
|
Principal buffer size
|
|
cleanrate
|
time
|
|
Cleaning rate
|
|
cpu
|
scalar
|
-c
|
CPU on which to enable tracing
|
|
defaultargs
|
—
|
|
Allow references to unspecified macro arguments
|
|
destructive
|
—
|
-w
|
Allow destructive actions
|
|
dynvarsize
|
size
|
|
Dynamic variable space size
|
|
flowindent
|
—
|
-F
|
Indent function entry and prefix with ->; unindent
function return and prefix with <-
|
|
grabanon
|
—
|
-a
|
Claim anonymous state
|
|
jstackframes
|
scalar
|
|
Number of default stack frames jstack()
|
|
jstackstrsize
|
scalar
|
|
Default string space size for jstack()
|
|
nspec
|
scalar
|
|
Number of speculations
|
|
quiet
|
—
|
-q
|
Output only explicitly traced data
|
|
specsize
|
size
|
|
Speculation buffer size
|
|
strsize
|
size
|
|
String size
|
|
stackframes
|
scalar
|
|
Number of stack frames
|
|
stackindent
|
scalar
|
|
Number of whitespace characters to use when indenting stack() and ustack() output
|
|
statusrate
|
time
|
|
Rate of status checking
|
|
switchrate
|
time
|
|
Rate of buffer switching
|
|
ustackframes
|
scalar
|
|
Number of user stack frames
|
A D script can refer to a set of built in macro variables. These macro
variables are defined by the D compiler.
-
$[0-9]+
-
Macro arguments
-
$egid
-
Effective group-ID
-
$euid
-
Effective user-ID
-
$gid
-
Real group-ID
-
$pid
-
Process ID
-
$pgid
-
Process group ID
-
$ppid
-
Parent process ID
-
$projid
-
Project ID
-
$sid
-
Session ID
-
$target
-
Target process ID
-
$taskid
-
Task ID
-
$uid
-
Real user-ID
Example 3–3 PID Argument Example
This example passes the PID of a running vi process
to the syscalls2.d D script. The D script terminates
when the vi command exits.
# cat -n syscalls2.d
1 #!/usr/sbin/dtrace -qs
2
3 syscall:::entry
4 /pid == $1/
5 {
6 @[probefunc] = count();
7 }
8 syscall::rexit:entry
9 {
10 exit(0);
11 }
# pgrep vi
2208
# ./syscalls2.d 2208
rexit 1
setpgrp 1
creat 1
getpid 1
open 1
lstat64 1
stat64 1
fdsync 1
unlink 1
close 1
alarm 1
lseek 1
sigaction 1
ioctl 1
read 1
write 1
|
DTrace Built-in Variables
The following list includes all of the built-in variables for the DTrace
framework.
-
int64_t arg0, ..., arg9
-
The first ten input arguments to a probe represented as raw
64-bit integers. If fewer than ten arguments are passed to the current probe,
the remaining variables return zero.
-
args[]
-
The typed arguments to the current probe, if any. The args[] array is accessed using an integer index, but each element is defined
to be the type corresponding to the given probe argument. For example, if
the args[] array is referenced by a read(2) system call probe, args[0] is of
type int, args[1] is of type void
*, and args[2] is of type size_t.
-
uintptr_t caller
-
The program counter location of the current thread just before
entering the current probe.
-
chipid_t chip
-
The CPU chip identifier for the current physical chip. See Chapter 26, sched Provider, in Solaris
Dynamic Tracing Guide for more information.
-
processorid_t cpu
-
The CPU identifier for the current CPU. See Chapter 26, sched Provider, in Solaris
Dynamic Tracing Guide for more information.
-
cpuinfo_t *curcpu
-
The CPU information for the current CPU. See Chapter 26, sched Provider, in Solaris
Dynamic Tracing Guide for more information.
-
lwpsinfo_t *curlwpsinfo
-
The lightweight process (LWP) state of the LWP associated
with the current thread. This structure is described in further detail in
the proc(4) man page.
-
psinfo_t *curpsinfo
-
The process state of the process associated with the current
thread. This structure is described in further detail in the This structure
is described in further detail in the proc(4) man page.
-
kthread_t *curthread
-
The address of the operating system kernel's internal data
structure for the current thread, the kthread_t. The kthread_t is defined in <sys/thread.h>. Refer
to Solaris Internals for more information on this variable
and other operating system data structures.
-
string cwd
-
The name of the current working directory of the process associated
with the current thread.
-
uint_t epid
-
The enabled probe ID (EPID) for the current probe. This integer
uniquely identifiers a particular probe that is enabled with a specific predicate
and set of actions.
-
int errno
-
The error value returned by the last system call executed
by this thread.
-
string execname
-
The name that was passed to exec(2) to execute the current process.
-
gid_t gid
-
The real group ID of the current process.
-
uint_t id
-
The probe ID for the current probe. This ID is the system-wide
unique identifier for the probe as published by DTrace and listed in the output
of dtrace -l.
-
uint_t ipl
-
The interrupt priority level (IPL) on the current CPU at the
time that the probe fires. Refer to Solaris Internals for
more information on interrupt levels and interrupt handling in the Solaris
operating system kernel.
-
lgrp_id_t lgrp
-
The locality group ID for the latency group of which the current
CPU is a member. See Chapter
26, sched Provider, in Solaris Dynamic Tracing Guide for more information
on CPU management in DTrace. See Chapter 4, Locality Group
APIs, in Programming Interfaces Guide for
more information about locality groups.
-
pid_t pid
-
The process ID of the current process.
-
pid_t ppid
-
The parent process ID of the current process.
-
string probefunc
-
The function name portion of the current probe's description.
-
string probemod
-
The module name portion of the current probe's description.
-
string probename
-
The name portion of the current probe's description.
-
string probeprov
-
The provider name portion of the current probe's description.
-
psetid_t pset
-
The processor set ID for the processor set that contains the
current CPU. See Chapter
26, sched Provider, in Solaris Dynamic Tracing Guide for more information.
-
string root
-
The name of the root directory of the process associated with
the current thread.
-
uint_t stackdepth
-
The current thread's stack frame depth at probe firing time.
-
id_t tid
-
The thread ID of the current thread. For threads that are
associated with user processes, this value is equal to the result of a call
to pthread_self(3C).
-
uint64_t timestamp
-
The current value of a nanosecond timestamp counter. This
counter increments from an arbitrary point in the past and should only be
used for relative computations.
-
uid_t uid
-
The real user ID of the current process.
-
uint64_t uregs[]
-
The current thread's saved user-mode register values at probe
firing time. Use of the uregs[] array is discussed in Chapter 33, User Process Tracing, in Solaris
Dynamic Tracing Guide.
-
uint64_t vtimestamp
-
The current value of a nanosecond timestamp counter. The counter
is virtualized to the amount of time that the current thread has been running
on a CPU. The counter does not include the time that is spent in DTrace predicates
and actions. This counter increments from an arbitrary point in the past and
should only be used for relative time computations.
-
uint64_t walltimestamp
-
The current number of nanoseconds since 00:00 Universal Coordinated
Time, January 1, 1970.