Initial revision
[gapil.git] / signal.tex
diff --git a/signal.tex b/signal.tex
new file mode 100644 (file)
index 0000000..60a7b52
--- /dev/null
@@ -0,0 +1,238 @@
+\chapter{I segnali}
+\label{sec: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
+loro tipo, si tratta in sostanza di un'interruzione software portata ad un
+processo.
+
+In genere i segnali vengono usati dal kernel per riportare situazioni
+eccezionali (come errori di accesso, eccezioni atritmetiche, etc.) ma possono
+anche essere usati come forma elementare di comunicazione fra processi (ad
+esempio vengono usati per il controllo di sessione), per notificare eventi
+(come la terminazione di un processo figlio), etc.
+
+\section{I concetti base}
+\label{sec:sig_base}
+
+Come il nome stesso indica i segnali sono usati per notificare ad un processo
+l'occorrenza di un evento eccezionale. Gli eventi che possono generare un
+segnale sono vari; un breve elenco di possibile cause è il seguente:
+
+\begin{itemize}
+\item un errore del programma, come una divisione per zero o un tentativo di
+  accesso alla memoria fuori dai limiti validi.
+\item la terminazione di un processo figlio.
+\item la scadenza di un timer o di un allarme.
+\item il tentativo di effettuare un'operazione di input/output che non può
+  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'.
+\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.
+
+
+\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
+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 il segnale arriva
+prima che il suo manipolatore sia installato, nel qual caso il segnale può
+essere perso o causare il comportamento originale (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 oiperazioni atomiche.
+
+In 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 sisteme possono essere fatte ripartire automaticamente e si può
+ottenere un'operazione di pausa atomica (usando la funzione POSIX
+\texttt{sigsuspend}).
+
+
+\subsubsection{Tipi di segnali}
+\label{sec:sig_types}
+
+
+In generale gli eventi che generano i segnali si possono diviedere in tre
+categorie principali: errori, eventi e richieste esplicite. 
+
+Un errore significa che un programma ha fatto qualcosa di sbagliato e non può
+continuare ad essere eseguito. Non tutti gli errori causano dei segnali, in
+genere la condizione di errore più comune comporta la restituzione di un
+codice di errore da parte di una funzione di libreria, sono gli errori che
+possono avvenire ovunque in un programma che causano l'emissione di un
+segnale, come le divisioni per zero o l'uso di indirizzi di memoria non validi.
+
+Un evento esterno ha in genere a che fare con l'I/O o con altri processi;
+esempi di segnali di questo tipo sono quelli legati all'arrivo di dati di
+input, scadenze di un timer, terminazione di processi figli.
+
+Una richiesta esplicita significa l'uso di una chiamata di sistema (come
+\texttt{kill} o \texttt{raise}) per la generazione di un segnale, cosa che
+viene fatta usualmente dalla shell quando l'utente invoca la sequenza di tasti
+di stop o di suspend, ma può essere pure inserita all'interno di un programma.
+
+Si dice poi che i segnali possono essere \textit{asincroni} o
+\textit{sincroni}. Un segnale sincrono è legato ad una azione specifica di un
+programma ed è inviato (a meno che non sia bloccato) durante tale azione;
+molti errori generano segnali sincroni, così come la richiesta esplicita da
+parte del processo tramite le chiamate al sistema. Alcuni errori come la
+divisione per zero non sono completamente sincroni e possono arrivare dopo
+qualche istruzione.
+
+I segnali asincroni sono generati da eventi fuori dal controllo del processo
+che li riceve e arrivano in tempi impredicibili nel corso dell'esecuzione del
+programma. Eventi esterni come la terminazione di un processo figlio generano
+segnali asincroni, così come le richieste di generazione di un segnale
+effettuate da altri processi.
+
+In generale un tipo di segnale o è sincrono o è asincrono, salvo il caso in
+cui esso sia generato attraverso una richiesta esplicita tramite chiamata al
+sistema, nel qual caso qualunque tipo di segnale (quello scelto nella
+chiamata) può diventare sincrono o asincrono a seconda che sia generato
+internamente o esternamente al processo.
+
+\section{La notifica dei segnali}
+\label{sec:sig_notification}
+
+Quando un segnale viene generato il kernel prende nota del fatto; si dice così
+che diventa \textit{pending} (sospeso), e rimarrà tale fino al momento in cui
+verrà notificato al processo a cui deve essere inviato.
+
+Normalmente l'invio al processo che deve ricevere il segnale è immediato, a
+meno che il segnale in questione non sia stato bloccato (\textit{blocked}) nel
+qual caso l'invio non avviene ed il segnale resta sospeso indefinitamente. Una
+volta però che esso venga sbloccato il segnale sarà subito notificato.
+
+Una volta che il segnale viene notificato (che questo avvenga subito o dopo
+una attesa più o meno lunga) viene eseguita l'azione specificata per detto
+segnale. Per alcuni segnali (\texttt{SIGKILL} e \texttt{SIGSTOP}) questa azione
+è fissa e non può essere cambiata, ma per tutti gli altri il programma può
+specificare una scelta fra le tre seguenti:
+
+\begin{itemize}
+\item ignorare il segnale
+\item utilizzare il manipolatore (\textit{signal handler}) specificato
+\item accettare l'azione di default per quel segnale.
+\end{itemize}
+
+Il programma può specificare queste scelte usano le due routine
+\texttt{signal} e \texttt{sigaction}; se si è installato un manipalatore sarà
+quest'ultimo a intercettare il segnale ed ad essere eseguito, e mentre viene
+eseguito (onde evitare race conditions) il segnale viene bloccato.
+
+Se l'azione specificata per un certo tipo di segnale è quella di ignorarlo
+questo sarà scartato immediatamente ogni volta che verrà generato, e questo
+avverrà anche se in quel momento il segnale è bloccato. Per questo un segnale
+ignorato non sarà mai notificato, anche se in seguito si sarà specificata una
+diversa azione per lo stesso segnale.
+
+Se arriva un segnale per il quale non è stato specificata un'azione viene
+utilizzata l'azione standard. Questa è diversa da segnale a segnale (come
+vedremo in \ref{sec:sig_standard}) ma per la maggior parte essa comporta la
+terminazione del processo, per alcuni che invece rappresentano eventi innoqui
+l'azione standard è di non fare nulla.
+
+Quando un segnale termina un processo, il padre può determinare la causa della
+terminazione esaminando il codice di stato riportato delle funzioni
+\texttt{wait} e \texttt{waitpid} in cui è riportato anche se la causa è un
+segnale e nel caso quale; questo è il modo in cui la shell determina i motivi
+della terminazione di un programma e scrive un eventuale messaggio di errore.
+
+I segnali che rappresentano errori del programma (divisione per zero o
+violazioni di accesso) hanno anche la caratteristica di scrivere un file
+\textit{core dump} che registra lo stato del processo prima della terminazione
+e può essere esaminato da un debugger per investigare sulla causa dell'errore.
+Lo stesso avvine se i suddetti segnale vengono generati artificialmente con
+una \texttt{kill}.
+
+
+
+\subsection{I segnali standard}
+\label{sec:sig_standard}
+
+Esaminiamo ora i vari segnali disponibili e le loro caratteristiche. 
+Ciascun segnale è identificato rispetto al sistema da un numero, ma l'uso
+diretto di questo numero da parte dei programmi è da evitare, in quanto esso
+può variare a seconda dell'implementazione del sistema.
+
+Per questo ad ogni tipo di segnale viene associato un nome, che corrisponde
+tramite una macro di preprocessore, al suddetto numero, e sono questi nomi,
+che sono standardizzati e uniformi rispetto alle varie implementazioni, che si
+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
+che i numeri dei segnali sono allocati progressivamente, essa corrisponde
+anche al successivo del valore numerico assegnato al'ultimo segnale definito.
+
+
+\subsubsection{Segnali di errore di programma}
+
+Questi segnali sono generati quando c'é un grave errore nel programma rilevato
+dal sistema o dallo stesso hardware. In generale indicano che il programma ha
+dei gravi problemi e l'esecuzione non può essere proseguita. 
+
+Alcuni programmi usano questi segnali per riordinare le cose prima di uscire.
+As esempio ripristinare i settaggi della console, o eliminare i file di lock.
+In questo caso il manipolatore deve concludersi ripristinando l'azione di
+default e rialzando il segnale, così che il programma possa concludersi come
+se il manipolatore non ci fosse mai stato.
+
+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 \textit{core dump file} che viene scritto in
+un file \texttt{core} nella directory corrente del processo al momento
+dell'errore. 
+
+Questi segnali sono:
+
+\begin{itemize}
+\item \texttt{SIGFPE} Riporta un errore aritmetico fatale. Benchè il nome
+  derivi da \textit{floating point exception} si applica a tutti gli errori
+  aritmetici comprea la divisione per zero e l'overflow.
+
+%   Per questo segnale le cose sono complicate dal fatto che possono esserci
+%   molte diverse eccezioni che \texttt{SIGFPE} non distingue, mentre lo
+%   standard IEEE per le operazioni in virgola mobile definisce vaire eccezioni
+%   aritmetiche e richiede che esse siano notificate.  
+\item \texttt{SIGFPE} Il nome deriva da \textit{illegal instruction} 
+\item \texttt{SIGILL} 
+\item \texttt{SIGSEGV} 
+\item \texttt{SIGBUS} 
+\item \texttt{SIGABRT} 
+\item \texttt{SIGTRAP} 
+\item \texttt{SIGSYS} 
+
+\end{itemize}
+