# C/Appendice/Librerie standard/signal.h

C
Copertina Tutti i moduli · Sviluppo
* LinguaggioC/Linguaggio
** PanoramicaC/Linguaggio/Panoramica
** Struttura del linguaggioC/Linguaggio/Struttura del linguaggio
* Variabili, operatori e costantiC/Variabili, operatori e costanti
** VariabiliC/Variabili, operatori e costanti/Variabili
** Operatori aritmeticiC/Variabili, operatori e costanti/Operatori aritmetici
** Operatori sui bitC/Variabili, operatori e costanti/Operatori sui bit
** CostantiC/Variabili, operatori e costanti/Costanti
* Blocchi e funzioniC/Blocchi e funzioni
** Blocchi if e switchC/Blocchi e funzioni/Blocchi if e switch
** Operatori logiciC/Blocchi e funzioni/Operatori logici
** CicliC/Blocchi e funzioni/Cicli
** FunzioniC/Blocchi e funzioni/Funzioni
** mainC/Blocchi e funzioni/main
** LibrerieC/Blocchi e funzioni/Librerie
** RicorsivitàC/Blocchi e funzioni/Ricorsività
* Vettori e puntatoriC/Vettori e puntatori
** VettoriC/Vettori e puntatori/Vettori
** PuntatoriC/Vettori e puntatori/Puntatori
** Interscambiabilità tra puntatori e vettoriC/Vettori e puntatori/Interscambiabilità tra puntatori e vettori
* StringheC/Variabili, operatori e costanti/Stringhe
* Enumerazioni, strutture e unioniC/Enumerazioni, strutture e unioni
** EnumerazioniC/Enumerazioni, strutture e unioni/Enumerazioni
** StruttureC/Enumerazioni, strutture e unioni/Strutture
** UnioniC/Enumerazioni, strutture e unioni/Unioni
* Conversioni di tipoC/Conversioni di tipo
* Lettura e scrittura su fileC/Lettura e scrittura su file
** File di TestoC/Lettura e scrittura su file/File di Testo
** File BinariC/Lettura e scrittura su file/File Binari
* Compilatore e precompilatoreC/Compilatore e precompilatore
** CompilatoreC/Compilatore e precompilatore/Compilatore
** DirettiveC/Compilatore e precompilatore/Direttive
** HeaderC/Compilatore e precompilatore/Header
* VisibilitàC/Visibilità
* Gestione della memoriaC/Gestione della memoria
* Le applicazioni CGIC/Le applicazioni CGI
* Appendice
** Librerie standardC/Appendice/Librerie standard
*** assert.hC/Appendice/Librerie standard/assert.h
*** ctype.hC/Appendice/Librerie standard/ctype.h
*** errno.hC/Appendice/Librerie standard/errno.h
*** float.hC/Appendice/Librerie standard/float.h
*** limits.hC/Appendice/Librerie standard/limits.h
*** locale.hC/Appendice/Librerie standard/locale.h
*** math.hC/Appendice/Librerie standard/math.h
*** setjmp.hC/Appendice/Librerie standard/setjmp.h
*** signal.hC/Appendice/Librerie standard/signal.h
*** stdarg.hC/Appendice/Librerie standard/stdarg.h
*** stddef.hC/Appendice/Librerie standard/stddef.h
*** stdio.hC/Appendice/Librerie standard/stdio.h
*** stdlib.hC/Appendice/Librerie standard/stdlib.h
*** string.hC/Appendice/Librerie standard/string.h
*** time.hC/Appendice/Librerie standard/time.h
** StrumentiC/Appendice/Strumenti
*** InstallerC/Appendice/Strumenti/Installer
** Librerie esterneC/Appendice/Librerie esterne
* Bibliografia
    IndiceC/Indice
Modifica il sommario
Il file signal.h della libreria standard definisce principalmente delle funzioni per la gestione dei segnali che riguardano il programma. Assieme alle funzioni definisce anche delle macro-variabili per classificare i segnali e per fare riferimento a delle funzioni predefinite, destinate astrattamente al trattamento dei segnali.

## Dichiarazione

