Correzioni e aggiunte
authorSimone Piccardi <piccardi@gnulinux.it>
Sun, 31 Mar 2002 23:25:45 +0000 (23:25 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Sun, 31 Mar 2002 23:25:45 +0000 (23:25 +0000)
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: 
-
-\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).
@@ -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.
 
-
 \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
-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}.
-
-  \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}
 
-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]
+  \footnotesize
   \centering
   \begin{tabular}[c]{|r|l|}
     \hline
@@ -1023,6 +993,12 @@ riportati in \tabref{tab:sig_kill_values}.
 \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
@@ -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
-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.
   
@@ -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}
 
-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
-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,
-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
-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
@@ -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]
+  \footnotesize
   \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
-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
@@ -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
-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{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 {
+
+struct timeval 
+{
     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}
-\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{lstlisting}[labelstep=0,frame=,indent=1cm]{}
+    \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
 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;
-    if (setitimer(ITIMER_REAL, &new, &old) < 0)
+    if (setitimer(ITIMER_REAL, &new, &old) < 0) {
         return 0;
-    else
+    }
+    else {
         return old.it_value.tv_sec;
+    }
 }
     \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 è
-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
@@ -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. 
 
-\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
@@ -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}.
 
+\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
@@ -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
-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}