Handbuch zur dynamischen Ablaufverfolgung in Solaris

Prozessdestruktive Aktionen

Einige destruktive Aktionen sind nur in Bezug auf einen bestimmten Prozess destruktiv. Diese Aktionen stehen Benutzern mit den Zugriffsrechten dtrace_proc oder dtrace_user zur Verfügung. Ausführliche Informationen zu DTrace-Sicherheitszugriffsrechten finden Sie in Kapitel 35Sicherheit.

stop()

void stop(void)

Die Aktion stop() erzwingt das Anhalten des Prozesses, der den aktivierten Prüfpunkt auslöst, sobald er den Kernel das nächste Mal verlässt. Der Prozess wird dabei wie durch eine proc(4)-Aktion angehalten. Mit dem Dienstprogramm prun(1) können Prozesse, die durch die Aktion stop() angehalten wurden, wieder fortgesetzt werden. Die Aktion stop() ermöglicht das Anhalten eines Prozesses an einem beliebigen DTrace-Prüfpunkt. Sie dient dazu, bestimmte Programmzustände zu erfassen, die mithilfe eines einfachen Haltepunkts nur schwer zu erreichen wären, und dann einen herkömmlichen Debugger wie beispielsweise mdb(1) an den Prozess anzuhängen. Außerdem können Sie mit dem Dienstprogramm gcore(1) den Zustand eines angehaltenen Prozesses für die nachträgliche Analyse in einer Speicherabbilddatei speichern.

raise()

void raise(int Signal)

Die Aktion raise() sendet dem aktuell laufenden Prozess das angegebene Signal. Diese Aktion ist mit dem Befehl kill(1) zum Senden eines Signals an einen Prozess vergleichbar. Mit der Aktion raise() können Sie gezielt an einem genauen Punkt in der Ausführung eines Prozesses ein Signal senden.

copyout()

void copyout(void *Puffer, uintptr_t addr, size_t Anzahl_Byte)

Die Aktion copyout() kopiert Anzahl_Byte aus dem mit Puffer angegebenen Puffer an die mit Adresse angegebene Adresse im Adressraum des Prozesses, zu dem der aktuelle Thread gehört. Sollte die Benutzerraumadresse nicht auf eine gültige, durch Seitenfehler eingelagerte Seite im aktuellen Adressraum zutreffen, wird ein Fehler generiert.

copyoutstr()

void copyoutstr(string Zeichenkette, uintptr_t addr, size_t maxlen)

Die Aktion copyoutstr() kopiert die mit Zeichenkette angegebene Zeichenkette an die mit Adresse angegebene Adresse im Adressraum des Prozesses, zu dem der aktuelle Thread gehört. Sollte die Benutzerraumadresse nicht auf eine gültige, durch Seitenfehler eingelagerte Seite im aktuellen Adressraum zutreffen, wird ein Fehler generiert. Die Länge der Zeichenkette ist auf den mit der Option strsize festgelegten Wert beschränkt. Ausführliche Informationen finden Sie in Kapitel 16Optionen und Tunables .

system()

void system(string Programm, ...) 

Die Aktion system() bewirkt die Ausführung des mit Programm angegebenen Programms, als wäre es der Shell als Eingabe übergeben worden. Die Zeichenkette Programm kann beliebige printf()/printa()-Formatumwandlungen enthalten. Es müssen Argumente angegeben werden, die mit den Formatumwandlungen übereinstimmen. Ausführliche Informationen zu zulässigen Formatumwandlungen finden Sie in Kapitel 12Formatierung der Ausgabe.

Im folgenden Beispiel wird der Befehl date(1) einmal pro Sekunde ausgeführt:


# dtrace -wqn tick-1sec'{system("date")}'
 Tue Jul 20 11:56:26 CDT 2004
 Tue Jul 20 11:56:27 CDT 2004
 Tue Jul 20 11:56:28 CDT 2004
 Tue Jul 20 11:56:29 CDT 2004
 Tue Jul 20 11:56:30 CDT 2004

Das nächste Beispiel zeigt eine etwas komplexere Verwendung der Aktion. Hier werden neben printf()-Konvertierungen in der Programm-Zeichenkette herkömmliche Filtertools wie Pipes eingesetzt:

#pragma D option destructive
#pragma D option quiet

proc:::signal-send
/args[2] == SIGINT/
{
	printf("SIGINT sent to %s by ", args[1]->pr_fname);
	system("getent passwd %d | cut -d: -f5", uid);
}

Die Ausführung des obigen Skripts erzeugt eine Ausgabe wie in folgendem Beispiel:


# ./whosend.d
SIGINT sent to MozillaFirebird- by Bryan Cantrill
SIGINT sent to run-mozilla.sh by Bryan Cantrill
^C
SIGINT sent to dtrace by Bryan Cantrill

Die Ausführung des angegebenen Befehls erfolgt nicht im Kontext des ausgelösten Prüfpunkts, sondern findet statt, wenn der Puffer, der die Angaben zur Aktion system() enthält, auf Benutzerebene verarbeitet wird. Wie und wann diese Verarbeitung erfolgt, hängt von der in Kapitel 11Puffer und Pufferung beschriebenen Pufferungsregel ab. Wenn die Standard-Pufferungsregel gilt, ist die Puffer-Verarbeitungsfrequenz durch die Option switchrate vorgegeben. Wenn Sie wie im nächsten Beispiel die switchrate ausdrücklich auf einen höheren als den Standardwert von 1 Sekunde einstellen, können Sie die der Aktion system() anhaftende Verzögerung beobachten:

#pragma D option quiet
#pragma D option destructive
#pragma D option switchrate=5sec

tick-1sec
/n++ < 5/
{
	printf("walltime  : %Y\n", walltimestamp);
	printf("date      : ");
	system("date");
	printf("\n");
}

tick-1sec
/n == 5/
{
	exit(0);
}

Die Ausführung des obigen Skripts erzeugt eine Ausgabe wie in folgendem Beispiel:


# dtrace -s ./time.d
 walltime  : 2004 Jul 20 13:26:30
date      : Tue Jul 20 13:26:35 CDT 2004

walltime  : 2004 Jul 20 13:26:31
date      : Tue Jul 20 13:26:35 CDT 2004

walltime  : 2004 Jul 20 13:26:32
date      : Tue Jul 20 13:26:35 CDT 2004

walltime  : 2004 Jul 20 13:26:33
date      : Tue Jul 20 13:26:35 CDT 2004

walltime  : 2004 Jul 20 13:26:34
date      : Tue Jul 20 13:26:35 CDT 2004

Beachten Sie, dass die walltime-Werte voneinander abweichen, die date-Werte jedoch identisch sind. Dieses Ergebnis spiegelt die Tatsache wider, dass der Befehl date(1) nicht bei der Aufzeichnung der Aktion system(), sondern erst zur Verarbeitung des Puffers ausgeführt wurde.