Process Control Interface in DTrace
One of the strengths of DTrace is its ability to insert probes in user space and in the kernel. The libdtrace
library provides the following functions to consumers to manipulate processes:
struct ps_prochandle *dtrace_proc_create(dtrace_hdl_t *dtp, const char *file, char *const *argv);
struct ps_prochandle *dtrace_proc_grab(dtrace_hdl_t *dtp, pid_t pid, int flags);
void dtrace_proc_release(dtrace_hdl_t *dtp, struct ps_prochandle *P);
void dtrace_proc_continue(dtrace_hdl_t *dtp, struct ps_prochandle *P);
-
dtrace_proc_create
(): Creates a process to run the specified program,file
, with the specified arguments,argv
. When the process is created it is in a stop state so that DTrace can instrument the process before it runs.Note:
Either thedtrace_proc_create
() function or thedtrace_proc_grab
() function must be called before a D program is compiled by the consumer. Certain variables, such as$target
, are set based on values set by these functions. -
dtrace_proc_grab
(): Attaches to an existing process specified byPID
. By default, the process is left in a stop state so that DTrace can instrument the process before it continues to run. You can modify this process by specifying thePGRAB_NOSTOP
flag in theflags
argument. Theflags
argument is passed to thepgrab
() function from thelibproc
library. For more information, see the libproc.h man page. -
dtrace_proc_release
(): Releases a process, which is then grabbed or created by using thedtrace_proc_create
() or thedtrace_proc_grab
() functions. A process that is created by the consumer terminates after being released. -
dtrace_proc_continue
(): Starts the stopped grabbed or created process.
Example 20-3 Using the Process Control Interface
You can perform simple profiling on an application by using the following D program:
pid$target:::entry { @c[probefunc] = count(); }
You can modify the consumer example to perform simple profiling on an application. First, you must either create or grab the process you want to profile. If you want to create a process, add the following code before the calling the dtrace_program_strcompile
() function. Because the consumer example is simple, it takes no arguments and you can pass the remaining arguments to the dtrace_proc_create
() function.
if ((g_pr = dtrace_proc_create(g_dtp, argv[1], &argv[1])) == NULL) fatal("cannot create process");
If you want to grab a existing process, call the dtrace_proc_grab
() function:
if ((g_pr = dtrace_proc_grab(g_dtp, (pid_t)atoi(argv[1]), 0)) == NULL) fatal("cannot grab process");
In each case, you must also call the dtrace_proc_continue
() function after calling the dtrace_go
() function, which starts the process again.
The original consumer loops a specified number of times before printing the gathered data and exiting. If you have grabbed a process, and want to grab a sample profile without waiting for the process to exit, you can use the same loop. However, if you want to follow either a grabbed or created process to its completion, you must modify the loop as follows:
do { dtrace_sleep(g_dtp); if (g_done) { if (dtrace_stop(g_dtp) == -1) fatal("dtrace_stop()"); } switch (dtrace_work(g_dtp, stdout, chew, chewrec, NULL)) { case DTRACE_WORKSTATUS_DONE: g_done = 1; break; case DTRACE_WORKSTATUS_OKAY: break; default: fatal("processing aborted"); } } while (!g_done);
This loop does not terminate by itself when the process exits. The consumer requires a process handler to catch the process termination:
static void prochandler(struct ps_prochandle *P, const char *msg, void *arg) { if (Pstate(P) == PS_UNDEAD) g_done = 1; return; }
You can install this handler as follows:
if (dtrace_handle_proc(g_dtp, &prochandler, NULL) == -1) fatal("failed to install proc handler");
When you run this consumer example, you can see the following output:
# ./consumer-proc-create /bin/ls /
bin devices home media opt root system var
boot etc kernel mnt platform rpool tmp
dev export lib net proc sbin usr
___lwp_private 1
__close 1
__fcntl_syscall 1
[ ... ]
mutex_lock 35
mutex_lock_impl 35
mutex_unlock 35
ferror 44
strlen 45
_ti_bind_clear 54
set_cancel_pending_flag 56
rt_bind_clear 58
strcol 67
__time 70
time 70
__strcoll_C 78
compar 78
strcoll 78
sigon 97
_flsbuf 109
strcmp 113
_realbufend 134
getxfdat 135