In welcher Beziehung steht SIGINT zu den anderen Abschlusssignalen wie SIGTERM, SIGQUIT und SIGKILL?

103

Auf POSIX-Systemen haben Terminierungssignale normalerweise die folgende Reihenfolge (gemäß vielen MAN-Seiten und der POSIX-Spezifikation):

  1. SIGTERM - Bitten Sie höflich um die Beendigung eines Prozesses. Es wird ordnungsgemäß beendet, alle Ressourcen (Dateien, Sockets, untergeordnete Prozesse usw.) bereinigt, temporäre Dateien gelöscht usw.

  2. SIGQUIT - energischere Anfrage. Es wird unansehnlich beendet und bereinigt weiterhin Ressourcen, die unbedingt bereinigt werden müssen, löscht jedoch möglicherweise keine temporären Dateien, schreibt möglicherweise irgendwo Debug-Informationen. Auf einigen Systemen wird auch ein Core-Dump geschrieben (unabhängig davon, ob das Signal von der App abgefangen wird oder nicht).

  3. SIGKILL - energischste Anfrage. Der Prozess wird nicht einmal aufgefordert, etwas zu tun, aber das System bereinigt den Prozess, ob es ihm gefällt oder nicht. Höchstwahrscheinlich wird ein Core Dump geschrieben.

Wie passt SIGINT in dieses Bild? Ein CLI-Prozess wird normalerweise von SIGINT beendet, wenn der Benutzer CRTL + C drückt. Ein Hintergrundprozess kann jedoch auch von SIGINT mit dem Dienstprogramm KILL beendet werden. Was ich in den Spezifikationen oder den Header-Dateien nicht sehen kann, ist, ob SIGINT mehr oder weniger stark als SIGTERM ist oder ob es überhaupt einen Unterschied zwischen SIGINT und SIGTERM gibt.

AKTUALISIEREN:

Die beste Beschreibung der Terminierungssignale, die ich bisher gefunden habe, finden Sie in der GNU LibC-Dokumentation . Es erklärt sehr gut, dass es einen beabsichtigten Unterschied zwischen SIGTERM und SIGQUIT gibt.

Es heißt über SIGTERM:

Es ist der normale Weg, ein Programm höflich um Beendigung zu bitten.

Und es heißt über SIGQUIT:

[...] und erzeugt einen Core-Dump, wenn er den Prozess beendet, genau wie ein Programmfehlersignal. Sie können sich dies als eine Programmfehlerbedingung vorstellen, die vom Benutzer „erkannt“ wurde. [...] Bestimmte Arten von Bereinigungen werden bei der Handhabung von SIGQUIT am besten weggelassen. Wenn das Programm beispielsweise temporäre Dateien erstellt, sollte es die anderen Beendigungsanforderungen durch Löschen der temporären Dateien verarbeiten. Für SIGQUIT ist es jedoch besser, sie nicht zu löschen, damit der Benutzer sie in Verbindung mit dem Core-Dump untersuchen kann.

Und SIGHUP wird auch gut genug erklärt. SIGHUP ist nicht wirklich ein Beendigungssignal, es bedeutet nur, dass die "Verbindung" zum Benutzer unterbrochen wurde, sodass die App nicht erwarten kann, dass der Benutzer weitere Ausgaben liest (z. B. stdout / stderr-Ausgabe), und dass keine Eingabe von der zu erwarten ist Benutzer nicht mehr. Für die meisten Apps bedeutet dies, dass sie besser beendet werden. Theoretisch könnte eine App auch entscheiden, dass sie beim Empfang eines SIGHUP in den Dämonmodus wechselt und nun als Hintergrundprozess ausgeführt wird und die Ausgabe in eine konfigurierte Protokolldatei schreibt. Für die meisten Daemons, die bereits im Hintergrund ausgeführt werden, bedeutet SIGHUP normalerweise, dass sie ihre Konfigurationsdateien erneut überprüfen müssen, sodass Sie sie nach dem Bearbeiten der Konfigurationsdateien an Hintergrundprozesse senden.

Es gibt jedoch keine nützliche Erklärung für SIGINT auf dieser Seite, außer dass es von CRTL + C gesendet wird. Gibt es einen Grund, warum man SIGINT anders als SIGTERM behandeln würde? Wenn ja, aus welchem ​​Grund und wie wäre die Handhabung anders?

Mecki
quelle
1
Gute Frage. Ich vermute, dass ein Teil der historischen Unix-Cruft an der Antwort beteiligt sein würde.
Alex B
Ich weiß, dass diese Frage alt ist, aber falls jemand hierher gekommen ist, um eine umfangreiche Liste von Signalen für Ihr (Linux-) Betriebssystem zu erhalten, können Sie diese durch Eingabe sudo fuser -lan Ihrer Eingabeaufforderung finden. Für mich bringt dies:HUP INT QUIT ILL TRAP ABRT IOT BUS FPE KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT CHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH IO PWR SYS UNUSED
Nick Bull
3
Versuchen Sie auch kill -leine Liste der Signale.
AAAfarmclub

