Your Browser is not longer supported

Please use Google Chrome, Mozilla Firefox or Microsoft Edge to view the page correctly
Loading...

{{viewport.spaceProperty.prod}}

sigaction - Signalbehandlung ermitteln oder ändern

&pagelevel(4)&pagelevel

Definition

#include <signal.h>

int sigaction(int sig, const struct sigaction *act, struct sigaction *oact);

Beschreibung

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:

  • SIG_DFL

  • SIG_IGN

  • ein Zeiger auf eine Signalbehandlungsfunktion

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.

Returnwert

0

bei Erfolg.

 

-1

bei Fehler. errno wird gesetzt, um den Fehler anzuzeigen. Es wird keine neue Signalbehandlungsfunktion festgelegt.

Fehler

sigaction() schlägt fehl, wenn gilt:

Erweiterung 

 

EFAULT

act und oact weisen über den zugewiesenen Adressraum des Prozesses hinaus. (Ende)

 

EINVAL

sig ist keine gültige Signalnummer,
oder es wurde versucht, ein Signal abzufangen bzw. zu ignorieren, das nicht abgefangen bzw. ignoriert werden kann,
oder es wurde versucht, die Signalaktion SIG_DFL für ein Signal zu setzen, das nicht abgefangen und/oder ignoriert werden kann.

Hinweise

sigaction() löst signal() ab und sollte vorzugsweise verwendet werden. Insbesondere sollten sigaction() und signal() nicht im selben Prozess für dasselbe Signal verwendet werden.

Wenn dasselbe Signal zweimal angemeldet wird, ist nur die letzte Anmeldung wirksam. Dies gilt insbesondere für aufeinander abgebildete Signale. So ist SIGDVZ auf SIGFPE abgebildet und SIGTIM auf SIGVTALRM. Wenn erst ein Signal eines solchen Paares angemeldet wird und dann das andere, gilt dies als Wiederholung desselben Signals.

Simultan nutzbare Funktionen verhalten sich so, wie es in diesem Handbuch beschrieben ist. Sie können ohne Einschränkung in Signalbehandlungsfunktionen verwendet werden.
Anwendungen müssen dennoch alle Wirkungen dieser Funktionen berücksichtigen, die sich auf Datenstrukturen, Dateien und Prozesszustände beziehen. Insbesondere müssen die Autoren von Anwendungen die Einschränkungen von Interaktionen beachten, die sich bei der Unterbrechung von sleep() ergeben und die Interaktionen zwischen mehreren Dateideskriptoren für eine Dateibeschreibung.

Um Fehler zu vermeiden, die sich aus der Unterbrechung von nicht simultan nutzbaren Funktionsaufrufen ergeben, sollten Anwendungen die Aufrufe solcher Funktionen entweder durch das Blockieren der entsprechenden Signale oder durch die Verwendung von Semaphoren schützen. Dieses Handbuch spricht die allgemeineren Probleme der Synchronisation des Zugriffs auf simultan genutzte Datenstrukturen nicht an. Auch die unterbrechungssicheren Funktionen können zum Beispiel die externe Variable errno verändern; die Signalbehandlungsfunktion wiederum kann den Wert der Variablen sichern und wiederherstellen wollen. Selbstverständlich treffen dieselben Prinzipien auch auf simultan nutzbare Anwendungs-Funktionen und asynchronen Datenzugriff zu.

siglongjmp() ist nicht in der Liste der simultan nutzbaren Funktionen enthalten. Denn der Code, der nach siglongjmp() ausgeführt wird, kann beliebige unsichere Funktionen aufrufen, mit denselben Gefahren, die beim Aufruf dieser unsicheren Funktionen direkt aus der Signalbehandlungsfunktion auftreten. Anwendungen, die siglongjmp() aus Signalbehandlungsfunktionen heraus verwenden, benötigen einen rigorosen Schutz, um portabel zu sein. Viele andere Funktionen, die nicht in der Liste aufgeführt sind, sind traditionell so implementiert, dass sie malloc(), free() oder Funktionen aus stdio.h verwenden; diese Funktionen verwenden Datenstrukturen in einer nicht simultan nutzbaren Weise. Weil jede Kombination verschiedener Funktionen, die eine gemeinsame Datenstruktur verwenden, Probleme bei der simultanen Nutzung verursachen können, definiert dieses Handbuch nicht das Verhalten, wenn eine unsichere Funktion aus einer Signalbehandlungsfunktion heraus aufgerufen wird, die eine unsichere Funktion unterbricht.

Wenn ein Signal auftritt, ohne dass abort(), kill() oder raise() aufgerufen wurden, ist das Verhalten nicht definiert, wenn die Signalbehandlungsfunktion eine X/Open-konforme Bibliotheksfunktion aufruft, die nicht in der obigen Tabelle steht, oder wenn auf ein Objekt im statischen Speicher zugegriffen wird und das keine statische Variable vom Typ volatile sig_atomic_t ist. Wenn ein derartiger Aufruf auf einen Fehler läuft, ist der Wert von errno nicht definiert.

Die Zuordnung zwischen den symbolischen Namen der Signalnummern und ihren numerischen Werten ist nicht standardisiert. Eine Anwendung ist nur portabel, wenn sig die symbolischen Namen verwendet.

Siehe auch

kill(), sigaddset(), sigdelset(), sigfillset(), sigemptyset(), sigismember(), sigprocmask(), sigsuspend(), signal.h, Abschnitt "Signale“.