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?

War es hilfreich?

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

  1. 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.
  2. Die signal() Funktion (in der Regel) setzt das Signal Aktion zurück zu SIG_DFL (Standard) für fast alle Signale. Dies bedeutet, dass der signal() 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
  3. Das genaue Verhalten von signal() variiert zwischen Systemen - und die Standards erlauben diese Variationen
  4. .

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.

Cornstalks beobachtet :

  

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() oder sigqueue() 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 als volatile 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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top