sigreturn, rt_sigreturn - Rückkehr vom Signal-Handler und
Aufräumen des Stack-Frames
Standard-C-Bibliothek (
libc,
-lc)
int sigreturn(…);
Wenn der Linux-Kernel feststellt, dass ein unblockiertes Signal in der
Warteschlange für einen Prozess ist, wird ein neuer Frame auf dem Stack
des Benutzerraums erstellt, wo verschiedene Teile des Prozesskontextes
(Status-Wort des Prozessors, Register, Signalmaske und Einstellungen des
Signalstacks) gespeichert werden, sobald der nächste Übergang
dieses Prozesses zurück in den Benutzerraum stattfindet. Dies kann
beispielsweise bei der Rückkehr aus einem Systemaufruf oder wenn der
Prozess für die CPU neu geplant wird der Fall sein.
Der Kernel sorgt auch dafür, dass während des Übergangs in
den Benutzerraum der Signal-Handler aufgerufen wird und dass nach der
Rückkehr aus dem Handler die Steuerung an ein Codestück im
Benutzerraum abgegeben wird, der häufig »Signaltrampolin«
genannt wird. Der Signaltrampolincode ruft dann wiederum
sigreturn()
auf.
Dieser Aufruf von
sigreturn() macht alle Aktionen für den Aufruf
des Signal Handlers – die Änderung der Signalmaske des
Prozesses, Umschalten der Signal-Stacks (siehe
sigaltstack(2)) –
rückgängig. Mittels der Informationen, die früher auf dem
Benutzer-Stack gespeichert wurden, stellt
sigreturn() die Signalmaske
des Prozesses wieder her, schaltet die Stacks um und stellt den Prozesskontext
(Prozessorschalter und -register, darunter den Stack-Zeiger und den
Instruktions-Zeiger) wieder her, so dass die Ausführung des Prozesses
an dem Punkt fortgesetzt wird, wo er von dem Signal unterbrochen wurde.
sigreturn() kehrt nie zurück.
Viele UNIX-artige Systeme haben einen Systemaufruf
sigreturn() oder etwas
nah verwandtes. Allerdings wird dieser Aufruf nicht in POSIX spezifiziert und
die Details seines Verhaltens unterscheiden sich von System zu System.
sigreturn() existiert nur, um die Implementierung von Signal-Handlern zu
erlauben. Es sollte
niemals direkt aufgerufen werden.
(Tatsächlich wird ein einfacher
sigreturn()-Wrapper in der
GNU-C-Bibliothek einfach -1 zurückliefern und
errno auf
ENOSYS setzen.) Details der an
sigreturn() übergebenen
Argumente (falls vorhanden) hängen von der Architektur ab. (Auf einigen
Architekturen, wie X86-64, akzeptiert
sigreturn() kein Argument, da
alle Informationen, die es benötigt, auf dem Stack-Frame
verfügbar ist, der vorher durch den Kenrel auf dem Stack des
Benutzerraums erstellt wurde.
Früher platzierten UNIX-Systeme den Signaltrampolincode in dem
Benutzerstack. Heutzutage sind die Seiten des Benutzer-Stacks so
geschützt, dass Code-Ausführung verweigert wird. Daher befindet
sich der Signaltrampolincode auf aktuellen Linux-Systemen, abhängig von
der Architektur, entweder im
vdso(7) oder in der C-Bibliothek. In
letzterem Falle informiert die Wrapperfunktion
sigaction(2) der
C-Bibliothek den Kernel über den Ort des Trampolincodes, indem es
dessen Adresse in dem Feld
sa_restorer der Struktur
sigaction
ablegt und den Schalter
SA_RESTORER im Feld
sa_flags setzt.
Die gespeicherte Prozesskontextinformation wird in einer Struktur
ucontext_t (siehe
<sys/ucontext.h>) abgelegt. Diese
Struktur ist innerhalb des Signal-Handlers als drittes Argument eines
Handlers, der über
sigaction(2) mit dem Schalter
SA_SIGINFO etabliert wurde, sichtbar.
Auf einigen anderen UNIX-Systemen unterscheidet sich die Aktion des
Signaltrampolins ein bisschen. Insbesondere übergibt der Kernel auf
einigen Systemen die Steuerung bei der Rückkehr in den
Benutzerraummodus an das Trampolin (statt an den Signal-Handler) und der
Trampolincode ruft den Signal-Handler auf (und ruft dann
sigreturn()
auf, sobald der Handler zurückkehrt).
Der ursprüngliche Systemaufruf hieß
sigreturn(). Mit der
Hinzunahme von Echtzeitsignalen in Linux 2.2 wurde allerdings ein neuer
Systemaufruf
rt_sigreturn() zur Unterstützung eines
vergrößerten Typs
sigset_t hinzugefügt. Die
GNU-C-Bibliothek versteckt diese Details und setzt
rt_sigreturn()
transparent ein, wenn der Kernel dies bereitstellt.
kill(2),
restart_syscall(2),
sigaltstack(2),
signal(2),
getcontext(3),
signal(7),
vdso(7)
Die deutsche Übersetzung dieser Handbuchseite wurde von Martin Schulze
<
[email protected]>, René Tschirley
<
[email protected]>, Martin Eberhard Schauer
<
[email protected]>, Mario Blättermann
<
[email protected]>, Dr. Tobias Quathamer
<
[email protected]> und Helge Kreutzmann <
[email protected]>
erstellt.
Diese Übersetzung ist Freie Dokumentation; lesen Sie die
GNU
General Public License Version 3 oder neuer bezüglich der
Copyright-Bedingungen. Es wird KEINE HAFTUNG übernommen.
Wenn Sie Fehler in der Übersetzung dieser Handbuchseite finden, schicken
Sie bitte eine E-Mail an die
Mailingliste
der Übersetzer