Antworten:

88

SIGTERM und SIGKILL sind für allgemeine Anforderungen zum Beenden dieses Prozesses vorgesehen. SIGTERM (standardmäßig) und SIGKILL (immer) führen zur Beendigung des Prozesses. SIGTERM kann vom Prozess erfasst werden (z. B. damit es seine eigene Bereinigung durchführen kann, wenn es möchte) oder sogar vollständig ignoriert werden. aber SIGKILL kann nicht gefangen oder ignoriert werden.

SIGINT und SIGQUIT sind speziell für Anforderungen vom Terminal vorgesehen: Zur Erzeugung dieser Signale können bestimmte Eingabezeichen zugewiesen werden (abhängig von den Einstellungen der Terminalsteuerung). Die Standardaktion für SIGINT ist dieselbe Art der Prozessbeendigung wie die Standardaktion für SIGTERM und die unveränderliche Aktion für SIGKILL. Die Standardaktion für SIGQUIT ist auch die Prozessbeendigung. Es können jedoch zusätzliche implementierungsdefinierte Aktionen auftreten, z. B. die Generierung eines Core-Dumps. Kann bei Bedarf vom Prozess abgefangen oder ignoriert werden.

SIGHUP soll, wie Sie sagen, anzeigen, dass die Terminalverbindung unterbrochen wurde, und kein Abschlusssignal als solches sein. Die Standardaktion für SIGHUP (wenn der Prozess sie nicht abfängt oder ignoriert) besteht darin, den Prozess auf die gleiche Weise wie SIGTERM usw. zu beenden.

In den POSIX- Definitionen gibt es eine Tabelle, in der signal.hdie verschiedenen Signale sowie ihre Standardaktionen und -zwecke aufgeführt sind, und das Kapitel Allgemeine Terminalschnittstelle enthält ausführlichere Informationen zu den terminalbezogenen Signalen.

Matthew Slattery
quelle
10
Dies ist der entscheidende Punkt: SIGINT und SIGQUIT können vom Terminal aus mit einzelnen Zeichen generiert werden, während das Programm ausgeführt wird. Die anderen Signale müssen irgendwie von einem anderen Programm erzeugt werden (zB durch den Befehl kill). SIGINT ist weniger gewalttätig als SIGQUIT; Letzteres erzeugt einen Core Dump. SIGKILL kann nicht gefangen werden. SIGHUP wird generiert, wenn Ihre Verbindung auflegt (Fenster wird geschlossen usw.). Sie haben also alle unterschiedliche Bedeutungen.
Jonathan Leffler
TTY Demystified enthält einige leicht verdauliche Informationen darüber, wie Signale mit dem tty-Subsystem des Kernels interagieren. Fügt Ihrer Antwort einen Kontext hinzu.
Daniel Näslund
1
Es sieht so aus, als ob die Spezifikationen nicht sehr genau sind, aber ich verstehe, dass SIgint das Programm auffordert, die aktuelle Aktion zu stoppen und nicht unbedingt zu beenden. Für ein Programm, das nur eine Aktion pro Lauf ausführt, die das Beenden impliziert, kann es für ein interaktives Programm mit einer Art Lese-Auswertungs-Druckschleife bedeuten, die aktuelle Auswertung aufzugeben und wieder Benutzereingaben zu lesen. Ich denke, weniger macht das auf Sigint.
BDSL
Welches Signal wird beim Neustart gesendet?
Dan Dascalescu
10

Wie DarkDust feststellte, haben viele Signale die gleichen Ergebnisse, aber Prozesse können ihnen unterschiedliche Aktionen zuordnen, indem sie unterscheiden, wie jedes Signal erzeugt wird. Wenn ich mir den FreeBSD-Kernel-Quellcode (kern_sig.c) ansehe, sehe ich, dass die beiden Signale auf die gleiche Weise behandelt werden, den Prozess beenden und an einen beliebigen Thread geliefert werden.

SA_KILL|SA_PROC,             /* SIGINT */
SA_KILL|SA_PROC,             /* SIGTERM */
Diomidis Spinellis
quelle
9

man 7 signal

Dies ist die praktische nicht normative Manpage des Linux-Manpages-Projekts , in der Sie häufig nach Linux-Signalinformationen suchen möchten.

Version 3.22 erwähnt interessante Dinge wie:

Die Signale SIGKILL und SIGSTOP können nicht abgefangen, blockiert oder ignoriert werden.

