A volte sono un po' confuso da 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 puoi inviare manualmente segnali ai processi in esecuzione tramite -s
parametro per kill
, ma quali sono i naturali circostanze in cui questi segnali vengono inviati? Ad esempio, quando fa SIGINT
inviato?
Inoltre, ci sono restrizioni sui segnali che possono essere gestiti? Può anche SIGSEGV
i segnali devono essere elaborati e il controllo restituito all'applicazione?
Risposta accettata:
Oltre ai processi che chiamano kill(2)
, alcuni segnali vengono inviati dal kernel (o talvolta dal processo stesso) in varie circostanze:
- I driver dei terminali inviano segnali corrispondenti a vari eventi:
- Notifiche alla pressione dei tasti:
SIGINT
(torna al ciclo principale) su Ctrl +C ,SIGQUIT
(per favore esci immediatamente) su Ctrl + ,SIGTSTP
(si prega di sospendere) su Ctrl +Z . Le chiavi possono essere cambiate con ilstty
comando. SIGTTIN
eSIGTTOU
vengono 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.SIGHUP
viene inviato per segnalare che il terminale è scomparso (storicamente perché il tuo modem aveva h ung su , oggigiorno di solito perché hai chiuso la finestra dell'emulatore di terminale).
- Notifiche alla pressione dei tasti:
- Alcune trap 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 l'accesso a una pagina non mappata;SIGILL
per un'istruzione illegale (codice operativo errato);SIGFPE
per un'istruzione in virgola mobile con argomenti errati (ad es.sqrt(-1)
).
- Un certo numero di segnali notifica al processo di destinazione che si è verificato un evento di sistema:
SIGALRM
notifica che un timer impostato dal processo è scaduto. I timer possono essere impostati conalarm
,setitimer
e altri.SIGCHLD
notifica a un processo che uno dei suoi figli è morto.SIGPIPE
viene generato quando un processo tenta di scrivere su una pipe quando la fine della lettura è stata chiusa (l'idea è che se si eseguefoo | bar
ebar
esce,foo
viene ucciso da unSIGPIPE
).SIGPOLL
(chiamato ancheSIGIO
) notifica al processo che si è verificato un evento pollable. POSIX specifica gli eventi pollable registrati tramiteI_SETSIG
ioctl
. Molti sistemi consentono eventi pollable su qualsiasi descrittore di file, impostati tramiteO_ASYNC
fcntl
bandiera. Un segnale correlato èSIGURG
, che notifica i dati urgenti su un dispositivo (registrato tramite ilI_SETSIG
ioctl
) o presa.- Su alcuni sistemi,
SIGPWR
viene 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
(muori e basta) e STOP
(interrompe l'esecuzione).
SIGSEGV
(errore di segmentazione) e suo cugino SIGBUS
(errore bus) può essere catturato, ma è una cattiva idea a meno che tu non sappia davvero cosa stai facendo. Un'applicazione comune per rilevarli è la stampa di una traccia dello stack o altre informazioni di debug. Un'applicazione più avanzata consiste nell'implementare una sorta di gestione della memoria in-process o per intercettare istruzioni errate nei motori delle macchine virtuali.
Infine, permettetemi di menzionare qualcosa che non è un segnale. Quando premi Ctrl +D all'inizio di una riga in un programma che sta leggendo 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 +C e amici, la chiave può essere configurata con stty
.