sigaction()
erlaubt es dem aufrufenden Prozess, die mit dem Signal sig verbundene Signalbehandlung zu ermitteln oder zu ändern. Mögliche Werte für sig sind in der Datei signal.h
definiert (siehe signal.h
).
Die Struktur sigaction
, die zur Beschreibung von Signalbehandlungen benutzt wird, ist in der Datei signal.h
definiert und beinhaltet zumindest folgende Komponenten:
Komponententyp | Komponentenname | Beschreibung |
void(*)(int)
| sa_handler
| SIG_DFL , SIG_IGN oder ein Zeiger auf eine Signalbehandlungsfunktion.
|
sigset_t
| sa_mask
| Zusätzliche Signalmenge, die während der Abarbeitung der Signalbehandlungsfunktion blockiert werden soll. |
int
| sa_flags
| Spezielle Flags, mit denen das Verhalten von sig beeinflusst werden kann. |
Wenn act kein Nullzeiger ist, zeigt es auf eine Struktur, welche die neue Signalbehandlung für sig beschreibt; d.h. die aktuelle Signalbehandlung wird geändert. In diesem Fall sollte oact auf eine Struktur zeigen, in der die aktuelle Signalbehandlung nach der Rückkehr von sigaction()
abgespeichert wird.
Wenn act ein Nullzeiger ist, bleibt die aktuelle Signalbehandlung unverändert; sie kann mit diesem sigaction
-Aufruf für ein gegebenes Signal ermittelt werden. In diesem Fall kann oact der Nullzeiger sein.
sa_handler
identifiziert die Signalaktion für sig und kann die Werte annehmen, die in signal.h
als Signalaktionen definiert sind (siehe signal.h
).
Wenn sa_handler
eine Signalbehandlungsfunktion festlegt, gibt die Komponente ssa_mask
eine Signalmenge an, die vor Aufruf der Signalbehandlungsfunktion der Signalmaske des Prozesses hinzugefügt wird Die Signale SIGKILL
und SIGSTOP
können nicht blockiert werden; diese Einschränkung wird vom System erzwungen, ohne dass ein Fehler angezeigt wird.
sa_flags
kann verwendet werden, um das Verhalten des angegebenen Signals zu ändern. Die folgenden, in der Datei signal.h
definierten Flag-Bits können in sa_flags
gesetzt werden:
SA_NOCLDSTOP
| Verhindert, dass SIGCHLD erzeugt wird, wenn ein Sohnprozess anhält. |
Erweiterung |
SA_NOCLDWAIT
| Wenn dieses Flag-Bit gesetzt und sig gleich SIGCHLD ist, erzeugt das System keine Zombie-Prozesse, wenn Sohnprozesse des aufrufenden Prozesses beendet werden. Führt der aufrufende Prozess aufeinander folgende wait -Aufrufe aus, wird blockiert, bis alle Sohnprozesse des aufrufenden Prozesses beendet sind; danach wird der Wert -1 zurückgegeben und errno enthält ECHILD . |
SA_NODEFER
| Das Signal wird vom System nicht automatisch blockiert, während es von der Signalbehandlungsfunktion bearbeitet wird. |
SA_RESETHAND
| Wenn diese Option gesetzt ist und das Signal behandelt wird, wird die Disposition des Signals auf SIG_DFL zurückgesetzt und das Signal bei Einsprung in die Signalbehandlungsroutine blockiert (SIGILL , SIGTRAP und SIGPWR können nicht automatisch zurückgesetzt werden, wenn sie empfangen werden; das System erzwingt diese Beschränkung stillschweigend). |
SA_RESTART
| Wenn dieses Flag-Bit gesetzt ist und das Signal behandelt wird, wird ein Systemaufruf, der durch die Ausführung der Signalbehandlungsroutine unterbrochen wird, vom System neu gestartet. Dies geschieht transparent. Ansonsten liefert der Systemaufruf den Fehler EINTR . |
SA_SIGINFO
| Wenn dieses Flag-Bit nicht gesetzt ist und das Signal behandelt wird, wird sig als einziges Argument an die Funktion gesendet, welche die Signale abfängt. Wenn die Option gesetzt ist und das Signal behandelt wird, werden blockierte Signale vom Typ sig zuverlässig für den aufrufenden Prozess in die Warteschlange aufgenommen und zwei zusätzliche Argumente an die Funktion übergeben, die das Signal bearbeitet. Wenn das zweite Argument nicht gleich dem Nullzeiger ist, zeigt es auf eine Struktur vom Typ sigin- fo_t , welche den Grund für das Signal enthält; das dritte Argument zeigt auf eine Struktur vom Typ ucontext_t , welche den Kontext des empfangenden Prozesses zurzeit des Signalempfangs enthält. (Ende) |
Wenn sig gleich SIGCHLD
ist und SA_NOCLDSTOP
nicht in sa_flags
gesetzt ist, wird das Signal SIGCHLD
jedes Mal an den aufrufenden Prozess gesendet, wenn einer seiner Sohnprozesse anhält. Wenn sig gleich SIGCHLD
ist und SA_NOCLDSTOP
in sa_flags
gesetzt ist, wird kein SIGCHLD
-Signal erzeugt.
Wenn ein Signal durch eine mit sigaction()
festgelegte Signalbehandlungsfunktion abgefangen wird, wird für die Laufzeit der Signalbehandlungsfunktion (bzw. bis entweder sigprocmask()
oder sigsuspend()
aufgerufen wird) eine neue Signalmaske berechnet. Diese Maske wird aus der Vereinigung der aktuellen Signalmaske und dem Wert aus ssa_mask
für das gesendete Signal gebildet, einschließlich des gesendeten Signals selbst. Wenn die benutzerdefinierte Signalbehandlungsfunktion normal beendet wird, wird die ursprüngliche Maske wiederhergestellt.
Die aktuelle Signalbehandlung für sig ist solange gültig, bis erneut sigaction()
oder eine der exec
-Funktionen aufgerufen wird.
Wenn die vorherige Signalbehandlung oact für sig durch signal()
festgelegt wurde, sind die Werte der Strukturkomponenten, auf die oact zeigt, nicht spezifiziert und in der speziellen Komponente oact-> sv_handler
befindet sich nicht notwendig derselbe Wert, der vorher von signal()
übergeben wurde. Trotzdem wird, wenn ein Zeiger auf dieselbe Struktur oder eine Kopie davon über act an einen nachfolgenden Aufruf von sigaction()
übergeben wird, die Signalbehandlung so sein, als ob der ursprüngliche Aufruf von signal()
wiederholt worden wäre.
Bei einem Versuch, eine Signalaktion festzulegen, die nicht abgefangen werden kann oder von SIG_DFL
ignoriert wird, wird errno
auf EINVAL
gesetzt.
Allgemeines zur Signalbehandlung
Ein Signal wird für einen Prozess erzeugt (oder an einen Prozess gesendet), wenn das Ereignis, welches das Signal auslöst, erstmalig eintritt. Beispiele für solche Ereignisse sind die Erkennung von Hardware-Fehlern, das Ablaufen von Zeitgebern, Bildschirmaktivitäten oder ein Aufruf von kill()
. Unter bestimmten Umständen erzeugt ein Ereignis Signale für mehrere Prozesse.
Jeder Prozess muss dafür sorgen, dass eine Signalaktion für jedes vom System definierte Signal festgelegt ist (siehe "Signalaktionen“ ). Ein Signal an einen Prozess nennt man zugestellt, wenn die für Prozess und Signal vorgesehene Signalaktion gestartet wird.
In der Zeit zwischen Signalerzeugung und -zustellung heißt ein Signal anstehend. Normalerweise kann diese Zeitspanne nicht von einer Anwendung erkannt werden. Dennoch kann ein Signal von der Zustellung an einen Prozess abgehalten, es kann blockiert werden. Wenn die Signalaktion, die einem blockierten Signal zugeordnet ist, eine andere Signalaktion als das Ignorieren des Signals ist und das Signal für den Prozess erzeugt wurde, bleibt das Signal solange anstehend, bis entweder die Blockierung aufgehoben wird oder die diesem Signal zugeordnete Signalaktion gleich Ignorieren gesetzt wird. Wenn die einem blockierten Signal zugeordnete Signalaktion das Ignorieren des Signals ist und das Signal für den Prozess erzeugt wurde, ist nicht festgelegt, ob das Signal sofort nach der Erzeugung aufgegeben wird oder ob es anstehend bleibt.
Jeder Prozess besitzt eine Signalmaske, die diejenigen Signale definiert, die derzeit vor der Zustellung an diesen Prozess blockiert werden. Die Signalmaske eines Prozesses wird von dessen Vaterprozess initialisiert. sigaction()
, sigprocmask()
und sigsuspend()
steuern die Manipulation dieser Signalmaske.
Die Entscheidung, welche Signalaktion als Antwort auf ein Signal ausgeführt wird, wird zu dem Zeitpunkt getroffen, zu dem das Signal zugestellt wird. Dabei können auch nach dem Zeitpunkt der Erzeugung beliebige Änderungen vorgenommen werden. Diese Entscheidung ist unabhängig von dem Weg, auf dem ein Signal ursprünglich erzeugt wurde. Wenn ein bereits anstehendes Signal erzeugt wird, ist es undefiniert, ob dieses Signal mehr als einmal zugestellt wird. Die Reihenfolge, in der mehrere gleichzeitig anstehende Signale an einen Prozess zugestellt werden, ist nicht festgelegt.
Wenn ein Haltesignal (SIGSTOP
, SIGTSTP
, SIGTTIN
, SIGTTOU
) für einen Prozess erzeugt wird, wird ein evtl. anstehendes Signal des Typs SIGCONT
senden. Umgekehrt werden, sobald ein Signal des Typs SIGCONT
für einen Prozess erzeugt wird, alle noch ausstehenden Haltesignale für diesen Prozess gesendet. Wenn SIGCONT
für einen Prozess erzeugt wird, der angehalten ist, so wird dieser Prozess fortgesetzt, auch wenn das Signal SIGCONT
blockiert ist oder ignoriert wird. Wenn das Signal SIGCONT
blockiert ist und nicht ignoriert wird, bleibt es anstehend bis es entweder freigegeben wird oder bis ein Haltesignal für den Prozess erzeugt wird.
Signalaktionen
Folgende Signalaktionen, können einem Signal zugeordnet werden:
Vor dem Eintritt in main()
sind alle Signale auf SIG_DFL
oder SIG_IGN
gesetzt (siehe signal.h
). Die durch diese Werte beschriebenen Signalaktionen bewirken Folgendes:
SIG_DFL
- voreingestellte Signalbehandlung:
Die voreingestellte Signalbehandlung für die unterstützten Signale wird unter signal.h
beschrieben.
Wenn die voreingestellte Signalbehandlung das Anhalten des Prozesses ist, wird die Ausführung des Prozesses zeitweilig unterbrochen. Wenn ein Prozess anhält, wird ein Signal des Typs SIGCHLD
für dessen Vater-Prozess erzeugt, solange dieser nicht das Flag SA_NOCLDSTOP
gesetzt hat. Solange ein Prozess angehalten ist, werden alle weiteren Signale, die an diesen Prozess gesendet werden, nicht mehr zugestellt, bis der Prozess fortgesetzt wird. Eine Ausnahme bildet das Signal SIGKILL
, das den empfangenden Prozess immer abbricht. Einem Prozess, der Mitglied in einer verwaisten Prozessgruppe ist, ist es nicht erlaubt, als Antwort auf eines der Signale SIGTSTP
, SIGTTIN
oder SIGTTOU
anzuhalten. In den Fällen, in denen die Zustellung eines dieser Signale einen solchen Prozess anhalten würden, wird dieses Signal aufgegeben.
Wenn die Signalbehandlung für ein anstehendes Signal, dessen voreingestellte Signalbehandlung das Ignorieren dieses Signals ist, auf SIG_DFL
gesetzt wird (z.B. SI-GCHLD
), so wird das anstehende Signal aufgegeben, gleichgültig ob es blockiert ist oder nicht.
SIG_IGN
- Signal ignorieren:
Die Zustellung des Signals hat keine Wirkung auf den Prozess. Das Verhalten eines Prozesses ist undefiniert, nachdem dieser eines der Signale SIGFPE
, SIGILL
oder SIGSEGV
ignoriert hat, sofern diese Signale nicht durch kill()
oder raise()
gesendet werden.
Das System erlaubt die Signalaktion SIG_IGN
nicht für die Signale SIGKILL
oder SIGSTOP
. Wenn die Signalaktion für ein anstehendes Signal auf SIG_IGN
gesetzt wird, wird das anstehende Signal aufgegeben, gleichgültig ob es blockiert ist oder nicht.
Wenn ein Prozess die Signalaktion für das Signal SIGCHLD
auf SIG_IGN
setzt, wird das Signal ignoriert.
Zeiger auf Signalbehandlungsfunktion - Signal abfangen:
Bei der Zustellung eines Signals hat der empfangende Prozess eine das Signal abfangende Funktion an einer festgelegten Adresse auszuführen. Nach der Rückkehr aus der Signalbehandlungsfunktion nimmt der Prozess die Ausführung an dem Punkt wieder auf, an dem er unterbrochen wurde.
Die Signalbehandlungsfunktion wird wie eine C-Funktion in der folgenden Art und Weise aufgerufen:
void func (int signo);
func ist die angegebene Signalbehandlungsfunktion und signo die Nummer des Signals, das zugestellt wird.
Das Verhalten eines Prozesses ist nicht definiert, wenn er normal von einer Fehlerbehandlungsfunktion für eines der Signale SIGFPE
, SIGILL
oder SIGSEGV
zurückkehrt, das nicht von kill()
oder von raise()
erzeugt wurde.
Das System verbietet es einem Prozess, die Signale SIGKILL
und SIGSTOP
abzufangen.
Wenn ein Prozess eine Signalbehandlungsfunktion für das Signal
SIGCHLD
einführt, während er einen beendeten Sohnprozess besitzt, auf den er nicht wartet, ist nicht festgelegt, ob ein Signal des Typs SIGCHLD
erzeugt wird, um diesen Sohn-Prozess anzuzeigen.
Wenn Signalbehandlungsfunktionen asynchron zur Prozessausführung aufgerufen werden, ist das Verhalten einiger in diesem Handbuch beschriebener Funktionen nicht definiert, wenn diese aus einer Signalbehandlungsfunktion heraus aufgerufen werden. Die folgende Tabelle listet eine Reihe von Funktionen auf, die entweder simultan nutzbar oder nicht durch Signale unterbrechbar sind. Daher können diese so genannten ssicheren Funktionen ohne Einschränkung von Anwendungen aus Signalbehandlungsfunktionen heraus aufgerufen werden:
Einschränkung
access()
| free()
| raise()
| sysconf()
|
alarm()
| fstat()
| read()
| tcdrain()
|
calloc()
| getegid()
| rename()
| tcflow()
|
cfgetispeed()
| geteuid()
| rmdir()
| tcflush()
|
cfgetospeed()
| getgid()
| setgid()
| tcgetattr()
|
cfsetispeed()
| getgroups()
| setpgid()
| tcgetpgrp()
|
cfsetospeed()
| getpgrp()
| setsid()
| tcsendbreak()
|
chdir()
| getpid()
| setuid()
| tcsetattr()
|
chmod()
| getppid()
| sigaction()
| tcsetpgrp()
|
chown()
| getuid()
| sigaddset()
| time()
|
close()
| kill()
| sigdelset()
| times()
|
creat()
| link()
| sigemptyset()
| umask()
|
dup2()
| lseek()
| sigfillset()
| uname()
|
dup()
| malloc()
| sigismember()
| unlink()
|
execle()
| mkdir()
| signal()
| utime()
|
execve()
| mkfifo()
| sigpending()
| wait()
|
_exit()
| open()
| sigprocmask()
| waitpid()
|
fcntl()
| pathconf()
| sigsuspend()
| write()
|
fork()
| pause()
| sleep()
|
|
fpathconf()
| pipe()
| stat()
|
|
Alle Funktionen, die nicht in der obigen Tabelle aufgeführt sind, gelten als unsicher in Bezug auf Signale. In Gegenwart von Signalen verhalten sich alle X/Open-konformen Funktionen wie definiert, wenn sie von einer Signalbehandlungsfunktion aufgerufen oder unterbrochen werden, mit einer einzigen Ausnahme: Wenn eine unsichere Funktion durch ein Signal unterbrochen wird und die Signalbehandlungsfunktion eine unsichere Funktion aufruft, ist das Verhalten undefiniert.
Wirkung von Signalen auf andere Funktionen
Signale beeinflussen das Verhalten der folgenden Funktionen, wenn sie an einen Prozess gesendet werden, der gerade eine dieser Funktionen ausführt:
catclose()
| fgetwc()
| getgrnam()
| tcdrain()
|
catgets()
| fopen()
| getpass()
| tcsetattr()
|
close()
| fputc()
| getpwnam()
| tmpfile()
|
dup()
| fputwc()
| getpwuid()
| wait()
|
fclose()
| freopen()
| open()
| write()
|
fcntl()
| fseek()
| pause()
|
|
fflush()
| fsync()
| read()
|
|
fgetc()
| getgrgid()
| sigsuspend()
|
|
Dies hat folgende Auswirkungen:
Wenn die Signalbehandlung der Prozessbeendigung dient, wird der Prozess beendet, und die Funktion kehrt nicht zurück.
Wenn die Signalbehandlung dem Anhalten des Prozesses dient, wird er solange angehalten, bis er fortgesetzt oder beendet wird.
Wenn für einen Prozess ein SIGCONT
-Signal erzeugt wird, wird der Prozess an dem Punkt fortgesetzt, an dem der Prozess angehalten wurde.
Wenn die zugehörige Signalbehandlung dem Aufrufen einer Signalbehandlungsfunktion dient, wird die Signalbehandlungsfunktion aufgerufen; in diesem Fall wird die ursprüngliche Funktion von dem Signal unterbrochen.
Wenn die Signalbehandlungsfunktion eine return
-Anweisung ausführt, verhält sich die unterbrochene Funktion genauso, wie es für diese Funktion beschrieben ist.
Signale, die ignoriert werden, beeinflussen das Verhalten einer Funktion nicht.
Signale, die blockiert werden, haben solange keinen Einfluss auf das Verhalten einer Funktion, bis sie zugestellt sind.