und enthält die Tabelle:

Signal     Value     Action   Comment
----------------------------------------------------------------------
SIGHUP        1       Term    Hangup detected on controlling terminal
                              or death of controlling process
SIGINT        2       Term    Interrupt from keyboard
SIGQUIT       3       Core    Quit from keyboard
SIGILL        4       Core    Illegal Instruction
SIGABRT       6       Core    Abort signal from abort(3)
SIGFPE        8       Core    Floating point exception
SIGKILL       9       Term    Kill signal
SIGSEGV      11       Core    Invalid memory reference
SIGPIPE      13       Term    Broken pipe: write to pipe with no
                              readers
SIGALRM      14       Term    Timer signal from alarm(2)
SIGTERM      15       Term    Termination signal
SIGUSR1   30,10,16    Term    User-defined signal 1
SIGUSR2   31,12,17    Term    User-defined signal 2
SIGCHLD   20,17,18    Ign     Child stopped or terminated
SIGCONT   19,18,25    Cont    Continue if stopped
SIGSTOP   17,19,23    Stop    Stop process
SIGTSTP   18,20,24    Stop    Stop typed at tty
SIGTTIN   21,21,26    Stop    tty input for background process
SIGTTOU   22,22,27    Stop    tty output for background process

ActionDies fasst das Signal zusammen , das zB SIGQUIT von SIGQUIT unterscheidet, da SIGQUIT Aktion Coreund SIGINT hat Term.

Die Aktionen sind im selben Dokument dokumentiert:

The entries in the "Action" column of the tables below specify the default disposition for each signal, as follows:

Term   Default action is to terminate the process.

Ign    Default action is to ignore the signal.
Core   Default action is to terminate the process and dump core (see core(5)).
Stop   Default action is to stop the process.
Cont   Default action is to continue the process if it is currently stopped.

Ich kann aus Sicht des Kernels keinen Unterschied zwischen SIGTERM und SIGINT erkennen, da beide Aktionen haben Termund beide abgefangen werden können. Es scheint, dass dies nur eine "Unterscheidung zwischen allgemeinen Verwendungskonventionen" ist:

  • SIGINT ist das, was passiert, wenn Sie STRG-C vom Terminal aus ausführen
  • SIGTERM ist das Standardsignal von kill

Einige Signale sind ANSI C und andere nicht

Ein wesentlicher Unterschied ist, dass:

  • SIGINT und SIGTERM sind ANSI C und daher portabler
  • SIGQUIT und SIGKILL nicht

Sie sind in Abschnitt "7.14 Signalbehandlung" des C99-Entwurfs N1256 beschrieben :

  • SIGINT-Empfang eines interaktiven Aufmerksamkeitssignals
  • SIGTERM eine an das Programm gesendete Beendigungsanforderung

Das macht SIGINT zu einem guten Kandidaten für eine interaktive Strg + C.

POSIX 7

POSIX 7 dokumentiert die Signale mit dem signal.hHeader: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html

Diese Seite enthält auch die folgende Tabelle von Interesse, in der einige der Dinge erwähnt werden, die wir bereits gesehen haben man 7 signal:

Signal    Default Action   Description
SIGABRT   A                Process abort signal.
SIGALRM   T                Alarm clock.
SIGBUS    A                Access to an undefined portion of a memory object.
SIGCHLD   I                Child process terminated, stopped,
SIGCONT   C                Continue executing, if stopped.
SIGFPE    A                Erroneous arithmetic operation.
SIGHUP    T                Hangup.
SIGILL    A                Illegal instruction.
SIGINT    T                Terminal interrupt signal.
SIGKILL   T                Kill (cannot be caught or ignored).
SIGPIPE   T                Write on a pipe with no one to read it.
SIGQUIT   A                Terminal quit signal.
SIGSEGV   A                Invalid memory reference.
SIGSTOP   S                Stop executing (cannot be caught or ignored).
SIGTERM   T                Termination signal.
SIGTSTP   S                Terminal stop signal.
SIGTTIN   S                Background process attempting read.
SIGTTOU   S                Background process attempting write.
SIGUSR1   T                User-defined signal 1.
SIGUSR2   T                User-defined signal 2.
SIGTRAP   A                Trace/breakpoint trap.
SIGURG    I                High bandwidth data is available at a socket.
SIGXCPU   A                CPU time limit exceeded.
SIGXFSZ   A                File size limit exceeded.

BusyBox init

Die Standardeinstellung 1.29.2 von BusyBox reboot sendet ein SIGTERM an Prozesse, schläft für eine Sekunde und sendet dann SIGKILL. Dies scheint eine gemeinsame Konvention für verschiedene Distributionen zu sein.

