\chapter{I segnali}
-\label{sec:signals}
+\label{cha:signals}
I segnali sono il primo e più semplice meccanismo di comunicazione nei
confronti dei processi. Non portano con se nessuna informazione che non sia il
essere eseguita.
\item una richiesta dell'utente di terminare o fermare il programma. In genere
si realizza attraverso un segnale mandato dalla shell in corrispondenza
- della pressione di tasti come 'ctrl-c' o 'ctrl-z'.
+ della pressione di tasti del terminale come 'ctrl-c' o 'ctrl-z'.
\item l'esecuzione di una \texttt{kill} o di una \texttt{raise} da parte del
processo stesso o di un'altro (solo nel caso della \texttt{kill}).
\end{itemize}
Ciascuno di questi eventi (tranne gli ultimi due che sono controllati
-dall'utente) comporta da parte del kernel la generazione un particolare tipo
-di segnale.
+dall'utente) comporta l'intervento diretto da parte del kernel che causa la
+generazione un particolare tipo di segnale.
\subsection{Le modalità di funzionamento}
\label{sec:sig_semantics}
-Quando un processo riceve un segnale il kernel esegue una apposita routine di
-gestione (il cosiddetto \textit{signal handler}) che può essere specificata
-dall'utente. Negli anni il comportamento del sistema in risposta ai segnali è
-stato modificato in vari modi nelle differenti implementazioni di unix.
-Attualmente si possono individuare due tipologie fondamentali di comportamento
-dei segnali (dette semantiche) che vengono chiamate rispettivamente
-\textit{reliable} e \textit{unreliable}.
-
-Nella semantica \textit{unreliable} la routine di gestione del segnale
-specificata dall'utente non resta installata una volta chiamata; è perciò a
-carico dell'utente stesso ripetere l'installazione all'interno della routine
-di gestione stessa in tutti i casi in cui si vuole che il signal handler
-esterno resti attivo.
-
-Per questo motivo è possibile una race-condition in cui un secondo segnale
-arriva prima che il manipolatore abbia eseguito la re-installazione di se
-stesso, nel qual caso il segnale può essere perso o causare il comportamento
-originale assegnato al segnale (in genere la terminazione del processo).
-Questa è la ragione per cui detti segnali sono chiamati \textit{inaffidabili},
-in quanto la ricezione del segnale e la reinstallazione del suo manipolatore
-non sono operazioni atomiche.
-
-Nel caso di implementazione inaffidabile le chiamate di sistema non
-sono fatte ripartire automaticamente quando sono interrotte da un segnale, per
-questo il programma deve controllare lo stato di uscita della chiamata al
-sistema e riperterla nel caso l'errore riportato da \texttt{errno} sia
-\texttt{EINTR}.
-
-Inoltre in questo caso non esiste una modalità semplice per ottenere una
-operazione di pausa atomica (cioè mandare in sleep un processo fino all'arrivo
-di un segnale), dato che ci sono casi in cui un segnale può arrivare quando il
-programma non è in grado di accorgersene.
-
-In caso di segnali \textit{reliable} invece il signal handler resta installato
-quando viene chiamato e i problemi precedenti sono evitati. Inoltre alcune
-chiamate di sistema possono essere fatte ripartire automaticamente e si può
-ottenere un'operazione di pausa atomica (usando la funzione POSIX
-\texttt{sigsuspend}).
-
-
-\subsubsection{Tipi di segnali}
+Quando un processo riceve un segnale il kernel esegue una azione di default o
+una apposita routine di gestione (il cosiddetto \textit{signal handler} o
+\textsl{manipolatore}) che può essere specificata dall'utente (nel qual caso
+si dice che si \textsl{intercetta} il segnale). Negli anni il comportamento
+del sistema in risposta ai segnali è stato modificato in vari modi nelle
+differenti implementazioni di unix. Si possono individuare due tipologie
+fondamentali di comportamento dei segnali (dette semantiche) che vengono
+chiamate rispettivamente \textit{reliable} e \textit{unreliable}.
+
+Nella semantica \textit{unreliable} (quella implementata dalle prime versioni
+di unix) la routine di gestione del segnale specificata dall'utente non resta
+installata una volta chiamata; è perciò a carico dell'utente stesso ripetere
+l'installazione all'interno della routine di gestione stessa in tutti i casi
+in cui si vuole che il signal handler esterno resti attivo.
+
+In questo caso è possibile una situazione in cui i segnali possono essere
+perduti; si consideri il seguente segmento di codice in cui la prima
+operazione del manipolatore è quella di reinstallare se stesso:
+\footnotesize
+\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
+ int sig_handler(); /* handler function */
+ ...
+ signal(SIGINT, sig_handler); /* establish handler */
+ ...
+
+int sig_handler()
+{
+ signal(SIGINT, sig_handler); /* restablish handler */
+ ... /* process signal */
+}
+\end{lstlisting}
+\normalsize
+se un secondo segnale arriva prima che il manipolatore invocato dal primo
+abbia eseguito la re-installazione di se stesso il segnale può essere perso o
+causare il comportamento originale assegnato al segnale (in genere la
+terminazione del processo).
+
+Questa è la ragione per cui l'implementazione dei segnali secondo questa
+semantica viene chiamata \textit{inaffidabile}, in quanto la ricezione del
+segnale e la reinstallazione del suo manipolatore non sono operazioni
+atomiche.
+
+Un'altro problema è che in questa semantica è che non esiste un modo per
+bloccare i segnali quando non si vuole che arrivino; i processi possono si
+ignorare il segnale, ma non è possibile istruire il sistema a non fare nulla
+in occasione di un segnale, pur mantenendo memoria del fatto che è avvenuto.
+
+Un caso classico, riportato da Stevens, in cui si incontra questo problema, è
+quello in cui si usa il manipolatore per settare un flag che riporta al
+processo l'occorrenza del segnale. Si consideri il seguente segmento di
+codice il cui scopo sarebbe quello di fermare il processo fino all'occorrenza
+di un opportuno segnale:
+\footnotesize
+\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
+int signal_flag = 0;
+main ()
+{
+ int sig_handler(); /* handler function */
+ ...
+ signal(SIGINT, sig_handler); /* establish handler */
+ ...
+ while(signal_flag == 0) { /* while flag is zero */
+ pause(); /* go to sleep */
+ }
+ ...
+}
+int sig_handler()
+{
+ signal(SIGINT, sig_handler); /* restablish handler */
+ signal_flag = 1; /* set flag */
+}
+\end{lstlisting}
+\normalsize
+l'idea è che quando il processo trova il flag a zero viene messo in sleep e
+verrà risvegliato solo dalla ricezione di un segnale. Il manipolatore si
+limita in questo caso a settare il flag a uno; all'uscita dal manipolatore la
+chiamata a \func{pause} è interrotta ed il processo viene risvegliato e
+riprende l'esecuzione all'istruzione successiva, ma essendo cambiato il flag
+la condizione non è più soddisfatta e il programma prosegue.
+
+Il problema con l'implementazione inaffidabile è che niente ci garantisce che
+il segnale arrivi fra la valutazione della condizione del \func{while} e la
+chiamata a \func{pause}, nel qual caso, se il segnale non viene più generato,
+il processo resterà in sleep permanentemente.
+
+% Un'altra caratteristica della implementazione inaffidabile è che le chiamate
+% di sistema non sono fatte ripartire automaticamente quando sono interrotte da
+% un segnale, per questo un programma deve controllare lo stato di uscita della
+% chiamata al sistema e riperterla nel caso l'errore riportato da \texttt{errno}
+% sia \texttt{EINTR}.
+
+Questo ci mostra ad esempio come con la semantica inaffidabile non esista una
+modalità semplice per ottenere una operazione di pausa atomica (cioè mandare
+in sleep un processo fino all'arrivo di un segnale).
+
+Nella semantica \textit{reliable} (quella utilizzata da Linux e da ogni Unix
+moderno) invece il signal handler una volta installato resta attivo e non si
+hanno tutti i problemi precedenti. In questa semantica i segnali vengono
+\textsl{generati} dal kernel per un processo all'occorrenza dell'evento che
+causa il segnale. In genere questo viene fatto dal kernel settando un flag
+nella process table del processo.
+
+Si dice che il segnale viene \textsl{consegnato} al processo (dall'inglese
+\textit{delivered}) quando viene eseguita l'azione per esso prevista, mentre
+per tutto il tempo che passa fra la generazione del segnale e la sua consegna
+esso è detto \textsl{pendente}. In genere questa procedura viene effettuata
+dal kernel quando, riprendendo l'esecuzione del processo in questione, verifica
+la presenza del flag del segnale nella process table.
+
+In questa semantica un processo ha la possibilità di bloccare la consegna dei
+segnali, in questo caso se l'azione per il suddetto segnale non è quella di
+ignorarlo, il segnale resta \textsl{pendente} fintanto che il processo non lo
+sblocca (nel qual caso viene consegnato) o setta l'azione di default per
+ignorarlo.
+
+Si tenga presente kernel stabilisce cosa fare con un segnale che è stato
+bloccato al momento della consegna, non quando viene generato; questo consente
+di cambiare l'azione per il segnale prima che esso venga consegnato, e si può
+usare la funzione \func{sigpending} (vedi \secref{sec:sig_sigpending}) per
+determinare quali segnali sono bloccati e quali sono pendenti.
+
+
+
+\subsection{Tipi di segnali}
\label{sec:sig_types}
In generale gli eventi che generano i segnali si possono dividere in tre
devono usare nei programmi. Tutti i nomi e le funzioni che concernono i
segnali sono definiti nell'header di sistema \texttt{signal.h}.
-Il numero totale di segnali presenti è dato dalla macro \texttt{NSIG}, e dato
+Il numero totale di segnali presenti è dato dalla macro \macro{NSIG}, e dato
che i numeri dei segnali sono allocati progressivamente, essa corrisponde
anche al successivo del valore numerico assegnato all'ultimo segnale definito.
In \ntab\ si è riportato l'elenco completo dei segnali definiti in Linux
(estratto dalle man page), comparati con quelli definiti in vari standard.
-
\begin{table}[htb]
+ \footnotesize
\centering
- \begin{tabular}[c]{|l|c|c|c||c|l|}
+ \begin{tabular}[c]{|l|c|c|c||c|p{6cm}|}
\hline
- Segnale & POSIX.1 & SUSv2 & Linux &Azione & Descrizione \\
+ Segnale & POSIX.1 & SUSv2 & Linux &Azione & Descrizione \\
\hline
\hline
- SIGHUP &$\bullet$&&$\bullet$& A & Hangup \\
- SIGINT &$\bullet$&&$\bullet$& A & Interrupt from keyboard \\
- SIGQUIT &$\bullet$&&$\bullet$& C & Quit from keyboard \\
- SIGILL &$\bullet$&&$\bullet$& C & Illegal Instruction \\
- SIGABRT &$\bullet$&&$\bullet$& C & Abort signal from abort(3) \\
- SIGFPE &$\bullet$&&$\bullet$& C & Floating point exception \\
- SIGKILL &$\bullet$&&$\bullet$& AEF & Kill signal \\
- SIGSEGV &$\bullet$&&$\bullet$& C & Invalid memory reference \\
- SIGPIPE &$\bullet$&&$\bullet$& A & Broken pipe \\
- SIGALRM &$\bullet$&&$\bullet$& A & Timer signal from alarm(2) \\
- SIGTERM &$\bullet$&&$\bullet$& A & Termination signal \\
- SIGUSR1 &$\bullet$&&$\bullet$& A & User-defined signal 1 \\
- SIGUSR2 &$\bullet$&&$\bullet$& A & User-defined signal 2 \\
- SIGCHLD &$\bullet$&&$\bullet$& B & Child stopped or terminated \\
- SIGCONT &$\bullet$&&$\bullet$& & Continue if stopped \\
- SIGSTOP &$\bullet$&&$\bullet$& DEF & Stop process \\
- SIGTSTP &$\bullet$&&$\bullet$& D & Stop typed at tty \\
- SIGTTIN &$\bullet$&&$\bullet$& D & tty input for background process \\
- SIGTTOU &$\bullet$&&$\bullet$& D & tty output for background process \\
- SIGBUS &&$\bullet$&$\bullet$& C & Bus error (bad memory access) \\
- SIGPOLL &&$\bullet$&$\bullet$& A & Pollable event (Sys V). Synonym of SIGIO\\
- SIGPROF &&$\bullet$&$\bullet$& A & Profiling timer expired \\
- SIGSYS &&$\bullet$&$\bullet$& C & Bad argument to routine (SVID) \\
- SIGTRAP &&$\bullet$&$\bullet$& C & Trace/breakpoint trap \\
- SIGURG &&$\bullet$&$\bullet$& B & Urgent condition on socket (4.2 BSD) \\
- SIGVTALRM &&$\bullet$&$\bullet$& A & Virtual alarm clock (4.2 BSD) \\
- SIGXCPU &&$\bullet$&$\bullet$& C & CPU time limit exceeded (4.2 BSD) \\
- SIGXFSZ &&$\bullet$&$\bullet$& C & File size limit exceeded (4.2 BSD) \\
+ SIGHUP &$\bullet$&&$\bullet$& A & Hangup o
+ fine del processo di controllo \\
+ SIGINT &$\bullet$&&$\bullet$& A & Interrupt da tastiera (\cmd{C-c})\\
+ SIGQUIT &$\bullet$&&$\bullet$& C & Quit da tastiera (\cmd{C-y}) \\
+ SIGILL &$\bullet$&&$\bullet$& C & Istruzione illegale\\
+ SIGABRT &$\bullet$&&$\bullet$& C & Segnale di Abort da \func{abort} \\
+ SIGFPE &$\bullet$&&$\bullet$& C & Errore aritmetico\\
+ SIGKILL &$\bullet$&&$\bullet$& AEF & Segnale di terminazione forzata \\
+ SIGSEGV &$\bullet$&&$\bullet$& C & Errore di accesso in memoria\\
+ SIGPIPE &$\bullet$&&$\bullet$& A & Pipe spezzata\\
+ SIGALRM &$\bullet$&&$\bullet$& A & Segnale del timer da \func{alarm} \\
+ SIGTERM &$\bullet$&&$\bullet$& A & Segnale di terminazione \verb|C-\|\\
+ SIGUSR1 &$\bullet$&&$\bullet$& A & User-defined signal 1\\
+ SIGUSR2 &$\bullet$&&$\bullet$& A & User-defined signal 2\\
+ SIGCHLD &$\bullet$&&$\bullet$& B & Child stopped or terminated\\
+ SIGCONT &$\bullet$&&$\bullet$& & Continue if stopped\\
+ SIGSTOP &$\bullet$&&$\bullet$& DEF & Stop process\\
+ SIGTSTP &$\bullet$&&$\bullet$& D & Stop typed at tty \\
+ SIGTTIN &$\bullet$&&$\bullet$& D & tty input for background process \\
+ SIGTTOU &$\bullet$&&$\bullet$& D & tty output for background process \\
+ SIGBUS &&$\bullet$&$\bullet$& C & Bus error (bad memory access) \\
+ SIGPOLL &&$\bullet$&$\bullet$& A & Pollable event (Sys V). Synonym of SIGIO\\
+ SIGPROF &&$\bullet$&$\bullet$& A & Profiling timer expired \\
+ SIGSYS &&$\bullet$&$\bullet$& C & Bad argument to routine (SVID)\\
+ SIGTRAP &&$\bullet$&$\bullet$& C & Trace/breakpoint trap \\
+ SIGURG &&$\bullet$&$\bullet$& B & Urgent condition on socket (4.2 BSD)\\
+ SIGVTALRM &&$\bullet$&$\bullet$& A & Virtual alarm clock (4.2 BSD) \\
+ SIGXCPU &&$\bullet$&$\bullet$& C & CPU time limit exceeded (4.2 BSD) \\
+ SIGXFSZ &&$\bullet$&$\bullet$& C & File size limit exceeded (4.2 BSD)\\
SIGIOT &&&$\bullet$& C & IOT trap. A synonym for SIGABRT \\
SIGEMT &&&$\bullet$& & \\
SIGSTKFLT &&&$\bullet$& A & Stack fault on coprocessor \\
\caption{Lista dei segnali in Linux}
\label{tab:sig_signal_list}
\end{table}
-in \curtab\ si sono riportate anche le caratteristiche di ciascun segnale,
-indicate con una lettera nel campo azione, la cui legenda è:
+in \curtab\ si sono riportate le azioni di default di ciascun segnale
+(riassunte con delle lettere, la cui legenda completa è in \ntab), quando
+nessun manipolatore è installato un segnale può essere ignorato o causare la
+terminazione del processo.
+
+In alcuni casi alla terminazione del processo è associata la creazione di un
+file (posto nella directory corrente del processo e chiamato \file{core}) su
+cui viene salvata un'immagine della memoria del processo (il cosiddetto
+\textit{core dump}), che può essere usata da un debugger per esaminare lo
+stato dello stack e delle variabili al momento della ricezione del segnale.
+
\begin{table}[htb]
\centering
- \begin{tabular}[c]{c p{6cm}}
+ \begin{tabular}[c]{|c|p{8cm}|}
+ \hline
+ Sigla & Significato \\
+ \hline
+ \hline
A & L'azione di default è terminare il processo. \\
B & L'azione di default è ignorare il segnale. \\
C & L'azione di default è terminare il processo e scrivere un \textit{core
D & L'azione di default è fermare il processo. \\
E & Il segnale non può essere intercettato. \\
F & Il segnale non può essere ignorato.\\
+ \hline
\end{tabular}
\caption{Legenda delle caratteristiche dei segnali riportate in
\tabref{tab:sig_signal_list}. }
\label{tab:sig_action_leg}
\end{table}
-la descrizione dettagliata del significato dei vari segnali, raggruppati per
-tipologia, è a seguire; una descrizione dettagliata del significato delle
-varie azioni si trova invece in \secred{sec:sig_handlers}.
+La descrizione dettagliata del significato dei vari segnali, raggruppati per
+tipologia, verrà affrontate nel seguito.
-\subsubsection{Segnali di errore di programma}
+\subsection{Segnali di errore di programma}
\label{sec:sig_prog_error}
Questi segnali sono generati quando il sistema, o in certi casi direttamente
L'azione di default per tutti questi segnali è causare la terminazione del
processo che li ha causati. In genere oltre a questo il segnale provoca pure
la registrazione su disco di un file di \textit{core dump} che viene scritto
-in un file \texttt{core} nella directory corrente del processo al momento
+in un file \file{core} nella directory corrente del processo al momento
dell'errore, che il debugger può usare per ricostruire lo stato del programma
al momento della terminazione.
Questi segnali sono:
\begin{description}
-\item \texttt{SIGFPE} Riporta un errore aritmetico fatale. Benché il nome
+\item \macro{SIGFPE} Riporta un errore aritmetico fatale. Benché il nome
derivi da \textit{floating point exception} si applica a tutti gli errori
aritmetici compresa la divisione per zero e l'overflow.
% standard IEEE per le operazioni in virgola mobile definisce vaire eccezioni
% aritmetiche e richiede che esse siano notificate.
-\item \texttt{SIGILL} Il nome deriva da \textit{illegal instruction},
+\item \macro{SIGILL} Il nome deriva da \textit{illegal instruction},
significa che il programma sta cercando di eseguire una istruzione
privilegiata o inesistente, in generale del codice illegale. Poiché il
compilatore del C genera del codice valido si ottiene questo segnale se il
una variabile locale, andando a corrompere lo stack. Lo stesso segnale viene
generato in caso di overflow dello stack o di problemi nell'esecuzione di di
un signal handler.
-\item \texttt{SIGSEGV} Il nome deriva da \textit{segment violation}, e
+\item \macro{SIGSEGV} Il nome deriva da \textit{segment violation}, e
significa che il programma sta cercando di leggere o scrivere in una zona di
memoria protetta al di fuori di quella che gli è stata riservata dal
sistema. In genere è il meccanismo della protezione della memoria che si
È tipico ottenere questo segnale dereferenziando un puntatore nullo o non
inizializzato leggendo al di la della fine di un vettore.
-\item \texttt{SIGBUS} In maniera analoga a \texttt{SIGSEGV} questo è un
- segnale che viene generato di solito quando si dereferenzia un puntatore non
- inzializzato, la differenza con con \texttt{SIGSEGV} è che questo indica un
- accesso non valido su un indirizzo esistente (tipo fuori dallo heap o dallo
- stack), mentre \texttt{SIGBUS} indica l'accesso ad un indirizzo non valido,
- come nel caso di un puntatore non allineato.
-\item \texttt{SIGABRT} Il segnale indica che il programma stesso ha rilevato
- un errore che viene riportato chiamando la funzione \texttt{abort} che
- genera questo segnale.
-\item \texttt{SIGTRAP}
-\item \texttt{SIGSYS} Sta ad indicare che si è eseguta una istruzione che
+\item \macro{SIGBUS} Il nome deriva da \textit{bus error}. Come
+ \macro{SIGSEGV} questo è un segnale che viene generato di solito quando si
+ dereferenzia un puntatore non inzializzato, la differenza è che
+ \macro{SIGSEGV} indica un accesso non permesso su un indirizzo esistente
+ (tipo fuori dallo heap o dallo stack), mentre \macro{SIGBUS} indica
+ l'accesso ad un indirizzo non valido, come nel caso di un puntatore non
+ allineato.
+\item \macro{SIGABRT} Il nome deriva da \textit{abort}. Il segnale indica che
+ il programma stesso ha rilevato un errore che viene riportato chiamando la
+ funzione \func{abort} che genera questo segnale.
+\item \macro{SIGTRAP} È il segnale generato da un'istruzione di breakpoint o
+ dall'attivazione del tracciamento per il processo. È usato dai programmi per
+ il debugging e se un programma normale non dovrebbe ricevere questo segnale.
+\item \macro{SIGSYS} Sta ad indicare che si è eseguita una istruzione che
richiede l'esecuzione di una system call, ma si è fornito un codice
sbagliato per quest'ultima.
\end{description}
L'azione di default di questi segnali è di terminare il processo, questi
segnali sono:
\begin{description}
-\item \texttt{SIGTERM}
-\item \texttt{SIGINT}
-\item \texttt{SIGQUIT}
-\item \texttt{SIGKILL}
-\item \texttt{SIGHUP}
+\item \macro{SIGTERM} Il nome sta per \textit{terminate}. È un segnale
+ generico usato per causare la conclusione di un programma. Al contrario di
+ \macro{SIGKILL} può essere intercettato, ignorato, bloccato. In genere lo si
+ usa per chiedere in maniera ``educata'' ad un processo di concludersi.
+\item \macro{SIGINT} Il nome sta per \textit{interrupt}. È il segnale di
+ interruzione per il programma. È quello che viene generato di default dal
+ comando \cmd{kill} o dall'invio sul terminale del carattere di controllo
+ INTR (interrupt, generato dalla sequenza \macro{C-c}).
+\item \macro{SIGQUIT} È analogo a \macro{SIGINT} con la differenze che è
+ controllato da un'altro carattere di controllo, QUIT, corrispondente alla
+ sequenza \macro{C-\\}. A differenza del precedente l'azione di default,
+ oltre alla terminazione del processo, comporta anche la creazione di un core
+ dump.
+
+ In genere lo si può pensare come corrispondente ad una condizione di
+ errore del programma rilevata dall'utente. Per questo motivo non è opportuno
+ fare eseguire al manipolatore di questo segnale le operazioni di pulizia
+ normalmente previste (tipo la cancellazione di file temporanei), dato che in
+ certi casi esse possono eliminare informazioni utili nell'esame dei core
+ dump.
+\item \macro{SIGKILL} Il nome è utilizzato per terminare in maniera immediata
+ qualunque programma. Questo segnale non può essere né intercettato, né
+ ignorato, né bloccato, per cui causa comunque la terminazione del processo.
+ In genere esso viene generato solo per richiesta esplicita dell'utente dal
+ comando (o tramite la funzione) \cmd{kill}. Dato che non lo si può
+ intercettare è sempre meglio usarlo come ultima risorsa quando metodi meno
+ brutali, come \macro{SIGTERM} o \macro{C-c} non funzionano.
+
+ Se un processo non risponde a nessun altro segnale \macro{SIGKILL} ne causa
+ sempre la terminazione (in effetti il fallimento della terminazione di un
+ processo da parte di \macro{SIGKILL} costituirebbe un funzionamento del
+ kernel). Talvolta è il sistema stesso che può generare questo segnale quando
+ per condizioni particolari il processo non può più essere eseguito neanche
+ per eseguire il manipolatore.
+\item \macro{SIGHUP} Il nome sta per \textit{hang-up}. Segnala che il
+ terminale dell'utente si è disconnesso (ad esempio perché si è interrotta la
+ rete). Viene usato anche per riportare la terminazione del processo di
+ controllo di un terminale a tutti i processi della sessione, in modo che
+ essi possano disconnettersi dal relativo terminale.
+
+ Viene inoltre usato in genere per segnalare ai demoni (che non hanno un
+ terminale di controllo) la necessità di reinizializzarsi e rileggere il/i
+ file di configurazione.
\end{description}
\subsection{I segnali di allarme}
\label{sec:sig_alarm}
-Questi segnali sono generati dalla scadenza di un temporizzatore. Il loro
-comportamento di default è quello di causare la terminazione del programma, ma
-nessun default ha una utlità avrebbe una utilità particolare, in quanto l'uso
-di questi segnali presuppone quasi sempre la necessità di un
-manipolatore. Questi segnali sono:
+Questi segnali sono generati dalla scadenza di un timer. Il loro comportamento
+di default è quello di causare la terminazione del programma, ma con questi
+segnali la scelta di default è irrilevante, in quanto il loro uso presuppone
+sempre la necessità di un manipolatore. Questi segnali sono:
\begin{description}
-\item \texttt{SIGALRM}
-\item \texttt{SIGVTALRM}
-\item \texttt{SIGPROF}
+\item \macro{SIGALRM} Il nome sta per \textit{alarm}. Segnale la scadenza di
+ un timer misurato sul tempo reale o sull'orologio di sistema. È normalmente
+ usato dalla funzione \func{alarm}.
+\item \macro{SIGVTALRM} Il nome sta per \textit{virtual alarm}. È analogo al
+ precedente ma segnala la scadenza di un timer sul tempo di CPU usato dal
+ processo.
+\item \macro{SIGPROF} Il nome sta per \textit{profiling}. Indica la scadenza
+ di un timer che misura sia il tempo di CPU speso direttamente dal processo
+ che quello che il sistema ha speso per conto di quest'ultimo. In genere
+ viene usato dai tool che servono a fare il profilo d'uso della CPU da parte
+ del processo.
\end{description}
L'azione di default è di essere ignorati. Questi segnali sono:
\begin{description}
-\item \texttt{SIGIO}
-\item \texttt{SIGURG}
-\item \texttt{SIGPOLL}
+\item \macro{SIGIO} Questo segnale viene inviato quando un file descriptor è
+ pronto per eseguire dell'input/output. In molti sistemi solo i socket e i
+ terminali possono generare questo segnale, in Linux questo può essere usato
+ anche per i file, posto che la \func{fcntl} abbia avuto successo.
+\item \macro{SIGURG} Questo segnale è inviato quando arrivano dei dati
+ urgenti o \textit{out of band} su di un socket; per maggiori dettagli al
+ proposito si veda \secref{sec:xxx_urgent_data}.
+\item \macro{SIGPOLL} Questo segnale è equivalente a \macro{SIGIO}, è
+ definito solo per compatibilità con i sistemi System V.
\end{description}
\subsection{I segnali per il controllo di sessione}
\label{sec:sig_job_control}
-Questi sono i segnali usati dal controllo di sessione, il loro uso è specifico
-per questo argomento e verrà trattato quando lo affronteremo.
-Questi segnali sono:
-\begin{description}
-\item \texttt{SIGCHLD}
-\item \texttt{SIGCONT}
-\item \texttt{SIGSTOP}
-\item \texttt{SIGTSTP}
-\item \texttt{SIGTTIN}
-\item \texttt{SIGTTOU}
+Questi sono i segnali usati dal controllo delle sessioni e dei processi, il
+loro uso è specifico e viene trattato in maniera specifica nelle sezioni in
+cui si trattano gli argomenti relativi. Questi segnali sono:
+\begin{description}
+\item \macro{SIGCHLD} Questo è il segnale mandato al processo padre quando un
+ figlio termina o viene fermato. L'azione di default è di ignorare il
+ segnale, la sua gestione è trattata in \secref{sec:proc_wait}.
+\item \macro{SIGCLD} Per Linux questo è solo un segnale identico al
+ precedente, il nome è obsoleto e andrebbe evitato.
+\item \macro{SIGCONT} Il nome sta per \textit{continue}. Il segnale viene
+ usato per fare ripartire un programma precedentemente fermato da
+ \macro{SIGSTOP}. Questo segnale ha un comportamento speciale, e fa sempre
+ ripartire il processo prima della sua consegna. Il comportamento di default
+ è di fare solo questo; il segnale non può essere bloccato. Si può anche
+ installare un manipolatore, ma il segnale provoca comunque il riavvio del
+ processo.
+
+ La maggior pare dei programmi non hanno necessità di intercettare il
+ segnale, in quanto esso è completamente trasparente rispetto all'esecuzione
+ che riparte senza che il programma noti niente. Si possono installare dei
+ manipolatori per far si che un programma produca una qualche azione speciale
+ se viene fermato e riavviato, come per esempio riscrivere un prompt, o
+ inviare un avviso.
+\item \macro{SIGSTOP} Il segnale ferma un processo (lo porta in uno stato di
+ sleep); il segnale non può essere né intercettato, né ignorato, né bloccato.
+\item \macro{SIGTSTP} Il nome sta per \textit{interactive stop}. Il segnale
+ ferma il processo interattivamente, ed è generato dal carattere SUSP
+ (prodotto dalla combinazione \macro{C-z}), ed al contrario di
+ \macro{SIGSTOP} può essere intercettato e ignorato. In genere un programma
+ installa un manipolatore per questo segnale quando vuole lasciare il sistema
+ o il terminale in uno stato definito prima di fermarsi; se per esempio un
+ programma ha disabilitato l'eco sul terminale può installare un manipolatore
+ per riabilitarlo prima di fermarsi.
+\item \macro{SIGTTIN}
+\item \macro{SIGTTOU}
\end{description}
\subsection{I segnali di operazioni errate}
L'azione di default di questi segnali è di terminare il processo, questi
segnali sono:
\begin{description}
-\item \texttt{SIGPIPE}
-\item \texttt{SIGLOST}
-\item \texttt{SIGXCPU}
-\item \texttt{SIGXFSZ}
+\item \macro{SIGPIPE} Sta per \textit{Broken pipe}. Se si usano delle pipe o
+ delle FIFO è necessario che, prima che un processo inizi a scrivere su di
+ essa, un'altro abbia aperto la pipe in lettura (si veda
+ \secref{sec:ipc_pipes}). Se il processo in lettura non è partito o è
+ terminato inavvertitamente alla scrittura sulla pipe il kernel genera questo
+ segnale. Se il segnale è bloccato, intercettato o ignorato la chiamata che
+ lo ha causato fallisce restituendo l'errore \macro{EPIPE}
+\item \macro{SIGLOST} Sta per \textit{Resource lost}.
+\item \macro{SIGXCPU} Sta per \textit{CPU time limit exceeded}.
+\item \macro{SIGXFSZ} Sta per \textit{File size limit exceeded}.
\end{description}
Raccogliamo qui infine usa serie di segnali che hanno scopi differenti non
classificabili in maniera omogenea. Questi segnali sono:
\begin{description}
-\item \texttt{SIGUSR1} e \texttt{SIGUSR2} Sono due segnali a disposizione
+\item \macro{SIGUSR1} e \macro{SIGUSR2} Sono due segnali a disposizione
dell'utente che li può usare per quello che vuole. Possono essere utili per
implementare una comunicazione elementare fra processi diversi, o per
- eseguire a richiesta una operazione utlizzando un manipolatore. L'azione di
- default è terminare il processo.
-\item \texttt{SIGWINCH} Il nome sta per \textit{window (size) change} ed è
+ eseguire a richiesta una operazione utilizzando un manipolatore. L'azione di
+ default è terminare il processo.
+\item \macro{SIGWINCH} Il nome sta per \textit{window (size) change} ed è
generato da molti sistemi (GNU/Linux compreso) quando le dimensioni (in
righe e colonne) di un terminale vengono cambiate. Viene usato da alcuni
programmi testuali per riformattare l'uscita su schermo quando si cambia
dimensione a quest'ultimo. L'azione di default è di essere ignorato.
-\item \texttt{SIGINFO} Il segnale indica una richiesta di informazioni. È
+\item \macro{SIGINFO} Il segnale indica una richiesta di informazioni. È
usato con il controllo di sessione, causa la stampa di informazioni da parte
del processo leader del gruppo associato al terminale di controllo, gli
altri processi lo ignorano.
\end{description}
+\subsection{Le funzioni \func{strsignal} e \func{psignal}}
+\label{sec:sig_strsignal}
+
+Per la descrizione dei segnali il sistema mette a disposizione due funzioni
+che stampano un messaggio di descrizione dato il numero. In genere si usano
+quando si vuole notificare all'utente il segnale avvenuto (nel caso di
+terminazione di un processo figlio o di un manipolatore che gestisce più
+segnali); la prima funzione è una estensione GNU ed è analoga alla funzione
+\func{strerr} per gli errori:
+\begin{prototype}{string.h}{char * strsignal (int signum)}
+ Ritorna il puntatore ad una stringa allocata staticamente che contiene la
+ descrizione del segnale \var{signum}.
+\end{prototype}
+
+Dato che la stringa è allocata staticamente non se ne deve modificare il
+contenuto, che resta valido solo fino alla successiva chiamata di
+\func{strsignal}; nel caso si debba mantenere traccia del messaggio sarà
+necessario copiarlo.
+
+La seconda funzione deriva da BSD ed è analoga alla funzione \func{perror}
+descritta in \secref{sec:intro_strerror}.
+
\section{La gestione dei segnali}
\label{sec:sig_handlers}
tutto quello che si potrà fare è di specificare (al kernel, che li genera)
quale azione andrà intrapresa quando essi si verificano.
-In questa sezione vedremo allora come si gestiscono i segnali, partendo dalla
-descrizione di cosa fanno le azioni di default citate in precedenza, per poi
-esaminare le funzioni usate per personalizzare la gestione dei segnali,
-analizzando tutte le problematiche relative alla gestione di eventi asincroni
-di questo tipo.
-
-
-
-\subsection{Le azioni di default}
-\label{sec:sig_default_acttion}
+In questa sezione vedremo allora come si gestiscono i segnali, esaminando le
+funzioni che si usano per effettuare la gestione dei segnali ed analizzando le
+problematiche relative alla gestione di eventi asincroni di questo tipo.
+
+
+\subsection{La funzione \func{signal}}
+\label{sec:sig_signal}
+
+L'interfaccia più semplice alla manipolazione dei segnali è costituita dalla
+funzione \func{signal}; questa funzione è definita fin dallo standard ANSI C
+che però non considera sistemi multitasking, per cui la sua definizione in
+tale standard è tanto vaga da essere del tutto inutile in un sistema unix, per
+questo ogni implementazione successiva ne ha modificato e ridefinito il
+comportamento, pur mantenendone immutato il prototipo\footnote{in realtà
+ alcune vecchie implementazioni (SVR4 e 4.3+BSD) usano parametri aggiuntivi
+ per definire il comportamento della funzione} che è:
+\begin{prototype}{signal.h}
+ {sighandler\_t signal(int signum, sighandler\_t handler)}
+
+ Installa una nuova funzione di gestione (manipolatore) per il segnale
+ \param{signum}, usando il manipolatore \param{handler}.
+
+ La funzione ritorna il precedente manipolatore in caso di successo o
+ \macro{SIG\_ERR} in caso di errore.
+\end{prototype}
+
+In questa definizione si è usato il tipo \type{sighandler\_t} che è una
+estensione GNU definita in Linux che permette di riscrivere il prototipo in
+forma più leggibile dell'originario \func{void (*signal(int signum, void
+ (*handler)(int)))int)}, e che è sostanzialmente equivalente alla
+definizione:
+\begin{verbatim}
+typedef void (* sighandler_t)(int)
+\end{verbatim}
+cioè un puntatore ad una funzione di tipo \type{void} con un parametro di tipo
+\type{int}\footnote{si devono usare le parentesi intorno al nome della
+ funzione per via delle precedenze degli operatori del C, senza di esse si
+ sarebbe definita una funzione che ritorna un puntatore a \type{void} e non
+ un puntatore ad una funzione \type{void}}.
+
+Il numero di segnale passato in \param{signum} segnale può essere indicato
+direttamente con una delle costanti definite in \secref{sec:sig_standard}, il
+manipolatore \param{handler} invece, oltre all'indirizzo della funzione da
+chiamare all'occorrenza del segnale, può assumere anche i valori costanti
+\macro{SIG\_IGN} con cui si dice ignorare il segnale e \macro{SIG\_DFL} per
+installare l'azione di di default (si ricordi però che i due segnali
+\macro{SIGKILL} e \macro{SIGSTOP} non possono essere ignorati né
+intercettati).
+
+
+\subsection{Funzioni rientranti e default dei segnali}
+\label{sec:sig_reentrant}