partendo da una introduzione relativa ai concetti base con cui essi vengono
realizzati, per poi affrontarne la classificazione a secondo di uso e modalità
di generazione fino ad esaminare in dettaglio funzioni e le metodologie di
-gestione.
+gestione.
\section{Introduzione}
Questa è la ragione per cui l'implementazione dei segnali secondo questa
semantica viene chiamata \textsl{inaffidabile}; infatti la ricezione del
segnale e la reinstallazione del suo manipolatore non sono operazioni
-atomiche, e sono sempre possibili delle race condition (sull'argomento vedi
-quanto detto in \secref{sec:proc_multi_prog}).
+atomiche, e sono sempre possibili delle race condition\index{race condition}
+(sull'argomento vedi quanto detto in \secref{sec:proc_multi_prog}).
Un'altro problema è che in questa semantica non esiste un modo per bloccare i
segnali quando non si vuole che arrivino; i processi possono ignorare il
\secref{sec:sig_sigaction}). Se si è installato un manipolatore sarà
quest'ultimo ad essere eseguito alla notifica del segnale. Inoltre il sistema
farà si che mentre viene eseguito il manipolatore di un segnale, quest'ultimo
-venga automaticamente bloccato (così si possono evitare race condition).
+venga automaticamente bloccato (così si possono evitare race
+condition\index{race condition}).
Nel caso non sia stata specificata un'azione, viene utilizzata l'azione
standard che (come vedremo in \secref{sec:sig_standard}) è propria di ciascun
\label{sec:sig_prog_error}
Questi segnali sono generati quando il sistema, o in certi casi direttamente
-l'hardware (come per i page fault non validi) rileva un qualche errore
-insanabile nel programma in esecuzione. In generale la generazione di questi
-segnali significa che il programma ha dei gravi problemi (ad esempio ha
+l'hardware (come per i \textit{page fault} non validi) rileva un qualche
+errore insanabile nel programma in esecuzione. In generale la generazione di
+questi segnali significa che il programma ha dei gravi problemi (ad esempio ha
dereferenziato un puntatore non valido o ha eseguito una operazione aritmetica
proibita) e l'esecuzione non può essere proseguita.
\subsection{Il comportamento generale del sistema.}
- \label{sec:sig_gen_beha}
+\label{sec:sig_gen_beha}
Abbiamo già trattato in \secref{sec:sig_intro} le modalità con cui il sistema
gestisce l'interazione fra segnali e processi, ci resta da esaminare però il
#include <sys/wait.h>
#include "macro.h"
-void Hand_CHLD(int sig)
+void sigchld_hand(int sig)
{
int errno_save;
int status;
Le funzioni esaminate finora fanno riferimento ad alle modalità più elementari
della gestione dei segnali; non si sono pertanto ancora prese in
-considerazione le tematiche più complesse, collegate alle varie race condition
-che i segnali possono generare e alla natura asincrona degli stessi.
+considerazione le tematiche più complesse, collegate alle varie race
+condition\index{race condition} che i segnali possono generare e alla natura
+asincrona degli stessi.
Affronteremo queste problematiche in questa sezione, partendo da un esempio
che le evidenzi, per poi prendere in esame le varie funzioni che permettono di
Questo codice però, a parte il non gestire il caso in cui si è avuta una
precedente chiamata a \func{alarm} (che si è tralasciato per brevità),
-presenta una pericolosa race condition. Infatti se il processo viene
-interrotto fra la chiamata di \func{alarm} e \func{pause} può capitare (ad
-esempio se il sistema è molto carico) che il tempo di attesa scada prima
-dell'esecuzione quest'ultima, cosicché essa sarebbe eseguita dopo l'arrivo di
-\macro{SIGALRM}. In questo caso ci si troverebbe di fronte ad un deadlock, in
-quanto \func{pause} non verrebbe mai più interrotta (se non in caso di un
-altro segnale).
+presenta una pericolosa race condition\index{race condition}. Infatti se il
+processo viene interrotto fra la chiamata di \func{alarm} e \func{pause} può
+capitare (ad esempio se il sistema è molto carico) che il tempo di attesa
+scada prima dell'esecuzione quest'ultima, cosicché essa sarebbe eseguita dopo
+l'arrivo di \macro{SIGALRM}. In questo caso ci si troverebbe di fronte ad un
+deadlock, in quanto \func{pause} non verrebbe mai più interrotta (se non in
+caso di un altro segnale).
Questo problema può essere risolto (ed è la modalità con cui veniva fatto in
SVr2) usando la funzione \func{longjmp} (vedi \secref{sec:proc_longjmp}) per
segnale, e prendere le relative azioni conseguenti (\texttt{\small 6-11}).
Questo è il tipico esempio di caso, già citato in \secref{sec:proc_race_cond},
-in cui si genera una race condition; se infatti il segnale arriva
-immediatamente dopo l'esecuzione del controllo (\texttt{\small 6}) ma prima
-della cancellazione del flag (\texttt{\small 7}), la sua occorrenza sarà
-perduta.
+in cui si genera una race condition\index{race condition}; se infatti il
+segnale arriva immediatamente dopo l'esecuzione del controllo (\texttt{\small
+ 6}) ma prima della cancellazione del flag (\texttt{\small 7}), la sua
+occorrenza sarà perduta.
Questi esempi ci mostrano che per una gestione effettiva dei segnali occorrono
funzioni più sofisticate di quelle illustrate finora, che hanno origine dalla
\label{fig:sig_sigaction}
\end{figure}
-Come si può notare da quanto riportato in \figref{fig:sig_sigaction} in Linux
-\func{sigaction} permette di specificare il manipolatore in due forme diverse,
-indicate dai campi \var{sa\_handler} e \var{sa\_sigaction}; esse devono essere
-usate in maniera alternativa (in certe implementazioni questi vengono
-specificati come \ctyp{union}): la prima è quella classica usata anche con
-\func{signal}, la seconda permette invece di usare un manipolatore in grado di
-ricevere informazioni più dettagliate dal sistema (ad esempio il tipo di
-errore in caso di \macro{SIGFPE}), attraverso dei parametri aggiuntivi; per i
-dettagli si consulti la man page di \func{sigaction}).
-
Il campo \var{sa\_mask} serve ad indicare l'insieme dei segnali che devono
essere bloccati durante l'esecuzione del manipolatore, ad essi viene comunque
sempre aggiunto il segnale che ne ha causato la chiamata, a meno che non si
\label{tab:sig_sa_flag}
\end{table}
+Come si può notare in \figref{fig:sig_sigaction} \func{sigaction}
+permette\footnote{La possibilità è prevista dallo standard POSIX.1b, ma in
+ Linux è stata aggiunta a partire dai kernel della serie 2.2.x. In precedenza
+ era possibile ottenere alcune informazioni addizionali usando
+ \var{sa\_handler} con un secondo parametro addizionale di tipo \var{struct
+ sigcontext}, che adesso è deprecato.} di utilizzare due forme diverse di
+manipolatore, da specificare, a seconda dell'uso o meno del flag
+\macro{SA\_SIGINFO}, rispettivamente attraverso i campi \var{sa\_sigaction} o
+\var{sa\_handler}, (che devono essere usati in maniera alternativa, in certe
+implementazioni questi vengono addirittura definiti come \ctyp{union}): la
+prima è quella classica usata anche con \func{signal}, la seconda permette
+invece di usare un manipolatore in grado di ricevere informazioni più
+dettagliate dal sistema, attraverso la struttura \var{siginfo\_t}, riportata
+in \figref{fig:sig_siginfo_t}.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
+siginfo_t {
+ int si_signo; /* Signal number */
+ int si_errno; /* An errno value */
+ int si_code; /* Signal code */
+ pid_t si_pid; /* Sending process ID */
+ uid_t si_uid; /* Real user ID of sending process */
+ int si_status; /* Exit value or signal */
+ clock_t si_utime; /* User time consumed */
+ clock_t si_stime; /* System time consumed */
+ sigval_t si_value; /* Signal value */
+ int si_int; /* POSIX.1b signal */
+ void * si_ptr; /* POSIX.1b signal */
+ void * si_addr; /* Memory location which caused fault */
+ int si_band; /* Band event */
+ int si_fd; /* File descriptor */
+}
+ \end{lstlisting}
+ \end{minipage}
+ \normalsize
+ \caption{La struttura \var{siginfo\_t}.}
+ \label{fig:sig_siginfo_t}
+\end{figure}
+
+Installando un manipolatore di tipo \var{sa\_sigaction} diventa allora
+possibile accedere alle informazioni restituite attraverso il puntatore a
+questa struttura. Tutti i segnali settano i campi \var{si\_signo}, che riporta
+il segnale ricevuto, \var{si\_errno}, che riporta il codice di errore, e
+\var{si\_code}, che viene usato per indicare la ragione per cui è stato emesso
+il segnale (come i dettagli sul tipo di errore per \macro{SIGFPE} e
+\macro{SIGILL}) ed ha valori diversi\footnote{un elenco dettagliato è
+ disponibile nella man page di \func{sigaction}.} a seconda del tipo di
+segnale ricevuto.
+
+Il resto della struttura può essere definito come \ctyp{union} ed i valori
+eventualmente presenti dipendono dal segnale, così \macro{SIGCHLD} ed i
+segnali POSIX.1b\footnote{NdA trovare quale sono e completare l'informazione.}
+inviati tramite \func{kill} avvalorano \var{si\_pid} e \var{si\_uid} coi
+valori corrispondenti al processo che ha emesso il segnale, \macro{SIGILL},
+\macro{SIGFPE}, \macro{SIGSEGV} e \macro{SIGBUS} avvalorano \var{si\_addr} con
+l'indirizzo cui è avvenuto l'errore, \macro{SIGIO} (vedi
+\secref{sec:file_asyncronous_io}) e \macro{SIGPOLL} avvalorano \var{si\_fd}
+con il numero del file descriptor.
+
Benché sia possibile usare nello stesso programma sia \func{sigaction} che
\func{signal} occorre molta attenzione, in quanto le due funzioni possono
interagire in maniera anomala. Infatti l'azione specificata con
ripristinare correttamente un manipolatore precedente, anche se questo è stato
installato con \func{signal}. In generale poi non è il caso di usare il valore
di ritorno di \func{signal} come campo \var{sa\_handler}, o viceversa, dato
-che in certi sistemi questi possono essere diversi. In generale dunque, a meno
-che non si sia vincolati allo standard ISO C, è sempre il caso di evitare
-l'uso di \func{signal} a favore di \func{sigaction}.
-
-Per questo motivo si è provveduto, per mantenere un'interfaccia semplificata
-che abbia le stesse caratteristiche di \func{signal}, a definire una funzione
-equivalente attraverso \func{sigaction}; la funzione è \code{Signal}, e si
-trova definita come \code{inline} nel file \file{wrapper.h} (nei sorgenti
-allegati), riportata in \figref{fig:sig_Signal_code}. La riutilizzeremo spesso
-in seguito.
+che in certi sistemi questi possono essere diversi. In definitiva dunque, a
+meno che non si sia vincolati all'aderenza stretta allo standard ISO C, è
+sempre il caso di evitare l'uso di \func{signal} a favore di \func{sigaction}.
\begin{figure}[!htb]
\footnotesize \centering
\label{fig:sig_Signal_code}
\end{figure}
+Per questo motivo si è provveduto, per mantenere un'interfaccia semplificata
+che abbia le stesse caratteristiche di \func{signal}, a definire una funzione
+equivalente attraverso \func{sigaction}; la funzione è \code{Signal}, e si
+trova definita come \code{inline} nel file \file{wrapper.h} (nei sorgenti
+allegati), riportata in \figref{fig:sig_Signal_code}. La riutilizzeremo spesso
+in seguito.
+
\subsection{La gestione della \textsl{maschera dei segnali} o
\textit{signal mask}}
\label{sec:sig_sigmask}
perduta alla conclusione del terminatore.
Benché con l'uso di \func{sigprocmask} si possano risolvere la maggior parte
-dei casi di race condition restano aperte alcune possibilità legate all'uso di
-\func{pause}; il caso è simile a quello del problema illustrato nell'esempio
-di \secref{fig:sig_sleep_incomplete}, e cioè la possibilità che il processo
-riceva il segnale che si intende usare per uscire dallo stato di attesa
-invocato con \func{pause} immediatamente prima dell'esecuzione di
-quest'ultima. Per poter effettuare atomicamente la modifica della maschera dei
-segnali (di solito attivandone uno specifico) insieme alla sospensione del
-processo lo standard POSIX ha previsto la funzione \func{sigsuspend}, il cui
-prototipo è:
+dei casi di race condition\index{race condition} restano aperte alcune
+possibilità legate all'uso di \func{pause}; il caso è simile a quello del
+problema illustrato nell'esempio di \secref{fig:sig_sleep_incomplete}, e cioè
+la possibilità che il processo riceva il segnale che si intende usare per
+uscire dallo stato di attesa invocato con \func{pause} immediatamente prima
+dell'esecuzione di quest'ultima. Per poter effettuare atomicamente la modifica
+della maschera dei segnali (di solito attivandone uno specifico) insieme alla
+sospensione del processo lo standard POSIX ha previsto la funzione
+\func{sigsuspend}, il cui prototipo è:
\begin{prototype}{signal.h}
{int sigsuspend(const sigset\_t *mask)}
\var{sleep\_mask} per riattivare \macro{SIGALRM} all'esecuzione di
\func{sigsuspend}.
-In questo modo non sono più possibili race condition dato che \macro{SIGALRM}
-viene disabilitato con \func{sigprocmask} fino alla chiamata di
-\func{sigsuspend}. Questo metodo è assolutamente generale e può essere
-applicato a qualunque altra situazione in cui si deve attendere per un
+In questo modo non sono più possibili race condition\index{race conditionx}
+dato che \macro{SIGALRM} viene disabilitato con \func{sigprocmask} fino alla
+chiamata di \func{sigsuspend}. Questo metodo è assolutamente generale e può
+essere applicato a qualunque altra situazione in cui si deve attendere per un
segnale, i passi sono sempre i seguenti:
\begin{enumerate}
\item Leggere la maschera dei segnali corrente e bloccare il segnale voluto
parte l'uso di \type{sigjmp\_buf} per \param{env}, è assolutamente identica a
\func{longjmp}.
-\begin{prototype}{signal.h}
-{int sigaltstack(const stack\_t *ss, stack\_t *oss)}
-
-Installa un nuovo stack per i segnali.
-
- \bodydesc{La funzione restituisce zero in caso di successo e -1 per un
- errore, nel qual caso \var{errno} assumerà i valori:
-
- \begin{errlist}
- \item[\macro{ENOMEM}] La dimensione specificata per il nuovo stack è minore
- di \macro{MINSIGSTKSZ}.
- \item[\macro{EPERM}] Uno degli indirizzi non è valido.
- \item[\macro{EFAULT}] Si è cercato di cambiare lo stack alternativo mentre
- questo è attivo (cioè il processo è in esecuzione su di esso).
- \item[\macro{EINVAL}] \param{ss} non è nullo e \var{ss\_flags} contiene un
- valore diverso da zero che non è \macro{SS\_DISABLE}.
- \end{errlist}}
-\end{prototype}
-
-
%%% Local Variables:
%%% mode: latex