Was ist der Unterschied zwischen sigaction und Signal?
Frage
Ich war über einen zusätzlichen Signal-Handler zu einer App haben wir hier hinzufügen, und ich bemerkte, dass der Autor sigaction()
benutzt hatte, die anderen Signal-Handler einzurichten. Ich wollte signal()
verwenden. Folgen Konvention sollte ich sigaction()
aber wenn ich wurde von Grund auf neu zu schreiben, was soll ich wählen?
Lösung
Verwenden Sie sigaction()
, wenn Sie sehr zwingende Gründe haben nicht zu dies tun.
Die signal()
Schnittstelle hat der Antike (und damit Verfügbarkeit) in seiner begünstigen, und es ist in dem C-Standard definiert. Dennoch hat es eine Reihe von unerwünschten Eigenschaften, die sigaction()
vermeidet -., Wenn Sie die Fahnen verwenden explizit treu zu lassen sigaction()
hinzugefügt, um das alte signal()
Verhalten simulieren
- Die
signal()
Funktion nicht (notwendigerweise) blockiert andere Signale von ankommen, während der Strom-Handler ausgeführt wird;sigaction()
kann, bis der Strom-Handler kehrt andere Signale blockieren. - Die
signal()
Funktion (in der Regel) setzt das Signal Aktion zurück zuSIG_DFL
(Standard) für fast alle Signale. Dies bedeutet, dass dersignal()
Handler selbst als seine erste Aktion neu installieren muß. Es öffnet auch ein Fenster der Verwundbarkeit zwischen der Zeit, wenn das Signal erkannt wird und die Prozedur neu installiert wird, in dem, wenn eine zweite Instanz des Signals ankommt, das Standardverhalten (in der Regel beenden, manchmal mit Vorurteilen - auch bekannt als Core-Dump). Tritt - Das genaue Verhalten von
signal()
variiert zwischen Systemen - und die Standards erlauben diese Variationen .
Diese sind im Allgemeinen gute Gründe für sigaction()
statt signal()
. Allerdings ist die Schnittstelle von sigaction()
ist unbestreitbar mehr knifflig.
Unabhängig davon, welche der beiden Sie verwenden, nicht durch die alternativen Signalschnittstellen versucht sein, wie zum Beispiel
sighold()
,
sigignore()
,
sigpause()
und
sigrelse()
.
Sie sind nominell Alternativen zu sigaction()
, aber sie sind nur kaum standardisiert und sind in POSIX für die Rückwärtskompatibilität nicht für ernsthafte Einsatz. Beachten Sie, dass der POSIX-Standard sagt ihr Verhalten in Multi-Threaded-Programmen ist nicht definiert.
Multi-Threaded-Programme und Signale sind eine ganz andere komplizierte Geschichte. AFAIK, beide signal()
und sigaction()
sind OK in Multithreading-Anwendungen.
Die Linux-man-Seite für
signal()
sagt:
Die Auswirkungen von
signal()
in einem Multi-Threaded-Prozess nicht spezifiziert sind.So, ich denke,
sigaction()
sind die einzigen, die sicher in einem Multi-Threaded-Prozess verwendet werden kann.
Das ist interessant. Die Linux-Handbuch Seite ist restriktiver als POSIX in diesem Fall. POSIX spezifiziert für signal()
:
Wird das Verfahren multi-threaded, oder wenn der Prozess Single-Thread ist und eine Signalbehandlungsroutine wird ausgeführt als anderes als das Ergebnis:
- Der Prozess ruft
abort()
,raise()
,kill()
,pthread_kill()
odersigqueue()
ein Signal zu erzeugen, die nicht blockiert ist- Ein anstehendes Signal entsperrt ist und vor dem Aufruf geliefert werden, die nicht blockiert es gibt
das Verhalten ist nicht definiert, wenn die Signalbehandlungsroutine zu jedem anderen Gegenstand als
errno
bezieht sich mit statischer Speicherdauer anders als durch einen Wert an ein Objekt zuweisen alsvolatile sig_atomic_t
deklarierte, oder wenn die Signalbehandlungsroutine ruft eine Funktion in dieser Norm andere definiert als ein der in Signal Konzepte aufgeführten Funktionen .
So POSIX legt das Verhalten von signal()
in einer Multi-Thread-Anwendung.
Dennoch sigaction()
im wesentlichen all Umstände vorzuziehen ist - und tragbarer Multi-Threaded-Code sollte sigaction()
verwenden, wenn es ein triftiger Grund, warum es nicht (wie zum Beispiel „nur Funktionen Verwendung definiert durch Standard C“ - und ja, C11-Code kann mit mehreren mit Gewinde versehen sein). Welches ist im Grunde, was die Öffnung Absatz dieser Antwort auch sagt.
Andere Tipps
Sie sind verschiedene Schnittstellen für OS Signaleinrichtungen. Man sollte mit sigaction es vorziehen, wenn möglich, zu signalisieren, wie das Signal () hat die Implementierung definiert (oft Rennen anfällig) Verhalten und verhält sich anders auf Windows, OS X, Linux und anderen UNIX-Systemen.
Sehen Sie diese Sicherheitshinweis .
Für mich ist diese unter der Linie war genug, um zu entscheiden:
Die sigaction () Funktion liefert ein umfassend und zuverlässige Mechanismus zur Steuerung von Signalen; Neu Anwendungen sollten sigaction () verwenden, eher als Signal ()
http://pubs.opengroup.org/onlinepubs/009695399/ Funktionen / signal.html # tag_03_690_07
Ob Sie von Grunde auf neu fangen oder ein altes Programm zu modifizieren, sigaction sollte die richtige Wahl sein.
Signal () ist Standard C, sigaction () nicht.
Wenn Sie in der Lage, entweder zu verwenden (das heißt, sie ist auf einem POSIX-System), dann verwenden Sie sigaction (); es ist nicht spezifiziert, ob das Signal () den Handler zurücksetzt, dass tragbar zu sein bedeutet, dass Sie Signal verlangen () wieder innerhalb des Handlers. Noch schlimmer ist, dass ein Rennen gibt es: Wenn man zwei Signale in schnellen Folge zu bekommen, und die zweiten geliefert wird, bevor Sie die Prozedur neu zu installieren, müssen Sie die Standardaktion haben, die wahrscheinlich Ihren Prozess sein wird, zu töten. sigaction () , auf der anderen Seite, ist garantiert „zuverlässig“ Signal Semantik zu verwenden. Sie müssen die Prozedur nicht neu installieren, weil es nie zurückgesetzt wird. Mit SA_RESTART, können Sie auch einige Systeme erhalten Anrufe automatisch neu zu starten (so dass Sie nicht manuell müssen für EINTR überprüfen). sigaction () Mehr Optionen und ist zuverlässig, so dass ihr Einsatz gefördert wird.
Psst ... nicht weitersagen ich gesagt, das Sie, aber POSIX verfügt derzeit über eine Funktion bsd_signal (), die wie Signal wirkt (), sondern gibt BSD-Semantik, die es zuverlässig bedeutet. Seine Hauptaufgabe ist alte Anwendungen für die Portierung, die zuverlässige Signale angenommen, und POSIX empfiehlt nicht, es zu benutzen.
Von der signal(3)
Manpage:
Beschreibung
This signal() facility is a simplified interface to the more general sigaction(2) facility.
Sowohl die gleiche zugrunde liegende Anlage aufrufen. Sie sollten vermutlich nicht die Antwort manipulieren die ein einzelnes Signal mit beiden, aber das Mischen sie nichts dazu führen sollte zu brechen ...
würde ich Signal (), da es mehr tragbar ist, zumindest in der Theorie. Ich werde jeden Kommentator vote up, die mit einem modernen System kommen können, die keine POSIX-Kompatibilitätsschicht haben und unterstützt Signal ().
vom GLIBC Dokumentation :
Es ist möglich, sowohl das Signal und sigaction Funktionen zu verwenden, um innerhalb ein einzelnes Programm, aber muss man vorsichtig sein, denn sie können interagieren in etwas seltsame Art und Weise.
Die sigaction Funktion gibt mehr Informationen als das Signal Funktion, so ist der Rückgabewert aus dem Signal die vollen nicht ausdrücken kann Bereich von sigaction Möglichkeiten. Deshalb, wenn Sie verwenden Signal speichern und später eine Aktion wiederherzustellen, kann es nicht in der Lage sein, Wiederherstellung richtig einen Handler, der mit sigaction gegründet wurde.
Zur Vermeidung von Problemen als Folge haben, verwenden Sie immer sigaction zu sparen und Wiederherstellen eines Handlers, wenn Ihr Programm verwendet sigaction überhaupt. Schon seit sigaction ist allgemeiner, kann es richtig jeder speichern und wiederherstellen Aktion, unabhängig davon, ob sie ursprünglich gegründet mit Signal oder sigaction.
Auf einigen Systemen, wenn Sie eine Aktion mit dem Signal aufzubauen und dann untersuchen sie mit sigaction, dass Sie die Handler-Adresse erhalten kann nicht das gleiche sein wie das, was Sie mit dem Signal angegeben. Es kann nicht einmal sein geeignet für die Verwendung mit dem Signal als eine Aktion Argument. Aber Sie können vertrauen auf sie als Argument an sigaction verwenden. Dieses Problem nie passiert auf dem GNU-System.
Also, du bist besser dran eine oder die andere der Mechanismen konsequent in einem einzigen Programm.
Portabilität Hinweis: Die grundlegende Signalfunktion ist eine Funktion von ISO C, während sigaction ist fester Bestandteil des POSIX.1. Wenn du bist besorgt über die Portabilität zu nicht-POSIX-Systeme, dann sollten Sie verwenden, um die Signalfunktion statt.
Copyright (C) 1996-2008 Free Software Foundation, Inc.
Es ist erlaubt, zu kopieren, zu verbreiten und / oder zu modifizieren Dokument unter den Bedingungen der GNU-Lizenz für freie Dokumentation, Version 1.2 oder eine spätere Version von der Free Software veröffentlicht Stiftung; keine unveränderlichen Abschnitte, keinen vorderen Umschlagtext, und ohne hintere Umschlagtexte. Eine Kopie der Lizenz ist im Preis enthalten in der Abschnitt mit dem Titel "GNU Free Documentation License".
Ich würde auch vorschlagen, mit sigaction () über Signal () und möchte einen weiteren Punkt hinzuzufügen. sigaction () gibt Ihnen mehr Möglichkeiten wie pid des Prozesses, (möglich mit der siginfo_t struct) gestorben.
Von Manpage Signal (7)
Verfahren gerichtete Signal kann zu einem geliefert werden eines des Gewindes, das momentan nicht das Signal hat blockiert. Wenn mehr als eine der Fäden hat das Signal deblockiert, dann ist die kernel wählt einen beliebigen Faden, der das Signal zu liefern.
Und ich würde sagen, das "Problem" gibt es für Signal (2 ) und sigaction (2) . Seien Sie also vorsichtig mit Signalen und pthreads.
... und Signal (2) scheint rufen sigaction (2) darunter in Linux mit glibc.