Correzioni e aggiunte
[gapil.git] / signal.tex
index be01dc4ec8304c0b992281a202f3c5aa056a6633..940b921157b4a58fa89d7b1a09fc2931fc30dccf 100644 (file)
@@ -84,22 +84,8 @@ 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: 
 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
+s
+e un secondo segnale arriva prima che il manipolatore invocato dal primo
 abbia eseguito la reinstallazione di se stesso il segnale può essere perso o
 causare il comportamento originale assegnato al segnale (in genere la
 terminazione del processo).
 abbia eseguito la reinstallazione di se stesso il segnale può essere perso o
 causare il comportamento originale assegnato al segnale (in genere la
 terminazione del processo).
@@ -322,7 +308,6 @@ In \tabref{tab:sig_signal_list} si 
 definiti in Linux (estratto dalle man page), comparati con quelli definiti in
 vari standard.
 
 definiti in Linux (estratto dalle man page), comparati con quelli definiti in
 vari standard.
 
-
 \begin{table}[htb]
   \footnotesize
   \centering
 \begin{table}[htb]
   \footnotesize
   \centering
@@ -966,43 +951,28 @@ manipolatore potr
 \func{raise}.
 
 Se invece si vuole inviare un segnale ad un altro processo occorre utilizzare
 \func{raise}.
 
 Se invece si vuole inviare un segnale ad un altro processo occorre utilizzare
-la funzione \func{kill}; il suo prototipo è:
+la funzione \func{kill}; il cui prototipo è:
 \begin{functions}
   \headdecl{sys/types.h}
   \headdecl{signal.h}
   \funcdecl{int kill(pid\_t pid, int sig)} Invia il segnale \param{sig} al
   processo specificato con \param{pid}.
 \begin{functions}
   \headdecl{sys/types.h}
   \headdecl{signal.h}
   \funcdecl{int kill(pid\_t pid, int sig)} Invia il segnale \param{sig} al
   processo specificato con \param{pid}.
-
-  \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{EINVAL}] Si è specificato un numero di segnale invalido.
-  \item[\macro{EPERM}] Il processo non ha il permesso di inviare il segnale
-  alla destinazione specificata.
-  \item[\macro{ESRCH}] Il \acr{pid} o il process group indicati non
-  esistono. Gli zombie (vedi \ref{sec:proc_termination}) sono considerati come
-  processi esistenti.
-  \end{errlist}}
 \end{functions}
 
 \end{functions}
 
-La funzione \code{raise(sig)} è sostanzialmente equivalente ad una
-\code{kill(getpid(), sig)}. Siccome \func{raise}, che è definita nello
-standard ISO C, non esiste in alcune vecchie versioni di Unix, in generale
-l'uso di \func{kill} finisce per essere più portabile.
-
-Lo standard POSIX poi prevede che il valore 0 sia usato per specificare il
-segnale nullo.  Se le funzioni vengono chiamate con questo valore non viene
-inviato nessun segnale, ma viene eseguito il controllo degli errori, in tal
-caso si otterrà un errore \macro{EPERM} se non si hanno i permessi necessari
-ed un errore \macro{ESRCH} se il processo specificato non esiste. Si tenga
-conto però che il sistema ricicla i \acr{pid} (come accennato in
-\secref{sec:proc_pid}) per cui l'esistenza di un processo non significa che
+Lo standard POSIX prevede che il valore 0 per \param{sig} sia usato per
+specificare il segnale nullo.  Se le funzioni vengono chiamate con questo
+valore non viene inviato nessun segnale, ma viene eseguito il controllo degli
+errori, in tal caso si otterrà un errore \macro{EPERM} se non si hanno i
+permessi necessari ed un errore \macro{ESRCH} se il processo specificato non
+esiste. Si tenga conto però che il sistema ricicla i \acr{pid} (come accennato
+in \secref{sec:proc_pid}) per cui l'esistenza di un processo non significa che
 esso sia realmente quello a cui si intendeva mandare il segnale.
 
 Il valore dell'argomento \param{pid} specifica il processo (o i processi) di
 destinazione a cui il segnale deve essere inviato e può assumere i valori
 riportati in \tabref{tab:sig_kill_values}.
 \begin{table}[htb]
 esso sia realmente quello a cui si intendeva mandare il segnale.
 
 Il valore dell'argomento \param{pid} specifica il processo (o i processi) di
 destinazione a cui il segnale deve essere inviato e può assumere i valori
 riportati in \tabref{tab:sig_kill_values}.
 \begin{table}[htb]
