Segnale (IPC) - Signal (IPC)
I segnali sono messaggi standardizzati inviati a un programma in esecuzione per attivare comportamenti specifici, come l'uscita o la gestione degli errori. Sono una forma limitata di comunicazione interprocesso (IPC), tipicamente utilizzata in Unix , Unix-like e altri sistemi operativi conformi a POSIX .
Un segnale è una notifica asincrona inviata a un processo oa un thread specifico all'interno dello stesso processo per notificargli un evento. Gli usi comuni di segnali sono di interrompere, sospendere, interrompere o uccidere un processo. I segnali hanno avuto origine negli anni '70 Bell Labs Unix e sono stati successivamente specificati nello standard POSIX .
Quando viene inviato un segnale, il sistema operativo interrompe il normale flusso di esecuzione del processo di destinazione per fornire il segnale. L'esecuzione può essere interrotta durante qualsiasi istruzione non atomica . Se il processo ha precedentemente registrato un gestore di segnale , quella routine viene eseguita. In caso contrario, viene eseguito il gestore del segnale predefinito.
I programmi incorporati possono trovare segnali utili per le comunicazioni tra processi, poiché i segnali sono notevoli per la loro efficienza algoritmica .
I segnali sono simili agli interrupt , con la differenza che gli interrupt sono mediati dalla CPU e gestiti dal kernel mentre i segnali sono mediati dal kernel (possibilmente tramite chiamate di sistema) e gestiti dai singoli processi . Il kernel può passare un interrupt come un segnale al processo che ha causato (tipici esempi sono SIGSEGV , SIGBUS , SIGILL e SIGFPE ).
Storia
La versione 1 Unix aveva chiamate di sistema separate per catturare interruzioni, chiusure e trap della macchina. La versione 4 combinava tutte le trap in un'unica chiamata, segnale e ogni trap numerata riceveva un nome simbolico nella versione 7 . kill è apparso nella versione 2 e nella versione 5 poteva inviare segnali arbitrari. Il piano 9 dei Bell Labs ha sostituito i segnali con note , che consentono l'invio di stringhe brevi e arbitrarie.
Invio di segnali
La chiamata di sistema kill (2) invia un segnale specificato a un processo specificato, se le autorizzazioni lo consentono. Allo stesso modo, il comando kill(1) consente a un utente di inviare segnali ai processi. La funzione di libreria raise(3) invia il segnale specificato al processo corrente.
Eccezioni come la divisione per zero o una violazione della segmentazione genereranno segnali (qui, rispettivamente, SIGFPE "floating point exception" e SIGSEGV "segmentation violazione", che entrambi per impostazione predefinita causano un core dump e un'uscita dal programma).
Il kernel può generare segnali per notificare i processi di eventi. Ad esempio, SIGPIPE verrà generato quando un processo scrive su una pipe che è stata chiusa dal lettore; per impostazione predefinita, ciò causa la terminazione del processo, il che è utile quando si costruiscono pipeline di shell .
La digitazione di determinate combinazioni di tasti sul terminale di controllo di un processo in esecuzione fa sì che il sistema invii determinati segnali:
- Ctrl-C (nei vecchi Unix, DEL) invia un segnale INT ("interrupt", SIGINT ); per impostazione predefinita, ciò causa l'interruzione del processo.
- Ctrl-Z invia un segnale TSTP ("terminal stop", SIGTSTP ); per impostazione predefinita, questo fa sì che il processo sospenda l'esecuzione.
- Ctrl-\ invia un segnale QUIT ( SIGQUIT ); per impostazione predefinita, questo provoca la chiusura del processo e il dump del core.
- Ctrl-T (non supportato su tutti gli UNIX) invia un segnale INFO ( SIGINFO ); per impostazione predefinita e, se supportato dal comando, questo fa sì che il sistema operativo mostri informazioni sul comando in esecuzione.
Queste combinazioni di tasti predefinite con i moderni sistemi operativi possono essere modificate con il comando stty .
Gestione dei segnali
I gestori di segnale possono essere installati con la chiamata di sistema signal(2) o sigaction(2) . Se non è installato un gestore di segnale per un segnale particolare, viene utilizzato il gestore predefinito. Altrimenti il segnale viene intercettato e viene richiamato il gestore del segnale. Il processo può anche specificare due comportamenti predefiniti, senza creare un gestore: ignorare il segnale (SIG_IGN) e utilizzare il gestore di segnale predefinito (SIG_DFL). Ci sono due segnali che non possono essere intercettati e gestiti: SIGKILL e SIGSTOP .
Rischi
La gestione del segnale è vulnerabile alle condizioni di gara . Poiché i segnali sono asincroni, è possibile fornire un altro segnale (anche dello stesso tipo) al processo durante l'esecuzione della routine di gestione del segnale.
La chiamata sigprocmask(2) può essere utilizzata per bloccare e sbloccare la consegna dei segnali. I segnali bloccati non vengono consegnati al processo fino a quando non vengono sbloccati. I segnali che non possono essere ignorati (SIGKILL e SIGSTOP) non possono essere bloccati.
I segnali possono causare l'interruzione di una chiamata di sistema in corso, lasciando all'applicazione la gestione di un riavvio non trasparente .
I gestori del segnale devono essere scritti in modo tale da non provocare effetti collaterali indesiderati, ad es. alterazione dell'errno , alterazione della maschera del segnale, modifica della disposizione del segnale e altre modifiche agli attributi del processo globale . Anche l'uso di funzioni non rientranti , ad esempio malloc o printf , all'interno di gestori di segnale è pericoloso. In particolare, la specifica POSIX e il segnale della pagina man di Linux (7) richiedono che tutte le funzioni di sistema chiamate direttamente o indirettamente da una funzione di segnale siano sicure per il segnale asincrono . La pagina man di signal-safety(7) fornisce un elenco di tali funzioni di sistema sicure per il segnale asincrono (praticamente le chiamate di sistema ), altrimenti è un comportamento indefinito . Si suggerisce di impostare semplicemente qualche volatile sig_atomic_tvariabile in un gestore di segnale e di testarla altrove.
I gestori del segnale possono invece mettere il segnale in una coda e tornare immediatamente. Il thread principale continuerà quindi "ininterrotto" fino a quando i segnali non vengono presi dalla coda, come in un ciclo di eventi . "Ininterrotto" qui significa che le operazioni che si bloccano possono tornare prematuramente e devono essere riprese , come accennato in precedenza. I segnali dovrebbero essere elaborati dalla coda sul thread principale e non dai pool di lavoratori , poiché ciò reintroduce il problema dell'asincronicità. Tuttavia, la gestione di una coda non è possibile in modo sicuro dal segnale asincrono con solo sig_atomic_t , poiché solo le singole letture e scritture su tali variabili sono garantite come atomiche, non incrementi o (fetch-and)-decrementi, come sarebbe richiesto per una coda. Quindi, effettivamente, solo un segnale per gestore può essere accodato in modo sicuro con sig_atomic_t fino a quando non è stato elaborato.
Relazione con le eccezioni hardware
L' esecuzione di un processo può comportare la generazione di un'eccezione hardware , ad esempio, se il processo tenta di dividere per zero o incorre in un errore di pagina .
Nei sistemi operativi simili a Unix , questo evento modifica automaticamente il contesto del processore per avviare l'esecuzione di un gestore di eccezioni del kernel . In caso di alcune eccezioni, come un errore di pagina , il kernel dispone di informazioni sufficienti per gestire completamente l'evento stesso e riprendere l'esecuzione del processo.
Altre eccezioni, tuttavia, il kernel non può elaborare in modo intelligente e deve invece rinviare l'operazione di gestione delle eccezioni al processo di errore. Questo differimento è ottenuto tramite il meccanismo del segnale, in cui il kernel invia al processo un segnale corrispondente all'eccezione corrente. Ad esempio, se un processo tentasse una divisione intera per zero su una CPU x86 , verrebbe generata un'eccezione di errore di divisione e il kernel invierà il segnale SIGFPE al processo.
Allo stesso modo, se il processo tentasse di accedere a un indirizzo di memoria al di fuori del suo spazio di indirizzi virtuale , il kernel notificherebbe al processo questa violazione tramite un segnale SIGSEGV . L'esatta mappatura tra i nomi dei segnali e le eccezioni dipende ovviamente dalla CPU, poiché i tipi di eccezione differiscono tra le architetture.
Segnali POSIX
L'elenco seguente documenta i segnali specificati nella Single Unix Specification . Tutti i segnali sono definiti come macro costanti nel <signal.h>file di intestazione. Il nome della macro costante è costituito da un prefisso "SIG" seguito da un nome mnemonico per il segnale.
- SIGABRT eSIGIOT
- Il segnale SIGABRT e SIGIOT viene inviato a un processo per dirgli di abortire , cioè di terminare. Il segnale viene solitamente avviato dal processo stesso quando richiama la
abort()funzione della libreria standard C , ma può essere inviato al processo dall'esterno come qualsiasi altro segnale. - SIGALRM ,SIGVTALRM eSIGPROF
- Il segnale SIGALRM, SIGVTALRM e SIGPROF viene inviato a un processo quando scade il limite di tempo specificato in una chiamata a una precedente funzione di impostazione dell'allarme (come
setitimer). SIGALRM viene inviato allo scadere del tempo reale o dell'orologio. SIGVTALRM viene inviato allo scadere del tempo CPU utilizzato dal processo. SIGPROF viene inviato allo scadere del tempo CPU utilizzato dal processo e dal sistema per conto del processo. - SIGBUS
- Il segnale SIGBUS viene inviato a un processo quando provoca un errore del bus . Le condizioni che portano all'invio del segnale sono, ad esempio, un errato allineamento dell'accesso alla memoria o un indirizzo fisico inesistente.
- SIGCHLD
- Il segnale SIGCHLD viene inviato a un processo quando un processo figlio termina , viene interrotto o riprende dopo essere stato interrotto. Un uso comune del segnale consiste nell'istruire il sistema operativo a ripulire le risorse utilizzate da un processo figlio dopo la sua terminazione senza una chiamata esplicita alla chiamata di
waitsistema. - SIGCONT
- Il segnale SIGCONT indica al sistema operativo di continuare (riavviare) un processo precedentemente sospeso dal segnale SIGSTOP o SIGTSTP. Un uso importante di questo segnale è nel controllo del lavoro nella shell Unix .
- SIGFPE
- Il segnale SIGFPE viene inviato a un processo quando è stata rilevata una condizione eccezionale (ma non necessariamente errata) nell'hardware aritmetico in virgola mobile o intero. Ciò può includere la divisione per zero , underflow o overflow in virgola mobile, overflow di numeri interi, un'operazione non valida o un calcolo inesatto. Il comportamento può variare a seconda dell'hardware.
- SIGHUP
- Il segnale SIGHUP viene inviato a un processo quando il suo terminale di controllo è chiuso. È stato originariamente progettato per notificare il processo di una caduta della linea seriale (un hangup ). Nei sistemi moderni, questo segnale di solito significa che lo pseudo terminale o virtuale di controllo è stato chiuso. Molti demoni (che non hanno un terminale di controllo) interpretano la ricezione di questo segnale come una richiesta di ricaricare i loro file di configurazione e svuotare/riaprire i loro file di log invece di uscire. nohup è un comando per fare in modo che un comando ignori il segnale.
- SIGILL
- Il segnale SIGILL viene inviato a un processo quando si tenta di eseguire illegale , composto correttamente, sconosciuto, o privilegiato istruzione .
- SIGINT
- Il segnale SIGINT viene inviato a un processo dal suo terminale di controllo quando un utente desidera interrompere il processo. Questo viene in genere avviato premendo Ctrl+C , ma su alcuni sistemi è possibile utilizzare il carattere " cancella " o il tasto " interruzione ".
- SIGKILL
- Il segnale SIGKILL viene inviato a un processo per farlo terminare immediatamente ( kill ). A differenza di SIGTERM e SIGINT, questo segnale non può essere catturato o ignorato e il processo di ricezione non può eseguire alcuna pulizia dopo aver ricevuto questo segnale. Si applicano le seguenti eccezioni:
- I processi zombi non possono essere uccisi poiché sono già morti e aspettano che i loro processi genitori li raccolgano.
- I processi che si trovano nello stato bloccato non moriranno finché non si riattiveranno.
- Il processo init è speciale: non riceve segnali che non vuole gestire e quindi può ignorare SIGKILL. Un'eccezione a questa regola è mentre init viene tracciato su Linux.
- Un processo ininterrotto di sospensione non può terminare (e liberare le sue risorse) anche quando viene inviato SIGKILL. Questo è uno dei pochi casi in cui potrebbe essere necessario riavviare un sistema UNIX per risolvere un problema software temporaneo.
- SIGKILL viene utilizzato come ultima risorsa quando si terminano i processi nella maggior parte delle procedure di arresto del sistema se non si chiude volontariamente in risposta a SIGTERM. Per velocizzare la procedura di spegnimento del computer, Mac OS X 10.6, noto anche come Snow Leopard , invierà SIGKILL alle applicazioni che si sono contrassegnate come "pulite" con conseguente tempi di spegnimento più rapidi senza, presumibilmente, effetti negativi. Il comando
killall -9ha un effetto simile, sebbene pericoloso, quando viene eseguito ad esempio in Linux; non consente ai programmi di salvare i dati non salvati. Ha altre opzioni e, con nessuna, utilizza il segnale SIGTERM più sicuro. - SIGPIPE
- Il segnale SIGPIPE viene inviato a un processo quando tenta di scrivere su una pipe senza un processo connesso all'altra estremità.
- SIGPOLL
- Il segnale SIGPOLL viene inviato quando si verifica un evento su un descrittore di file controllato in modo esplicito. Il suo utilizzo porta effettivamente a effettuare richieste di I/O asincrone poiché il kernel eseguirà il polling del descrittore al posto del chiamante. Fornisce un'alternativa al polling attivo .
- SIGRTMIN aSIGRTMAX
- I segnali da SIGRTMIN a SIGRTMAX sono destinati ad essere utilizzati per scopi definiti dall'utente. Sono segnali in tempo reale .
- SIGQUIT
- Il segnale SIGQUIT viene inviato a un processo dal suo terminale di controllo quando l'utente richiede che il processo esca ed esegua un core dump .
- SIGSEGV
- Il SIGSEGV segnale viene inviato a un processo quando si fa un riferimento non valido memoria virtuale, o segmentazione guasto , cioè quando si esegue una seg mentazione v iolation .
- SIGSTOP
- Il segnale SIGSTOP indica al sistema operativo di interrompere un processo per una successiva ripresa.
- SIGSYS
- Il segnale SIGSYS viene inviato a un processo quando passa un argomento errato a una chiamata di sistema . In pratica, questo tipo di segnale si incontra raramente poiché le applicazioni si affidano a librerie (ad esempio libc ) per effettuare la chiamata. SIGSYS può essere ricevuto da applicazioni che violano le regole di sicurezza di Linux Seccomp configurate per limitarle. SIGSYS può essere utilizzato anche per emulare chiamate di sistema esterne, ad esempio emulare chiamate di sistema Windows su Linux.
- SIGTERM
- Il segnale SIGTERM viene inviato a un processo per richiederne la terminazione . A differenza del segnale SIGKILL, può essere catturato e interpretato o ignorato dal processo. Ciò consente al processo di eseguire una buona terminazione rilasciando risorse e salvando lo stato se appropriato. SIGINT è quasi identico a SIGTERM.
- SIGTSTP
- Il SIGTSTP segnale viene inviato ad un processo per la sua controllando terminale richiedere a fermata ( t erminal st o p ). Viene comunemente avviato dall'utente premendo Ctrl+Z . A differenza di SIGSTOP, il processo può registrare un gestore di segnale per o ignorare il segnale.
- SIGTTIN eSIGTTOU
- I SIGTTIN e SIGTTOU segnali sono inviati ad un processo quando si tenta di leggere in o scrivere fuori rispettivamente ricavati tty mentre in fondo . Tipicamente, questi segnali vengono ricevuti solo dai processi sotto il controllo del lavoro ; i demoni non hanno terminali di controllo e, quindi, non dovrebbero mai ricevere questi segnali.
- SIGTRAP
- Il segnale SIGTRAP viene inviato a un processo quando si verifica un'eccezione (o trap ): una condizione di cui un debugger ha richiesto di essere informato, ad esempio quando viene eseguita una particolare funzione o quando una particolare variabile cambia valore.
- SIGURG
- Il segnale SIGURG viene inviato a un processo quando un socket dispone di dati urgenti o fuori banda disponibili per la lettura.
- SIGUSR1 eSIGUSR2
- I segnali SIGUSR1 e SIGUSR2 vengono inviati a un processo per indicare condizioni definite dall'utente .
- SIGXCPU
- Il segnale SIGXCPU viene inviato ad un processo quando ha esaurito la CPU per una durata che supera un certo valore predeterminato impostabile dall'utente. L'arrivo di un segnale SIGXCPU fornisce al processo di ricezione la possibilità di salvare rapidamente eventuali risultati intermedi e di uscire con garbo, prima che venga terminato dal sistema operativo utilizzando il segnale SIGKILL.
- SIGXFSZ
- Il segnale SIGXFSZ viene inviato a un processo quando cresce un file che supera la dimensione massima consentita .
- SIGWINCH
- Il segnale SIGWINCH viene inviato a un processo quando il terminale di controllo cambia la sua dimensione (una win dow ch ange).
Azione predefinita
Un processo può definire come gestire i segnali POSIX in ingresso . Se un processo non definisce un comportamento per un segnale, viene utilizzato il gestore predefinito per quel segnale. La tabella seguente elenca alcune azioni predefinite per i sistemi UNIX compatibili con POSIX, come FreeBSD , OpenBSD e Linux .
| Segnale | Numero portatile |
Azione predefinita | Descrizione |
|---|---|---|---|
| SIGABRT | 6 | Termina (core dump) | Segnale di interruzione del processo |
| SIGALRM | 14 | Terminare | Sveglia |
| SIGBUS | N / A | Termina (core dump) | Accesso a una porzione indefinita di un oggetto di memoria |
| SIGCHLD | N / A | Ignorare | Processo figlio terminato, interrotto o continuato |
| SIGCONT | N / A | Continua | Continua l'esecuzione, se interrotto |
| SIGFPE | 8 | Termina (core dump) | Operazione aritmetica errata |
| SIGHUP | 1 | Terminare | Appendere |
| SIGILL | 4 | Termina (core dump) | Istruzione illegale |
| SIGINT | 2 | Terminare | Segnale di interruzione del terminale |
| SIGKILL | 9 | Terminare | Uccidi (non può essere catturato o ignorato) |
| SIGPIPE | 13 | Terminare | Scrivi su una pipa senza che nessuno lo legga |
| SIGPOLL | N / A | Terminare | Evento sondabile |
| SIGPROF | N / A | Terminare | Timer di profilazione scaduto |
| SIGQUIT | 3 | Termina (core dump) | Segnale di chiusura del terminale |
| SIGSEGV | 11 | Termina (core dump) | Riferimento di memoria non valido |
| SIGSTOP | N / A | Fermare | Interrompi l'esecuzione (non può essere catturato o ignorato) |
| SIGSYS | N / A | Termina (core dump) | Cattiva chiamata di sistema |
| SIGTERM | 15 | Terminare | Segnale di terminazione |
| SIGTRAP | 5 | Termina (core dump) | Traccia/trappola punto di interruzione |
| SIGTSTP | N / A | Fermare | Segnale di arresto del terminale |
| SIGTTIN | N / A | Fermare | Processo in background durante il tentativo di lettura |
| SIGTTOU | N / A | Fermare | Processo in background che tenta di scrivere |
| SIGUSR1 | N / A | Terminare | Segnale definito dall'utente 1 |
| SIGUSR2 | N / A | Terminare | Segnale definito dall'utente 2 |
| SIGURG | N / A | Ignorare | I dati fuori banda sono disponibili su una presa |
| SIGVTALRM | N / A | Terminare | Timer virtuale scaduto |
| SIGXCPU | N / A | Termina (core dump) | Limite di tempo della CPU superato |
| SIGXFSZ | N / A | Termina (core dump) | Limite dimensione file superato |
| SIGWINCH | N / A | Ignorare | La dimensione della finestra del terminale è cambiata |
- Numero portatile:
- Per la maggior parte dei segnali il numero di segnale corrispondente è definito dall'implementazione. Questa colonna elenca i numeri specificati nello standard POSIX.
- Azioni spiegate:
- Terminate – Interruzione anomala del processo. Il processo viene terminato con tutte le conseguenze di _exit() eccetto che lo stato reso disponibile per wait() e waitpid() indica una terminazione anomala da parte del segnale specificato.
- Terminate (core dump) – Terminazione anomala del processo. Inoltre, possono verificarsi azioni di terminazione anomale definite dall'implementazione, come la creazione di un file principale.
- Ignora – Ignora il segnale.
- Stop – Arresta (non termina) il processo.
- Continua – Continua il processo, se è stato interrotto; in caso contrario ignorare il segnale.
Segnali vari
I seguenti segnali non sono specificati nella specifica POSIX . Tuttavia, a volte vengono utilizzati su vari sistemi.
- SIGEMT
- Il segnale SIGEMT viene inviato a un processo quando si verifica un trap dell'emulatore .
- SIGNINFO
- Il segnale SIGINFO viene inviato a un processo quando viene ricevuta una richiesta di stato ( info ) dal terminale di controllo.
- SIGPWR
- Il segnale SIGPWR viene inviato a un processo quando il sistema subisce un'interruzione di corrente .
- SIGLOST
- Il segnale SIGLOST viene inviato a un processo quando un file lock viene perso .
- SIGSTKFLT
- Il segnale SIGSTKFLT viene inviato a un processo quando il coprocessore sperimenta una v ac k f au lt (cioè popping quando la pila è vuota o spingendo quando è pieno). È definito da, ma non utilizzato su Linux, dove un errore dello stack del coprocessore x87 genererà invece SIGFPE.
- SIGUNUSED
- Il segnale SIGUNUSED viene inviato a un processo quando viene effettuata una chiamata di sistema con un numero di chiamata di sistema inutilizzato . È sinonimo di SIGSYS sulla maggior parte delle architetture.
- SIGCLD
- Il segnale SIGCLD è sinonimo di SIGCHLD.
Guarda anche
Riferimenti
- Stevens, W. Richard (1992). Programmazione avanzata in ambiente UNIX® . Reading, Massachusetts: Addison Wesley. ISBN 0-201-56317-7.
- "Le specifiche di base del gruppo aperto numero 7, edizione 2013" . Il gruppo aperto . Estratto il 19 giugno 2015 .
link esterno
- Tabella dei segnali Unix, Ali Alanjawi, Università di Pittsburgh
- Man7.org Signal Man Page
- Introduzione alla programmazione dei segnali Unix Introduzione alla programmazione dei segnali Unix alla Wayback Machine (archiviata il 26 settembre 2013)
- Un'altra introduzione alla programmazione dei segnali Unix (post sul blog, 2009)
- UNIX e segnali POSIX affidabili di Baris Simsek
- Gestori di segnale di Henning Brauer