Cosa causa l'invio di vari segnali?


28

A volte mi confondo un po 'tutti i segnali che un processo può ricevere. A quanto ho capito, un processo ha un gestore predefinito ( disposizione del segnale ) per ciascuno di questi segnali, ma può fornire il proprio gestore chiamando sigaction().

Quindi, ecco la mia domanda: cosa causa l'invio di ciascuno dei segnali? Mi rendo conto che è possibile inviare manualmente segnali ai processi in esecuzione tramite il -sparametro a kill, ma quali sono le circostanze naturali in cui vengono inviati questi segnali? Ad esempio, quando SIGINTviene inviato?

Inoltre, ci sono restrizioni su quali segnali possono essere gestiti? È anche SIGSEGVpossibile elaborare i segnali e restituire il controllo all'applicazione?


Una risposta adeguata a questo sarà epica e fondamentalmente replicherà le informazioni nell'articolo di Wikipedia sull'argomento, quindi indicherò lì.
— Shawn J. Goff,

@Shawn: l'articolo di Wikipedia ha un elenco di segnali, ma nessuna presentazione chiara di chi invia quali segnali.
— Gilles 'SO- smetti di essere malvagio' il

Risposte:


41

Oltre alla chiamata dei processi kill(2), alcuni segnali vengono inviati dal kernel (o talvolta dal processo stesso) in varie circostanze:

  • I driver del terminale inviano segnali corrispondenti a vari eventi:
    • Notifiche chiave: SIGINT(torna al ciclo principale) su Ctrl+ C, SIGQUIT(esci immediatamente) su Ctrl+ \, SIGTSTP(sospendi) su Ctrl+ Z. Le chiavi possono essere modificate con il sttycomando.
    • SIGTTINe SIGTTOUvengono inviati quando un processo in background tenta di leggere o scrivere sul suo terminale di controllo.
    • SIGWINCH viene inviato per segnalare che la dimensione della finestra del terminale è cambiata.
    • SIGHUPviene inviato al segnale che il terminale è scomparso (storicamente perché il modem aveva h ung up , al giorno d'oggi di solito perché avete chiuso la finestra di emulatore di terminale).
  • Alcune trappole del processore possono generare un segnale. I dettagli dipendono dall'architettura e dal sistema; ecco alcuni esempi tipici:
    • SIGBUS per una memoria di accesso non allineata;
    • SIGSEGV per un accesso a una pagina non mappata;
    • SIGILL per un'istruzione illegale (codice operativo errato);
    • SIGFPEper un'istruzione in virgola mobile con argomenti non validi (ad es sqrt(-1).).
  • Numerosi segnali segnalano al processo di destinazione che si è verificato un evento di sistema:
    • SIGALRMnotifica che un timer impostato dal processo è scaduto. Timer può essere impostato con alarm, setitimere altri.
    • SIGCHLD notifica a un processo che uno dei suoi figli è morto.
    • SIGPIPEviene generato quando un processo tenta di scrivere su una pipe quando la fine della lettura è stata chiusa (l'idea è che se corri foo | bared baresci, fooviene ucciso da un SIGPIPE).
    • SIGPOLL(chiamato anche SIGIO) notifica al processo che si è verificato un evento pollable. POSIX specifica gli eventi pollable registrati tramite I_SETSIG ioctl. Molti sistemi consentono eventi pollable su qualsiasi descrittore di file, impostato tramite il O_ASYNC fcntlflag. Un segnale correlato è SIGURG, che notifica i dati urgenti su un dispositivo (registrato tramite I_SETSIG ioctl) o presa .
    • Su alcuni sistemi, SIGPWRviene inviato a tutti i processi quando l' UPS segnala che è imminente un'interruzione di corrente.

Questi elenchi non sono esaustivi. I segnali standard sono definiti in signal.h.

La maggior parte dei segnali può essere catturata e gestita (o ignorata) dall'applicazione. Gli unici due segnali portatili che non possono essere catturati sono SIGKILL(basta morire) e STOP(interrompere l'esecuzione).

SIGSEGV( errore di segmentazione ) e suo cugino SIGBUS( errore del bus ) possono essere colti, ma è una cattiva idea se non sai davvero cosa stai facendo. Un'applicazione comune per catturarli è la stampa di una traccia dello stack o altre informazioni di debug. Un'applicazione più avanzata è implementare una sorta di gestione della memoria in-process o intrappolare cattive istruzioni nei motori di macchine virtuali.

Infine, vorrei menzionare qualcosa che non è un segnale. Quando si preme Ctrl+ Dall'inizio di una riga in un programma che legge l'input dal terminale, questo indica al programma che è stata raggiunta la fine del file di input. Questo non è un segnale: viene trasmesso tramite l'API di input / output. Come Ctrl+ Ce gli amici, la chiave può essere configurata con stty.


E SIGHUP, il tuo modem ha riagganciato. :-)
— Keith

