2010-10-28 8 views
77

Sui sistemi POSIX, segnali di terminazione di solito hanno il seguente ordine (secondo molte pagine di manuale e POSIX Spec):In che modo SIGINT si riferisce agli altri segnali di terminazione?

  1. SIGTERM - cortesemente chiedere un processo per terminare. Termina con grazia, pulendo tutte le risorse (file, prese, processi figlio, ecc.), Cancellando file temporanei e così via.

  2. SIGQUIT - richiesta più valida. Dovrà terminare in modo ingiustificato, ripulendo comunque le risorse che devono assolutamente essere pulite, ma forse non eliminare i file temporanei, magari scrivere da qualche parte informazioni di debug; su alcuni sistemi verrà scritto anche un core dump (indipendentemente dal fatto che il segnale venga catturato dall'app o meno).

  3. SIGKILL - richiesta più valida. Il processo non viene nemmeno chiesto di fare nulla, ma il sistema pulirà il processo, che sia così o meno. Molto probabilmente viene scritto un dump principale.

Come si inserisce SIGINT in quell'immagine? Un processo CLI viene solitamente terminato da SIGINT quando l'utente preme CRTL + C, tuttavia un processo in background può anche essere terminato da SIGINT usando l'utilità KILL. Quello che non posso vedere nelle specifiche o nei file di intestazione è se SIGINT è più o meno potente di SIGTERM o se c'è qualche differenza tra SIGINT e SIGTERM.

UPDATE:

La migliore descrizione dei segnali di terminazione che ho trovato finora è nel GNU LibC Documentation. Spiega molto bene che esiste una differenza tra SIGTERM e SIGQUIT.

che dice di SIGTERM:

E 'il modo normale di chiedere gentilmente un programma per terminare.

E dice di SIGQUIT:

[...] e produce un core dump quando si termina il processo, proprio come un segnale di errore di programma. Si può pensare a questo come una condizione di errore del programma "rilevata" dall'utente. [...] Alcuni tipi di pulizie sono meglio omessi nella gestione di SIGQUIT. Ad esempio, se il programma crea file temporanei, deve gestire le altre richieste di terminazione eliminando i file temporanei . Ma è meglio per SIGQUIT non cancellarli, in modo che l'utente possa esaminarli nella congiunzione con il core dump.

E SIGHUP è anche spiegato abbastanza bene. SIGHUP non è in realtà un segnale di terminazione, significa solo che la "connessione" all'utente è andata persa, quindi l'app non può aspettarsi che l'utente legga ulteriori output (es. Output stdout/stderr) e non ci sono input da aspettarsi dal utente ancora. Per la maggior parte delle app significa che è meglio smettere. In teoria, un'app potrebbe anche decidere di passare alla modalità daemon quando viene ricevuto un SIGHUP e ora viene eseguito come processo in background, scrivendo l'output in un file di registro configurato. Per la maggior parte dei daemon già in esecuzione in background, SIGHUP di solito significa che devono riesaminare i loro file di configurazione, in modo da inviarlo ai processi in background dopo aver modificato i file di configurazione.

Tuttavia non esiste alcuna spiegazione utile di SIGINT su questa pagina, oltre a quella inviata da CRTL + C. C'è qualche ragione per cui si dovrebbe gestire SIGINT in modo diverso rispetto a SIGTERM? In caso affermativo, quale sarebbe la ragione e come sarebbe diversa la gestione?

+1

Buona domanda. Sospetto che alcuni degli storici Unix cruft siano coinvolti nella risposta. –

+0

So che questa domanda è vecchia, ma nel caso qualcuno venisse qui per una lunga lista di segnali per il proprio sistema operativo (Linux), è possibile trovarli digitando 'sudo fuser -l' sul prompt dei comandi. Per me viene visualizzato: 'HUP INT QUIT ILL TRAP ABRT IOT BUS FPE KILL USR1 SEGV USR2 TUBO ALRM STKFLT CHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH IO PWR SYS UNUSED' –

+1

Prova anche 'kill -l' per una lista di segnali. – AAAfarmclub

risposta

58

SIGTERM e SIGKILL sono destinati per l'uso generale "terminare questo processo" richieste. SIGTERM (per impostazione predefinita) e SIGKILL (sempre) causeranno la chiusura del processo. SIGTERM può essere catturato dal processo (ad esempio in modo che possa fare la sua pulizia se lo desidera), o addirittura ignorato completamente; ma SIGKILL non può essere catturato o ignorato.

SIGINT e SIGQUIT sono specifici per le richieste provenienti dal terminale: è possibile assegnare determinati caratteri di input per generare questi segnali (in base alle impostazioni di controllo del terminale). L'azione predefinita per SIGINT è lo stesso tipo di chiusura del processo dell'azione predefinita per SIGTERM e l'azione immutabile per SIGKILL; l'azione predefinita per SIGQUIT è anche la terminazione del processo, ma possono verificarsi ulteriori azioni definite dall'implementazione, come la generazione di un core dump. O può essere catturato o ignorato dal processo, se necessario.

SIGHUP, come dici tu, intende indicare che la connessione del terminale è stata persa, piuttosto che essere un segnale di terminazione in quanto tale. Ma, di nuovo, l'azione predefinita per SIGHUP (se il processo non la cattura o la ignora) è di terminare il processo allo stesso modo di SIGTERM ecc.

C'è un tavolo nei POSIX definizioni per signal.h che elenca i vari segnali e le loro azioni e le finalità di default, e il capitolo General Terminal Interface include molti più dettagli sui segnali dei terminali connessi.

+8

Questo è il punto chiave: SIGINT e SIGQUIT possono essere generati dal terminale usando caratteri singoli, mentre il programma è in esecuzione. Gli altri segnali devono essere generati da un altro programma, in qualche modo (ad esempio dal comando kill). SIGINT è meno violento di SIGQUIT; il secondo produce una discarica principale. SIGKILL non può essere intrappolato. SIGHUP viene generato se la connessione si blocca (la finestra si chiude, ecc.). Quindi, hanno tutti significati diversi. –

+0

[TTY Demystified] (http://www.linusakesson.net/programming/tty/index.php) ha alcune informazioni facilmente digeribili su come i segnali interagiscono con il sottosistema tty del kernel. Aggiunge un po 'di contesto alla tua risposta. –

+0

Sembra che le specifiche non siano molto precise, ma la mia comprensione è che SIgint chiede al programma di interrompere la sua azione corrente, non necessariamente uscire.Per un programma progettato solo eseguire un'azione per esecuzione che implica la chiusura, ma per un programma interattivo che ha una sorta di ciclo di lettura-eval-print, può significare rinunciare all'eval corrente e tornare alla lettura dell'input dell'utente. Penso che meno lo sia su sigint. – bdsl

0

Con l'eccezione di alcuni segnali, i gestori di segnale possono intercettare i vari segnali oppure il comportamento predefinito al ricevimento di un segnale può essere modificato. Vedere la pagina man signal(7) per i dettagli.

+0

Sì, ma se non conosco "il significato" di un singnal, prendere il segnale è inutile, perché non saprò cosa fare nella mia applicazione. GNU C, ad es. spiega la differenza tra SIGQUIT e SIGTERM. Ma fornisce poche informazioni su SIGINT: http://www.gnu.org/s/libc/manual/html_node/Termination-Signals.html – Mecki

+0

"Il segnale' SIGINT' ("interrupt di programma") viene inviato quando l'utente digita il carattere INTR (normalmente 'Cc')." "SIGINT 2 Term Interrupt dalla tastiera" Premete Ctrl-C, viene inviato 'SIGINT'. Il processo normalmente muore. Che altro da dare? –

+0

Potenzialmente potrebbe esserci una descrizione dell'intenzione che il programmatore dovrebbe assumere che l'utente avrà quando preme ctrl-c, I.e.la semantica del messaggio. Ad esempio, le specifiche HTTP chiariscono che quando un utente invia una richiesta GET il server non deve presumere che desidera che faccia qualsiasi cosa tranne che restituire una risposta. – bdsl

3

Utilizzando kill (sia per la chiamata di sistema che per l'utilità) è possibile inviare quasi tutti i segnali a qualsiasi processo, dato il permesso. Un processo non può distinguere come un segnale è venuto alla luce e chi lo ha inviato.

Detto questo, SIGINT ha lo scopo di singolare l'interruzione Ctrl-C, mentre SIGTERM è il segnale generale del terminale.Non vi è alcun concetto che un segnale sia "più forte", con la sola eccezione che ci sono segnali che non possono essere bloccato o gestito (SIGKILL e SIGSTOP, secondo la pagina man.)

Un segnale può essere solo "più potente" di un altro segnale rispetto a come un processo di ricezione gestisce il segnale (e qual è l'azione predefinita per quel segnale). Ad esempio, per impostazione predefinita, sia SIGTERM che SIGINT portano alla chiusura. Ma se ignori SIGTERM allora non terminerà il tuo processo, mentre SIGINT lo fa ancora.

8

Come DarkDust ha notato che molti segnali hanno gli stessi risultati, ma i processi possono associare diverse azioni a loro distinguendo il modo in cui ogni segnale è generato. Guardando il codice sorgente del kernel di FreeBSD (kern_sig.c) vedo che i due segnali sono gestiti allo stesso modo, terminano il processo e vengono consegnati a qualsiasi thread.

SA_KILL|SA_PROC,    /* SIGINT */ 
SA_KILL|SA_PROC,    /* SIGTERM */ 
+1

+1 grazie per "usare il codice sorgente!" Luke! –

7

Dopo una rapida ricerca su Google per sigint vs sigterm, sembra che l'unica differenza tra i due sia se è stato avviato da una scorciatoia da tastiera o da una chiamata esplicita a kill.

Come risultato, è possibile, ad esempio, intercettare sigint e fare qualcosa di speciale con esso, sapendo che probabilmente è stato inviato da una scorciatoia da tastiera. Forse aggiornare lo schermo o qualcosa del genere, invece di morire (sconsigliato, poiché la gente si aspetta che ^C uccida il programma, solo un esempio).

Ho anche appreso che ^\ dovrebbe inviare sigquit, che potrei iniziare a usare da solo. Sembra molto utile

4

Alcuni sono ANSI C e altri non

Una notevole differenza è che:

  • SIGINT e SIGTERM sono ANSI C, quindi più portatile
  • SIGQUIT e SIGKILL non sono

Sono descritti nella sezione "7.14 Gestione dei segnali" di C99 draft N1256:

  • SIGINT ricezione di un segnale di attenzione interattivo
  • SIGTERM una richiesta di terminazione inviata al programma

che rende SIGINT un buon candidato per l'esercitazione Ctrl + C.

Problemi correlati