Per la gestione dei segnali ci sono due funzioni che vengono dichiarate nel file signal.h: signal e raise. La funzione raise serve ad azionare un segnale specificato, come dire che serve ad attivare manualmente un allarme interno al programma, specificato da un numero particolare che ne definisce il tipo. Il programma contiene sempre una procedura predefinita che stabilisce ciò che deve essere fatto in presenza di un certo allarme, ma il programmatore può ridefinire la procedura attraverso l'uso della funzione signal, con la quale si associa l'avvio di una funzione particolare in presenza di un certo segnale. Il modello sintattico seguente rappresenta, in modo estremamente semplificato, l'uso della funzione signal:
Logicamente la funzione che si associa a un certo numero di segnale viene indicata negli argomenti della chiamata come puntatore a funzione. La funzione che viene passata come argomento è un gestore di segnale e deve avere una certa forma:
In pratica, quando viene creata l'associazione tra segnale e funzione che deve gestirlo, la funzione in questione deve avere un parametro tale da poter rappresentare il numero del segnale che la riguarda e non restituisce alcun valore (pertanto è di tipo void).
Avendo determinato questo, il modello della funzione signal può essere precisato un po' di più:
Ciò significa che il secondo argomento della funzione signal è un puntatore a una funzione (gestore) con un parametro di tipo int, la quale non restituisce alcunché (void).
Ma non è ancora stato specificato cosa deve restituire la funzione signal: un puntatore a una funzione che ha un parametro di tipo int e che a sua volta non restituisce alcunché. In pratica, signal deve restituire il puntatore a una funzione che ha le stesse caratteristiche di quella del proprio secondo parametro. A questo punto, si arriva al prototipo completo, ma molto difficile da interpretare a prima vista:
Per ovviare a questo problema di comprensibilità, anche se lo standard non lo prescrive, di norma, nel file signal.h si dichiara un tipo speciale, in qualità di puntatore a funzione con le caratteristiche del gestore di segnale:
Così facendo, la funzione signal può essere dichiarata in modo più gradevole:

## Tipo sig_atomic_t

il file signal.h definisce il tipo sig_atomic_t, il cui uso non viene precisato dai documenti ufficiali. Si chiarisce solo che deve trattarsi di un valore intero, possibilmente di tipo volatile, a cui si possa accedere attraverso una sola istruzione elementare del linguaggio macchina (in modo tale che la lettura o la modifica del suo contenuto non possa essere sospesa a metà da un'interruzione di qualunque genere).
Nell'esempio, il tipo sig_atomic_t viene dichiarato come equivalente al tipo int, supponendo che l'accesso alla memoria per un tipo intero normale corrisponda a un'operazione «atomica» nel linguaggio macchina. A ogni modo, il tipo a cui corrisponde sig_atomic_t può dipendere da altri fattori, mentre l'unico vincolo nel rango è quello di poter contenere i valori rappresentati dalle macro-variabili SIG..., che individuano mnemonicamente i segnali.
Il programmatore che deve memorizzare un segnale in una variabile, potrebbe usare per questo il tipo sig_atomic_t.

## Denominazione dei segnali

Un gruppo di macro-variabili definisce l'elenco dei segnali gestibili. Lo standard del linguaggio ne prescrive solo una quantità minima, mentre il sistema operativo può richiederne degli altri. Teoricamente l'associazione del numero al nome simbolico del segnale è libera, ma in pratica la concordanza con altri standard prescrive il rispetto di un minimo di uniformità.

## Uso delle funzioni

La funzione signal viene usata per associare un «gestore di segnale», costituito dal puntatore a una funzione, a un certo segnale; tutto questo allo scopo di attivare automaticamente quella tale funzione al verificarsi di un certo evento che si manifesta tramite un certo segnale.
La funzione signal restituisce un puntatore alla funzione che precedentemente si doveva occupare di quel segnale. Se invece l'operazione fallisce, signal esprime questo errore restituendo il valore SIG_ERR, spiegando così il motivo per cui questo debba avere l'apparenza di un puntatore a funzione.
Per la stessa ragione per cui esiste SIG_ERR, le macro-variabili SIG_DFL e SIG_IGN vanno usate come gestori di segnali, rispettivamente, per ottenere il comportamento predefinito o per far sì che i segnali siano ignorati semplicemente.
In linea di principio si può ritenere che nel proprio programma esista una serie iniziale di dichiarazioni implicite per cui si associano tutti i segnali gestibili a SIG_DFL:
L'altra funzione da considerare è raise, con la quale si attiva volontariamente un segnale, dal quale poi dovrebbero o potrebbero sortire delle conseguenze, come stabilito in una fase precedente attraverso signal. La funzione raise è molto semplice:
La funzione richiede come argomento il numero del segnale da attivare e restituisce un valore pari a zero in caso di successo, altrimenti restituisce un valore diverso da zero. Naturalmente, a seconda dell'azione che viene intrapresa all'interno del programma, a seguito della ricezione del segnale, può darsi che dopo questa funzione non venga eseguito altro, pertanto non è detto che possa essere letto il valore che la funzione potrebbe restituire.

### Esempio

Esempio
Viene proposto un esempio che serve a dimostrare il meccanismo di provocazione e intercettazione dei segnali:
All'inizio del programma vengono definite delle funzioni per il trattamento delle situazioni che hanno provocato un certo segnale. Nella funzione main, prima di ogni altra cosa, si associano tali funzioni ai segnali principali, quindi si passa a un ciclo senza fine, nel quale possono essere provocati dei segnali premendo un certo tasto, come suggerito da un breve menù. Per esempio è possibile provocare la condizione che si verifica tentando di dividere un numero per zero.
La divisione per zero fa scattare il segnale SIGFPE che viene intercettato dalla funzione sigfpe_handler, la quale però non può far molto e così conclude anche il funzionamento del programma.