Wenn Sie ein BusyBox-System herunterfahren mit:

reboot

Es sendet ein Signal an den Init-Prozess.

Dann ruft der Init-Signal-Handler auf:

static void run_shutdown_and_kill_processes(void)
{
    /* Run everything to be run at "shutdown".  This is done _prior_
     * to killing everything, in case people wish to use scripts to
     * shut things down gracefully... */
    run_actions(SHUTDOWN);

    message(L_CONSOLE | L_LOG, "The system is going down NOW!");

    /* Send signals to every process _except_ pid 1 */
    kill(-1, SIGTERM);
    message(L_CONSOLE, "Sent SIG%s to all processes", "TERM");
    sync();
    sleep(1);

    kill(-1, SIGKILL);
    message(L_CONSOLE, "Sent SIG%s to all processes", "KILL");
    sync();
    /*sleep(1); - callers take care about making a pause */
}

welches auf dem Terminal druckt:

The system is going down NOW!
Sent SIGTERM to all processes
Sent SIGKILL to all processes

Hier ist ein minimales konkretes Beispiel dafür .

Vom Kernel gesendete Signale

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
quelle
8

Nach einer schnellen Google-Suche nach sigint vs sigterm scheint der einzige beabsichtigte Unterschied zwischen den beiden darin zu bestehen, ob es durch eine Tastenkombination oder durch einen expliziten Aufruf von initiiert wurde kill.

Infolgedessen können Sie beispielsweise Sigint abfangen und etwas Besonderes damit tun, da Sie wissen, dass es wahrscheinlich über eine Tastenkombination gesendet wurde. Aktualisieren Sie möglicherweise den Bildschirm oder etwas anderes, anstatt zu sterben (nicht empfohlen, da die Leute erwarten ^C, das Programm zu beenden, nur ein Beispiel).

Ich habe auch gelernt, dass ^\Sigquit gesendet werden sollte, das ich selbst verwenden kann. Sieht sehr nützlich aus.

Jonathan
quelle
3

Mit kill(sowohl dem Systemaufruf als auch dem Dienstprogramm) können Sie fast jedes Signal an jeden Prozess senden, sofern Sie über die Berechtigung verfügen. Ein Prozess kann nicht unterscheiden, wie ein Signal zum Leben erweckt wurde und wer es gesendet hat.

Davon abgesehen soll SIGINT wirklich die Strg-C-Unterbrechung singalisieren, während SIGTERM das allgemeine Terminalsignal ist. Es gibt kein Konzept dafür, dass ein Signal "stärker" ist, mit der einzigen Ausnahme, dass es Signale gibt, die nicht blockiert oder verarbeitet werden können (SIGKILL und SIGSTOP laut Manpage).

Ein Signal kann nur "stärker" sein als ein anderes Signal, wenn es darum geht, wie ein Empfangsprozess mit dem Signal umgeht (und wie die Standardaktion für dieses Signal lautet). Beispielsweise führen sowohl SIGTERM als auch SIGINT standardmäßig zur Beendigung. Wenn Sie SIGTERM jedoch ignorieren, wird Ihr Prozess nicht beendet, während SIGINT dies weiterhin tut.

DarkDust
quelle
0

Mit Ausnahme einiger weniger Signale können Signalhandler die verschiedenen Signale abfangen oder das Standardverhalten beim Empfang eines Signals kann geändert werden. Weitere signal(7)Informationen finden Sie in der Manpage.

Ignacio Vazquez-Abrams
quelle
Ja, aber wenn ich die "Bedeutung" eines Singnals nicht kenne, ist es sinnlos, das Signal zu erfassen, da ich nicht weiß, was ich in meiner Anwendung tun soll. GNU C erklärt zB den Unterschied zwischen SIGQUIT und SIGTERM. Aber es gibt wenig Informationen über SIGINT: gnu.org/s/libc/manual/html_node/Termination-Signals.html
Mecki
"Das SIGINTSignal (" Programmunterbrechung ") wird gesendet, wenn der Benutzer das INTR-Zeichen (normalerweise C-c) eingibt ." "SIGINT 2 Term Interrupt von der Tastatur" Sie drücken Strg-C, SIGINTwird gesendet. Der Prozess stirbt normalerweise ab. Was gibt es noch zu geben?
Ignacio Vazquez-Abrams
Möglicherweise gibt es eine Beschreibung der Absicht, die der Programmierer annehmen sollte, wenn der Benutzer Strg-C drückt, dh die Semantik der Nachricht. Als Beispiel macht die HTTP-Spezifikation deutlich, dass der Server beim Senden einer GET-Anforderung nicht davon ausgehen sollte, dass er etwas anderes tun möchte, als eine Antwort zurückzusenden.
BDSL