开发者

Calling C function from DTrace scripts

DTrace is impressive, powerful tracing system originally from Solaris, but it is ported to FreeBSD and Ma开发者_如何学编程c OSX.

DTrace uses a high-level language called D not unlike AWK or C. Here is an example:

io:::start
/pid == $1/
{
    printf("file %s offset %d size %d block %llu\n", args[2]->fi_pathname, 
        args[2]->fi_offset, args[0]->b_bcount, args[0]->b_blkno);
}

Using the command line sudo dtrace -q -s <name>.d <pid> all IOs originated from that process are logged.

My question is if and how it is possible to call custom C functions from a DTrace script to do advanced operations with that tracing data during the tracing itself.


DTrace explicity prevents you from doing anything like this for the same reason that you cannot write a loop in D: if you screw it up in any way, shape, or form, you crash the entire system. When a D probe fires, you are in KERNEL mode, not userland. Let me quote from the "Linux Kernel Module Programming Guide:"

So, you want to write a kernel module. You know C, you've written a number of normal programs to run as processes, and now you want to get to where the real action is, to where a single wild pointer can wipe out your file system and a core dump means a reboot.

That's why you don't want to be playing cowboy in a D probe and why D's restrictions are good for you. =]


you should be able to atleast filter the output of dtrace after each probe fires with pipes.

sudo dtrace -n 'proc:::exec-success { trace(curpsinfo->pr_psargs); }' | perl myscript.pl

myscript.pl:

#!/usr/bin/perl
while (<>){
print $_;
print "another application launched, do something!";
}


It's not possible to call arbitrary C from inside of your probes for the reasons that @Sniggerfardimungus mentions, but presumably you just want to do some operations with the data that's being collected (store it in a database / make some calculations or visualizations with it / etc), and that's totally possible from C (and via wrappers around C in a few other languages).

To do this, use libdtrace (the header is in /usr/include/dtrace.h on my Mac OS X box) or a wrapper for it such as node-libdtrace. The basic idea is that you can build your own consumer of DTrace data (in effect, replacing the dtrace(1m) command line tool), which receives output from whatever script is being run. Once you have the data, you can do whatever you want with it.


Too late to edit my original answer, but you can also use the system() command inside of a DTrace script to spawn a subprocess that runs arbitrary code when an event occurs in DTrace. This is a potentially destructive action, so you have to use the -w command line option or #pragma D option destructive directive in the D script. Note that destructive actions can hang, infinite loop, kill, and otherwise destroy the processes you're probing if you don't use them carefully. (And I would not recommend using the kernel destructive actions unless you really don't care if your system goes down when you mess it up accidentally.)

You could use the script run by system() to call your arbitrary C code (or send a signal to another process to invoke it, etc).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