+  \footnotesize
   \centering
   \begin{tabular}[c]{|r|l|}
     \hline
   \centering
   \begin{tabular}[c]{|r|l|}
     \hline
@@ -1023,6 +993,12 @@ riportati in \tabref{tab:sig_kill_values}.
 \end{table}
 
 
 \end{table}
 
 
+Si noti pertanto che la funzione \code{raise(sig)} può essere definita in
+termini di \func{kill}, ed è sostanzialmente equivalente ad una
+\code{kill(getpid(), sig)}. Siccome \func{raise}, che è definita nello
+standard ISO C, non esiste in alcune vecchie versioni di Unix, in generale
+l'uso di \func{kill} finisce per essere più portabile.
+
 Solo l'amministratore può inviare un segnale ad un processo qualunque, in
 tutti gli altri casi il \textit{real user id} o l'\textit{effective user id}
 del processo chiamante devono corrispondere al \textit{real user id} o al
 Solo l'amministratore può inviare un segnale ad un processo qualunque, in
 tutti gli altri casi il \textit{real user id} o l'\textit{effective user id}
 del processo chiamante devono corrispondere al \textit{real user id} o al
@@ -1045,9 +1021,10 @@ segnale al processo che ha effettuato la chiamata.
 \label{sec:sig_alarm_abort}
 
 Un caso particolare di segnali generati a richiesta è quello che riguarda i
 \label{sec:sig_alarm_abort}
 
 Un caso particolare di segnali generati a richiesta è quello che riguarda i
-segnali di temporizzazione e \macro{SIGABORT}, per i quali sono previste
-funzioni specifiche che ne effettuino l'invio. La prima di queste è
-\func{alarm} il cui prototipo è:
+vari segnali di temporizzazione e \macro{SIGABORT}, per ciascuno di questi
+segnali sono previste funzioni specifiche che ne effettuino l'invio. La più
+comune delle funzioni usate per la temporizzazione è \func{alarm} il cui
+prototipo è:
 \begin{prototype}{unistd.h}{unsigned int alarm(unsigned int seconds)}
   Predispone l'invio di \macro{SIGALARM} dopo \param{seconds} secondi.
   
 \begin{prototype}{unistd.h}{unsigned int alarm(unsigned int seconds)}
   Predispone l'invio di \macro{SIGALARM} dopo \param{seconds} secondi.
   
@@ -1055,22 +1032,25 @@ funzioni specifiche che ne effettuino l'invio. La prima di queste 
     precedente allarme, o zero se non c'erano allarmi pendenti.}
 \end{prototype}
 
     precedente allarme, o zero se non c'erano allarmi pendenti.}
 \end{prototype}
 
-La funzione provvede un meccanismo che consente ad un processo di predisporre
+La funzione fornisce un meccanismo che consente ad un processo di predisporre
 un'interruzione nel futuro, (ad esempio per effettuare una qualche operazione
 un'interruzione nel futuro, (ad esempio per effettuare una qualche operazione
-dopo un certo periodo di tempo), programmando l'emissione di un segnale (in
-genere \macro{SIGALARM}) dopo il numero di secondi specificato da
+dopo un certo periodo di tempo), programmando l'emissione di un segnale (nel
+caso in questione \macro{SIGALARM}) dopo il numero di secondi specificato da
 \param{seconds}.
 
 Se si specifica per \param{seconds} un valore nullo non verrà inviato nessun
 segnale; siccome alla chiamata viene cancellato ogni precedente allarme,
 \param{seconds}.
 
 Se si specifica per \param{seconds} un valore nullo non verrà inviato nessun
 segnale; siccome alla chiamata viene cancellato ogni precedente allarme,
-questo può essere usato per cancellare una programmazione precedente. La
-funzione inoltre ritorna il numero di secondi rimanenti all'invio dell'allarme
-precedentemente programmato, in modo che sia eventualmente possibile
-effettuare delle scelte in caso di necessità di più interruzioni.
+questo può essere usato per cancellare una programmazione precedente. 
+
+La funzione inoltre ritorna il numero di secondi rimanenti all'invio
+dell'allarme precedentemente programmato, in modo che sia possibile
+controllare se non si cancella un precedente allarme ed eventualmente
+predisporre le opportune misure per gestire il caso di necessità di più
+interruzioni.
 
 In \secref{sec:sys_unix_time} abbiamo visto che ad ogni processo sono
 
 In \secref{sec:sys_unix_time} abbiamo visto che ad ogni processo sono