1
Un'altra cosa da notare SIGFPE:, in qualche modo non intuitivo, viene anche segnalato su un intero diviso per zero, e talvolta su un overflow di numeri interi con segno .
— effimero

18

Per rispondere prima alla tua seconda domanda: SIGSTOPe SIGKILLnon può essere catturato dall'applicazione, ma ogni altro segnale può, anche SIGSEGV. Questa proprietà è utile per il debug: ad esempio, con il giusto supporto di libreria, è possibile ascoltare SIGSEGVe generare una backtrace dello stack per mostrare esattamente dove si è verificato il segfault.

La parola ufficiale (per Linux, comunque) su ciò che fa ogni segnale è disponibile digitando man 7 signalda una riga di comando di Linux. http://linux.die.net/man/7/signal ha le stesse informazioni, ma le tabelle sono più difficili da leggere.

Tuttavia, senza una certa esperienza con i segnali, è difficile sapere dalle brevi descrizioni cosa fanno in pratica, quindi ecco la mia interpretazione:

Attivato dalla tastiera

  • SIGINTsuccede quando colpisci CTRL+C.
  • SIGQUITviene attivato da CTRL+\e scarica core.
  • SIGTSTPsospende il programma quando si colpisce CTRL+Z. Diversamente SIGSTOP, è acquistabile, il che offre ai programmi la vipossibilità di ripristinare il terminale in uno stato sicuro prima di sospendere se stessi.

Interazioni terminali

  • SIGHUP ("hangup") è ciò che accade quando si chiude xterm (o si disconnette in altro modo il terminale) mentre il programma è in esecuzione.
  • SIGTTINe SIGTTOUmettere in pausa il programma se tenta di leggere o scrivere sul terminale mentre è in esecuzione in background. Perché SIGTTOUciò accada, penso che il programma debba scrivere /dev/tty, non solo standard stdout.

Attivato da un'eccezione della CPU

Ciò significa che il tuo programma ha tentato di fare qualcosa di sbagliato.

  • SIGILLindica un'istruzione del processore illegale o sconosciuta. Ciò può accadere se, ad esempio, si è tentato di accedere direttamente alle porte I / O del processore.
  • SIGFPEsignifica che si è verificato un errore matematico hardware; molto probabilmente il programma ha cercato di dividere per zero.
  • SIGSEGV significa che il tuo programma ha tentato di accedere a un'area di memoria non mappata.
  • SIGBUSsignifica che il programma ha avuto accesso errato alla memoria in qualche altro modo; Non entrerò nei dettagli per questo riassunto.

Interazione di processo

  • SIGPIPEsuccede se provi a scrivere su una pipe dopo che il lettore della pipe ha chiuso la loro estremità. Vedere man 7 pipe.
  • SIGCHLDsi verifica quando un processo figlio creato viene chiuso o sospeso (da SIGSTOPo simile).

Utile per l'auto-segnalazione

  • SIGABRTdi solito è causato dal programma che chiama la abort()funzione e causa un dump principale per impostazione predefinita. Ordinamento di un "pulsante antipanico".
  • SIGALRMè causato dalla alarm()chiamata di sistema, che farà in modo che il kernel consegni un SIGALRMprogramma al programma dopo un determinato numero di secondi. Vedi man 2 alarme man 2 sleep.
  • SIGUSR1e SIGUSR2vengono utilizzati comunque come piace al programma. Potrebbero essere utili per la segnalazione tra processi.

Inviato dall'amministratore

Questi segnali vengono generalmente inviati dal prompt dei comandi, tramite il killcomando o fgo bgnel caso di SIGCONT.

  • SIGKILLe SIGSTOPsono i segnali sbloccabili. Il primo termina sempre immediatamente il processo; il secondo sospende il processo.
  • SIGCONT riprende un processo sospeso.
  • SIGTERMè una versione catchable di SIGKILL.

Quale segnale viene inviato quando shutdownsi utilizza il comando?
— Nathan Osman,

Dipende dagli script di spegnimento. In genere, SIGTERMviene inviato per primo, seguito da un ritardo, seguito da SIGKILL. In linea di principio, per un arresto immediato e immediato, il kernel non ha bisogno di inviare alcun segnale; potrebbe semplicemente smettere di eseguire il processo.
— Jander
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.