Wie ich letztes mal schon festgestellt habe, arbeitet man bei dtrace mit der Programmiersprache D. Diese Sprache verfügt unter anderem über Datentypen. Ein besonderer Datentyp ist die Aufzählung. Ich will hier mal in einem kleinen Beispiel zeigen wie das funktioniert indem ich dtrace Systemcalls aufzählen lasse.
raichoo@itzkoatl:~# dtrace -n 'syscall:::entry{@[probefunc] = count();}'
dtrace: description 'syscall:::entry' matched 233 probes
^C
fstat64 1
mmap 1
schedctl 1
sigpending 1
nanosleep 2
stat64 2
pset 3
sysconfig 3
c2audit 4
dup 4
fcntl 4
open 4
sigaction 4
brk 6
close 8
gtime 10
clock_gettime 11
writev 12
setcontext 13
lwp_sigmask 15
setitimer 25
p_online 32
portfs 84
write 133
getpid 169
read 171
doorfs 252
lwp_park 320
pollsys 496
ioctl 648
Wollen wir mal der Aufzählung auseinandernehmen:
Mit dem @ zeigen wir an das wir etwas aufzählen wollen. Was das genau ist geben wir in eckigen Klammern an, in diesem Fall ist das die Probefunktion. probefunc ist eine vordefinierte Variable die uns sagt welche Probe "gefeuert" hat. Kommen wir nun zum = count(). Dieser Teil sagt uns WIE wir aufzählen wollen. count() zählt einfach nur wie oft ein Ereignis eingetreten ist. Später werden wir uns genauer unterschiedlichen Aufzählungsarten befassen.
Als Anmerkung bleibt wohl noch zu sagen das dtrace während der Ausführung nichts ausgibt sondern erst wenn wir es mit Strg-C beenden.
Als nächstes wollen wir uns zur Vertiefung noch einen dtrace-Aufruf ansehen der uns anzeigt welche Programme den mmap Systemcall aufrufen und wie oft.
raichoo@itzkoatl:~# dtrace -n 'syscall::mmap:entry{@[execname] = count();}'
dtrace: description 'syscall::mmap:entry' matched 1 probe
^C
dtrace 1
hostname 16
utmp_update 16
bash 33
Hier zählen wir nicht nach probefunc sondern nach execname auf. Außerdem haben wir das Probetupel genauer spezifiziert.
Wir wollen uns jetzt mal genauer angucken was ein Systemcall so macht. Als Beispiel nehme ich hier den open Systemcall. Gucken wir uns die Funktionsdefinition in der dazugehörigen Manpage an:
int open(const char *path, int oflag, /* mode_t mode */);
Diese Informationen werden an den open Syscall übergeben und wenn man ehrlich ist, würde man da eigentlich auch ganz gerne drankommen wenn man dtrace benutzt. Und das geht auch. Wir haben mit execname und probefunc bereits 2 vordefinierte Variablen kennengelernt, jetzt kommen die Variablen arg0 bis arg9 hinzu. Jede gibt uns Zugang zu einem Argument der jeweiligen Probe.
Als Beisiel konstruieren wir hier mal einen dtrace Aufruf der uns anzeigt welche Dateien unser System gerade öffnet.
raichoo@itzkoatl:~# dtrace -n 'syscall::open:entry{printf("%s",copyinstr(arg0));}'
dtrace: description 'syscall::open:entry' matched 1 probe
CPU ID FUNCTION:NAME
0 69268 open:entry /export/home/raichoo/.icons/Neutral_Plus_Inv/cursors/xterm
0 69268 open:entry /export/home/raichoo/.icons/Neutral_Plus_Inv/index.theme
0 69268 open:entry /usr/share/icons/Neutral_Plus_Inv/cursors/xterm
0 69268 open:entry /export/home/raichoo/.icons/Neutral_Plus_Inv/cursors/xterm
0 69268 open:entry /export/home/raichoo/.icons/Neutral_Plus_Inv/index.theme
0 69268 open:entry /usr/share/icons/Neutral_Plus_Inv/cursors/xterm
0 69268 open:entry /export/home/raichoo/.icons/Neutral_Plus_Inv/cursors/xterm
0 69268 open:entry /export/home/raichoo/.icons/Neutral_Plus_Inv/index.theme
0 69268 open:entry /usr/share/icons/Neutral_Plus_Inv/cursors/xterm
0 69268 open:entry /export/home/raichoo/.icons/Neutral_Plus_Inv/cursors/xterm
0 69268 open:entry /export/home/raichoo/.icons/Neutral_Plus_Inv/index.theme
0 69268 open:entry /usr/share/icons/Neutral_Plus_Inv/cursors/xterm
0 69268 open:entry /export/home/raichoo/.icons/Neutral_Plus_Inv/cursors/xterm
Zu printf werde ich hier nicht viel verlieren sondern auf die C Manpage verweisen, da sich die dtrace Funktion genauso verhält. Wir wollen und das erste Argument der Probe ansehen, wie wir oben schon gesehen haben ist das erste Argument const char *path der Pfad der zur öffnenden Datei. Um dieses auszulesen benutzen wir das Probeargument arg0. Da wir uns in einem Systemcall befinden müssen wir die Informationen aus dem Kerneladressraum in den Userspaceaddressraum kopieren, dazu ist die copyinstr() Funktion da.
Eigentlich wollte ich noch etwas auf den FBT-Provider eingehen, aber ich glaube das ist erstmal genug Input für heute, also werde ich mir das für später aufbewahren.
Keine Kommentare:
Kommentar veröffentlichen