Dieses Kapitel befasst sich mit den DTrace-Einrichtungen für die nachträgliche (post mortem) Extraktion und Verarbeitung von kernelinternen Daten der DTrace-Verbraucher. Im Fall eines Systemabsturzes können sich die mit DTrace aufgezeichneten Informationen als Schlüssel zur Ursache des Systemausfalls erweisen. Die DTrace-Daten können aus dem Systemspeicherabzug extrahiert und verarbeitet werden und bei der Aufklärung schwerwiegender Systemstörungen behilflich sein. Die Kombination aus diesen Post-Mortem-Fähigkeiten von DTrace und der Ringpufferrichtlinie (siehe Kapitel 11Puffer und Pufferung) macht DTrace zu einer Art Blackbox, wie wir sie aus der kommerziellen Luftfahrt kennen, für Betriebssysteme.
Zum Extrahieren der DTrace-Daten aus einem bestimmten Speicherabzug führen Sie zunächst den Solaris Modular Debugger mdb(1) auf dem gewünschten Speicherabzug aus. Das MDB-Modul, das die DTrace-Funktion enthält, wird automatisch geladen. Näheres über MDB erfahren Sie in Solaris Modular Debugger Guide .
Wenn Sie DTrace-Daten von einem DTrace-Verbraucher extrahieren möchten, müssen Sie zunächst den gewünschten DTrace-Verbraucher angeben. Hierzu führen Sie den MDB-Befehl ::dtrace_state aus:
> ::dtrace_state ADDR MINOR PROC NAME FILE ccaba400 2 - <anonymous> - ccab9d80 3 d1d6d7e0 intrstat cda37078 cbfb56c0 4 d71377f0 dtrace ceb51bd0 ccabb100 5 d713b0c0 lockstat ceb51b60 d7ac97c0 6 d713b7e8 dtrace ceb51ab8 |
Dieser Befehl gibt eine Tabelle der DTrace-Statusstrukturen aus. Jede Zeile der Tabelle enthält folgende Angaben:
Adresse der Statusstruktur
Unternummer des dtrace(7D)-Geräts
Adresse der Prozessstruktur, die auf den DTrace-Verbraucher zutrifft
Name des DTrace-Verbrauchers (oder <anonymous> bei anonymen Verbrauchern)
Name der Dateistruktur für das geöffnete dtrace(7D)-Gerät
Um weitere Informationen über einen bestimmten DTrace-Verbraucher zu erhalten, übergeben Sie ::ps die Adresse der entsprechenden Prozessstruktur:
> d71377f0::ps S PID PPID PGID SID UID FLAGS ADDR NAME R 100647 100642 100647 100638 0 0x00004008 d71377f0 dtrace |
Nachdem Sie einen Verbraucher bestimmt haben, können Sie die Daten jedes unverbrauchten Puffers abrufen, indem Sie ::dtrace die Adresse der Statusstruktur übergeben. Das folgende Beispiel zeigt die Ausgabe des Befehls ::dtrace auf einer anonymen Aktivierung von syscall:::entry mit der Aktion trace(execname):
> ::dtrace_state ADDR MINOR PROC NAME FILE cbfb7a40 2 - <anonymous> - > cbfb7a40::dtrace CPU ID FUNCTION:NAME 0 344 resolvepath:entry init 0 16 close:entry init 0 202 xstat:entry init 0 202 xstat:entry init 0 14 open:entry init 0 206 fxstat:entry init 0 186 mmap:entry init 0 186 mmap:entry init 0 186 mmap:entry init 0 190 munmap:entry init 0 344 resolvepath:entry init 0 216 memcntl:entry init 0 16 close:entry init 0 202 xstat:entry init 0 14 open:entry init 0 206 fxstat:entry init 0 186 mmap:entry init 0 186 mmap:entry init 0 186 mmap:entry init 0 190 munmap:entry init ... |
Der Befehl ::dtrace dcmd behandelt Fehler auf dieselbe Weise wie dtrace(1M). Kommt es während der Ausführung des Verbrauchers zu Auslassungen, Fehlern, spekulativen Auslassungen oder Ähnlichem gibt ::dtrace die gleiche Meldung aus wie dtrace(1M).
::dtrace zeigt die Ereignisse je CPU stets vom ältesten zum neuesten an. Die CPU-Puffer selbst werden in numerischer Reihenfolge wiedergegeben. Sollte es erforderlich sein, die Ereignisse von unterschiedlichen CPUs in sortierter Reihenfolge darzustellen, verfolgen Sie die Variable timestamp.
Durch Angabe der Option -c für ::dtrace lassen sich gezielt nur die Daten einer bestimmten CPU anzeigen:
> cbfb7a40::dtrace -c 1 CPU ID FUNCTION:NAME 1 14 open:entry init 1 206 fxstat:entry init 1 186 mmap:entry init 1 344 resolvepath:entry init 1 16 close:entry init 1 202 xstat:entry init 1 202 xstat:entry init 1 14 open:entry init 1 206 fxstat:entry init 1 186 mmap:entry init ... |
Beachten Sie, dass ::dtrace nur kernelinterne DTrace-Daten verarbeitet. Daten, die aus dem Kernel entnommen und (durch dtrace(1M) oder auf andere Weise) verarbeitet wurden, können nicht mit ::dtrace verarbeitet werden. Um zum Zeitpunkt eines Fehlers stets die größtmögliche Menge an Daten verfügbar zu haben, sollten Sie die Ringpufferrichtlinie verwenden. Weitere Informationen zu Pufferrichtlinien finden Sie in·Kapitel 11Puffer und Pufferung.
Im folgenden Beispiel wird ein sehr kleiner (16 KB) Ringpuffer angelegt und alle Systemaufrufe sowie der Prozess, der sie ausführt, werden aufgezeichnet.
# dtrace -P syscall'{trace(curpsinfo->pr_psargs)}' -b 16k -x bufpolicy=ring dtrace: description 'syscall:::entry' matched 214 probes |
Wenn wir den bei der Ausführung des obigen Befehls erstellten Speicherabzug betrachten, sehen wir eine Ausgabe der Art:
> ::dtrace_state ADDR MINOR PROC NAME FILE cdccd400 3 d15e80a0 dtrace ced065f0 > cdccd400::dtrace CPU ID FUNCTION:NAME 0 139 getmsg:return mibiisa -r -p 25216 0 138 getmsg:entry mibiisa -r -p 25216 0 139 getmsg:return mibiisa -r -p 25216 0 138 getmsg:entry mibiisa -r -p 25216 0 139 getmsg:return mibiisa -r -p 25216 0 138 getmsg:entry mibiisa -r -p 25216 0 139 getmsg:return mibiisa -r -p 25216 0 138 getmsg:entry mibiisa -r -p 25216 0 139 getmsg:return mibiisa -r -p 25216 0 138 getmsg:entry mibiisa -r -p 25216 0 17 close:return mibiisa -r -p 25216 ... 0 96 ioctl:entry mibiisa -r -p 25216 0 97 ioctl:return mibiisa -r -p 25216 0 96 ioctl:entry mibiisa -r -p 25216 0 97 ioctl:return mibiisa -r -p 25216 0 96 ioctl:entry mibiisa -r -p 25216 0 97 ioctl:return mibiisa -r -p 25216 0 96 ioctl:entry mibiisa -r -p 25216 0 97 ioctl:return mibiisa -r -p 25216 0 16 close:entry mibiisa -r -p 25216 0 17 close:return mibiisa -r -p 25216 0 124 lwp_park:entry mibiisa -r -p 25216 1 68 access:entry mdb -kw 1 69 access:return mdb -kw 1 202 xstat:entry mdb -kw 1 203 xstat:return mdb -kw 1 14 open:entry mdb -kw 1 15 open:return mdb -kw 1 206 fxstat:entry mdb -kw 1 207 fxstat:return mdb -kw 1 186 mmap:entry mdb -kw ... 1 13 write:return mdb -kw 1 10 read:entry mdb -kw 1 11 read:return mdb -kw 1 12 write:entry mdb -kw 1 13 write:return mdb -kw 1 96 ioctl:entry mdb -kw 1 97 ioctl:return mdb -kw 1 364 pread64:entry mdb -kw 1 365 pread64:return mdb -kw 1 366 pwrite64:entry mdb -kw 1 367 pwrite64:return mdb -kw 1 364 pread64:entry mdb -kw 1 365 pread64:return mdb -kw 1 38 brk:entry mdb -kw 1 39 brk:return mdb -kw > |
Beachten Sie, dass die neuesten Aufzeichnungen der CPU 1 eine Reihe von write(2)-Systemaufrufen durch einen mdb-kw-Prozess enthalten. Dieses Ergebnis steht wahrscheinlich mit dem Grund für die Systemstörung in Zusammenhang, da Benutzer mit mdb(1) und den Optionen -k und -w Daten oder Text des laufenden Kernels modifizieren können. In diesem Fall stellen die DTrace-Daten zumindest eine interessante Spur, möglicherweise aber die Fehlerursache selbst dar.