-associati tre tempi diversi: \textit{clock time}, \textit{user time} e
-\textit{system time}.  Per poterli calcolare il kernel mantiene per ciascun
+associati tre tempi diversi: il \textit{clock time}, l'\textit{user time} ed
+il \textit{system time}.  Per poterli calcolare il kernel mantiene per ciascun
 processo tre diversi timer:
 \begin{itemize}
 \item un \textit{real-time timer} che calcola il tempo reale trascorso (che
 processo tre diversi timer:
 \begin{itemize}
 \item un \textit{real-time timer} che calcola il tempo reale trascorso (che
@@ -1111,6 +1091,7 @@ Il valore di \param{which} permette di specificare quale dei tre timer
 illustrati in precedenza usare; i possibili valori sono riportati in
 \tabref{tab:sig_setitimer_values}.
 \begin{table}[htb]
 illustrati in precedenza usare; i possibili valori sono riportati in
 \tabref{tab:sig_setitimer_values}.
 \begin{table}[htb]
+  \footnotesize
   \centering
   \begin{tabular}[c]{|l|l|}
     \hline
   \centering
   \begin{tabular}[c]{|l|l|}
     \hline
@@ -1130,7 +1111,7 @@ illustrati in precedenza usare; i possibili valori sono riportati in
 Il valore della struttura specificata \param{value} viene usato per settare il
 timer, se il puntatore \param{ovalue} non è nullo il precedente valore viene
 salvato qui. I valori dei timer devono essere indicati attraverso una
 Il valore della struttura specificata \param{value} viene usato per settare il
 timer, se il puntatore \param{ovalue} non è nullo il precedente valore viene
 salvato qui. I valori dei timer devono essere indicati attraverso una
-struttura \var{itimerval}, definita in \ref{fig:file_stat_struct}.
+struttura \var{itimerval}, definita in \figref{fig:file_stat_struct}.
 
 La struttura è composta da due membri, il primo, \var{it\_interval} definisce
 il periodo del timer; il secondo, \var{it\_value} il tempo mancante alla
 
 La struttura è composta da due membri, il primo, \var{it\_interval} definisce
 il periodo del timer; il secondo, \var{it\_value} il tempo mancante alla
@@ -1138,18 +1119,22 @@ scadenza. Entrambi esprimono i tempi tramite una struttura \var{timeval} che
 permette una precisione fino al microsecondo.
 
 Ciascun timer decrementa il valore di \var{it\_value} fino a zero, poi invia
 permette una precisione fino al microsecondo.
 
 Ciascun timer decrementa il valore di \var{it\_value} fino a zero, poi invia
-il segnale e resetta \var{it\_value} al valore di \var{it\_interval},
-ripetendo il ciclo; se \var{it\_interval} è nullo il timer si ferma.
+il segnale e resetta \var{it\_value} al valore di \var{it\_interval}, in
+questo modo il ciclo verrà ripetuto; se invece il valore di \var{it\_interval}
+è nullo il timer si ferma.
 
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
 
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
-struct itimerval {
+    \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
+struct itimerval 
+{
     struct timeval it_interval; /* next value */
     struct timeval it_value;    /* current value */
 };
     struct timeval it_interval; /* next value */
     struct timeval it_value;    /* current value */
 };
-struct timeval {
+
+struct timeval 
+{
     long tv_sec;                /* seconds */
     long tv_usec;               /* microseconds */
 };
     long tv_sec;                /* seconds */
     long tv_usec;               /* microseconds */
 };
@@ -1165,12 +1150,13 @@ L'uso di \func{setitimer} consente dunque un controllo completo di tutte le
 caratteristiche dei timer, ed in effetti la stessa \func{alarm}, benché
 definita direttamente nello standard POSIX.1, può a sua volta essere espressa
 in termini di \func{setitimer}, come evidenziato dal manuale delle \acr{glibc}
 caratteristiche dei timer, ed in effetti la stessa \func{alarm}, benché
 definita direttamente nello standard POSIX.1, può a sua volta essere espressa
 in termini di \func{setitimer}, come evidenziato dal manuale delle \acr{glibc}
-\cite{glibc} che ne riporta la definizione in \figref{fig:sig_alarm_def}.
+\cite{glibc} che ne riporta la definizione mostrata in
+\figref{fig:sig_alarm_def}.
 
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
 
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
+    \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
 unsigned int alarm(unsigned int seconds)
 {
     struct itimerval old, new;
 unsigned int alarm(unsigned int seconds)
 {
     struct itimerval old, new;
@@ -1178,10 +1164,12 @@ unsigned int alarm(unsigned int seconds)
     new.it_interval.tv_sec = 0;
     new.it_value.tv_usec = 0;
     new.it_value.tv_sec = (long int) seconds;
     new.it_interval.tv_sec = 0;
     new.it_value.tv_usec = 0;
     new.it_value.tv_sec = (long int) seconds;
-    if (setitimer(ITIMER_REAL, &new, &old) < 0)
+    if (setitimer(ITIMER_REAL, &new, &old) < 0) {
         return 0;
         return 0;
-    else
+    }
+    else {
         return old.it_value.tv_sec;
         return old.it_value.tv_sec;
+    }
 }
     \end{lstlisting}
   \end{minipage} 
 }
     \end{lstlisting}
   \end{minipage} 
@@ -1191,13 +1179,23 @@ unsigned int alarm(unsigned int seconds)
 \end{figure}
 
 Si deve comunque tenere presente che la precisione di queste funzioni è
 \end{figure}
 
 Si deve comunque tenere presente che la precisione di queste funzioni è
-limitata da quella del timer di sistema (in genere 10~ms). Il sistema assicura
-comunque che il segnale non sarà mai generato prima della scadenza programmata
-(l'arrotondamento cioè è sempre effettuato per eccesso). Una seconda causa di
-potenziali ritardi è che il segnale viene generato alla scadenza del timer,
-ma poi deve essere consegnato; se il processo è attivo (questo è sempre vero
-per \macro{ITIMER\_VIRT}) la consegna è immediata, altrimenti può esserci un
-ulteriore ritardo che può variare a seconda del carico del sistema.
+limitata da quella della frequenza del timer di sistema (che nel caso dei PC
+significa circa 10~ms). Il sistema assicura comunque che il segnale non sarà
+mai generato prima della scadenza programmata (l'arrotondamento cioè è sempre
+effettuato per eccesso).  
+
+Una seconda causa di potenziali ritardi è che il segnale viene generato alla
+scadenza del timer, ma poi deve essere consegnato al processo; se quest'ultimo
+è attivo (questo è sempre vero per \macro{ITIMER\_VIRT}) la consegna è
+immediata, altrimenti può esserci un ulteriore ritardo che può variare a
+seconda del carico del sistema.
+
+Questo ha una conseguenza che può indurre ad errori molto subdoli, si tenga
+conto poi che in caso di sistema molto carico, si può avere il caso patologico
+in cui un timer scade prima che il segnale di una precedente scadenza sia
+stato consegnato; in questo caso, per il comportamento dei segnali descritto
+in \secref{sec:sig_sigchld}, un solo segnale sarà consegnato.
+
 
 Dato che sia \func{alarm} che \func{setitimer} non consentono di leggere il
 valore corrente di un timer senza modificarlo, è possibile usare la funzione
 
 Dato che sia \func{alarm} che \func{setitimer} non consentono di leggere il
 valore corrente di un timer senza modificarlo, è possibile usare la funzione
@@ -1333,22 +1331,6 @@ delle strutture di tipo \var{timespec}, la cui definizione 
 \figref{fig:sig_timespec_def}, che permettono di specificare un tempo con una
 precisione (teorica) fino al nanosecondo. 
 
 \figref{fig:sig_timespec_def}, che permettono di specificare un tempo con una
 precisione (teorica) fino al nanosecondo. 
 
-\begin{figure}[!htb]
-  \footnotesize \centering
-  \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
-struct timespec
-{
-    time_t  tv_sec;         /* seconds */
-    long    tv_nsec;        /* nanoseconds */
-};
-    \end{lstlisting}
-  \end{minipage} 
-  \normalsize 
-  \caption{La struttura \var{timespec} di \func{nanosleep}.} 
-  \label{fig:sig_timespec_def}
-\end{figure}
-
 La funzione risolve anche il problema di proseguire l'attesa dopo
 l'interruzione dovuta ad un segnale; infatti in tal caso in \param{rem} viene
 restituito il tempo rimanente rispetto a quanto richiesto inizialmente, e
 La funzione risolve anche il problema di proseguire l'attesa dopo
 l'interruzione dovuta ad un segnale; infatti in tal caso in \param{rem} viene
 restituito il tempo rimanente rispetto a quanto richiesto inizialmente, e
@@ -1364,6 +1346,21 @@ sia scarico ed il processa venga immediatamente rimesso in esecuzione); per
 questo motivo il valore restituito in \param{rem} è sempre arrotondato al
 multiplo successivo di 1/\macro{HZ}.
 
 questo motivo il valore restituito in \param{rem} è sempre arrotondato al
 multiplo successivo di 1/\macro{HZ}.
 
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
+struct timespec {
+    time_t  tv_sec;         /* seconds */
+    long    tv_nsec;        /* nanoseconds */
+};
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \var{timespec} di \func{nanosleep}.} 
+  \label{fig:sig_timespec_def}
+\end{figure}
+
 In realtà è possibile ottenere anche pause più precise del centesimo di
 secondo usando politiche di scheduling real time come \macro{SCHED\_FIFO} o
 \macro{SCHED\_RR}; in tal caso infatti il meccanismo di scheduling ordinario
 In realtà è possibile ottenere anche pause più precise del centesimo di
 secondo usando politiche di scheduling real time come \macro{SCHED\_FIFO} o
 \macro{SCHED\_RR}; in tal caso infatti il meccanismo di scheduling ordinario
@@ -1617,18 +1614,60 @@ infatti il segnale di allarme interrompe un altro manipolatore, in questo caso
 l'esecuzione non riprenderà nel manipolatore in questione, ma nel ciclo
 principale, interrompendone inopportunamente l'esecuzione.  È per questo
 motivo che occorrono funzioni più sofisticate della semplice \func{signal} che
 l'esecuzione non riprenderà nel manipolatore in questione, ma nel ciclo
 principale, interrompendone inopportunamente l'esecuzione.  È per questo
 motivo che occorrono funzioni più sofisticate della semplice \func{signal} che
-permettano di gestire in maniera più completa
+permettano di gestire i segnali in maniera più completa.
 
 
 
 
 
 
-\subsection{Le funzioni \func{sigprocmask} e \func{sigpending}}
-\label{sec:sig_sigpending}
+\subsection{La funzione \func{sigaction}}
+\label{sec:sig_sigaction}
 
 
+Per i limiti che hanno le funzioni originarie dei primi Unix nella gestione
+dei segnali, evidenziati al paragrafo precedente, lo standard POSIX ha
+introdotto una interfaccia di gestione completamente diversa, che prevede
+tutta una serie di nuove funzioni la principale delle quali è
+\func{sigaction}, che lo standard raccomanda come sostituta di \func{signal}
+(che da essa infatti può essere ottenuta); il suo prototipo è:
 
 
+\begin{prototype}{signal.h}{int sigaction(int signum, const struct sigaction
+    *act, struct sigaction *oldact)} 
+  
+  Installa un nuovo manipolatore per il segnale \param{signum}.
+  
+  \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{EINVAL}] Si è specificato un numero di segnale invalido o si è
+  cercato di installare il manipolatore per \macro{SIGKILL} o \macro{SIGSTOP}.
+\item[\macro{EFAULT}] Si sono specificati indirizzi non validi.
+  \end{errlist}}
+\end{prototype}
+
+La struttura \var{sigaction} è anch'essa definita dallo standard POSIX, che
+prevede abbia la forma: 
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
+struct sigaction {
+    void (*sa_handler)(int);
+    void (*sa_sigaction)(int, siginfo_t *, void *);
+    sigset_t sa_mask;
+    int sa_flags;
+    void (*sa_restorer)(void);
+}
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \var{sigaction}.} 
+  \label{fig:sig_sigaction}
+\end{figure}
+
+
+
+\subsection{Le funzioni \func{sigprocmask} e \func{sigpending}}
+\label{sec:sig_sigpending}
 
 
 
 
-\subsection{La funzione \func{sigaction}}
-\label{sec:sig_sigaction}