Si va avanti molto piano
[gapil.git] / signal.tex
index 940b921157b4a58fa89d7b1a09fc2931fc30dccf..58454408615332f9a7bc5d78e41a8c6de8f8e3f1 100644 (file)
@@ -883,11 +883,11 @@ con il precedente prototipo si pu
 \begin{verbatim}
     typedef void (* sighandler_t)(int) 
 \end{verbatim}
 \begin{verbatim}
     typedef void (* sighandler_t)(int) 
 \end{verbatim}
-e cioè un puntatore ad una funzione \type{void} (cioè senza valore di ritorno)
-e che prende un argomento di tipo \type{int}.\footnote{si devono usare le
+e cioè un puntatore ad una funzione \ctyp{void} (cioè senza valore di ritorno)
+e che prende un argomento di tipo \ctyp{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
   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}.}
+  un puntatore a \ctyp{void} e non un puntatore ad una funzione \ctyp{void}.}
 La funzione \func{signal} quindi restituisce e prende come secondo argomento
 un puntatore a una funzione di questo tipo, che è appunto il manipolatore del
 segnale.
 La funzione \func{signal} quindi restituisce e prende come secondo argomento
 un puntatore a una funzione di questo tipo, che è appunto il manipolatore del
 segnale.
@@ -957,6 +957,15 @@ la funzione \func{kill}; il cui prototipo 
   \headdecl{signal.h}
   \funcdecl{int kill(pid\_t pid, int sig)} Invia il segnale \param{sig} al
   processo specificato con \param{pid}.
   \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 0 in caso di successo e -1 in caso di
+    errore nel qual caso \var{errno} può assumere i valori:
+    \begin{errlist}
+    \item[\macro{EINVAL}] Il segnale specificato non esiste.
+    \item[\macro{ESRCH}] Il processo selezionato non esiste.
+    \item[\macro{EPERM}] Non si hanno privilegi sufficienti ad inviare il
+      segnale.
+    \end{errlist}}
 \end{functions}
 
 Lo standard POSIX prevede che il valore 0 per \param{sig} sia usato per
 \end{functions}
 
 Lo standard POSIX prevede che il valore 0 per \param{sig} sia usato per
@@ -992,7 +1001,6 @@ riportati in \tabref{tab:sig_kill_values}.
   \label{tab:sig_kill_values}
 \end{table}
 
   \label{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
 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
@@ -1532,7 +1540,8 @@ unsigned int sleep(unsigned int seconds)
     /* remove alarm, return remaining time */
     return alarm(0);
 }
     /* remove alarm, return remaining time */
     return alarm(0);
 }
-void alarm_hand(int sig) {
+void alarm_hand(int sig) 
+{
     /* check if the signal is the right one */
     if (sig != SIGALRM) { /* if not exit with error */
         printf("Something wrong, handler for SIGALRM\n");
     /* check if the signal is the right one */
     if (sig != SIGALRM) { /* if not exit with error */
         printf("Something wrong, handler for SIGALRM\n");
@@ -1585,7 +1594,8 @@ unsigned int sleep(unsigned int seconds)
     /* remove alarm, return remaining time */
     return alarm(0);
 }
     /* remove alarm, return remaining time */
     return alarm(0);
 }
-void alarm_hand(int sig) {
+void alarm_hand(int sig) 
+{
     /* check if the signal is the right one */
     if (sig != SIGALRM) { /* if not exit with error */
         printf("Something wrong, handler for SIGALRM\n");
     /* check if the signal is the right one */
     if (sig != SIGALRM) { /* if not exit with error */
         printf("Something wrong, handler for SIGALRM\n");
@@ -1617,16 +1627,80 @@ motivo che occorrono funzioni pi
 permettano di gestire i segnali in maniera più completa.
 
 
 permettano di gestire i segnali in maniera più completa.
 
 
+\subsection{I \textit{signal set}}
+\label{sec:sig_sigset}
+
+Come evidenziato nel paragrafo precedente, le funzioni di gestione dei segnali
+dei primi Unix, nate con la semantica inaffidabile, hanno dei limiti non
+superabili; in particolare non è prevista nessuna funzione che permetta di
+gestire gestire il blocco dei segnali o di verificare lo stato dei segnali
+pendenti.
+
+Per questo motivo lo standard POSIX, insieme alla nuova semantica dei segnali
+ha introdotto una interfaccia di gestione completamente nuova, che permette di
+ottenete un controllo molto più dettagliato. In particolare lo standard ha
+introdotto un nuovo tipo di dato \type{sigset\_t}, che permette di
+rappresentare un insieme di segnali (un \textit{signal set}, come viene
+usualmente chiamato), che è il tipo di dato che viene usato per gestire il
+blocco dei segnali.
+
+In genere un \textit{signal set} è rappresentato da un intero di dimensione
+opportuna, di solito si pari al numero di bit dell'architettura della
+macchina\footnote{nel caso dei PC questo comporta un massimo di 32 segnali
+  distinti, dato che in Linux questi sono sufficienti non c'è necessità di
+  nessuna struttura più complicata.}, ciascun bit del quale è associato ad uno
+specifico segnale; in questo modo è di solito possibile implementare le
+operazioni direttamente con istruzioni elementari del processore; lo standard
+POSIX definisce cinque funzioni per la manipolazione dei \textit{signal set},
+\func{sigemptyset}, \func{sigfillset}, \func{sigaddset}, \func{sigdelset} e
+\func{sigismember}, i cui prototipi sono:
+\begin{functions}
+  \headdecl{signal.h} 
+
+  \funcdecl{int sigemptyset(sigset\_t *set)} Inizializza un \textit{signal set}
+  vuoto.
+  \funcdecl{int sigfillset(sigset\_t *set)} Inizializza un \textit{signal set}
+  pieno (con tutti i segnali).
+  
+  \funcdecl{int sigaddset(sigset\_t *set, int signum)} Aggiunge il segnale
+  \param{signum} al  \textit{signal set} \param{set}.
+
+  \funcdecl{int sigdelset(sigset\_t *set, int signum)} Toglie il segnale
+  \param{signum} dal \textit{signal set} \param{set}.
+  
+  \funcdecl{int sigismember(const sigset\_t *set, int signum)} Controlla se il
+  segnale \param{signum} è nel \textit{signal set} \param{set}
+  
+  \bodydesc{Le prime quattro funzioni ritornano 0 in caso di successo, mentre
+    \func{sigismember} ritorna 1 se \param{signum} è in \param{set} e 0
+    altrimenti. In caso di errore tutte ritornano -1, con \var{errno} settata a
+    \macro{EINVAL} (il solo errore possibile è che \param{signum} non sia un
+    segnale valido).}
+\end{functions}
+
+Dato che in generale non si può fare conto sulle caratteristiche di una
+implementazione (non è detto che si disponga di un numero di bit sufficienti
+per mettere tutti i segnali in un intero, o in \type{sigset\_t} possono essere
+immagazzinate ulteriori informazioni) tutte le operazioni devono essere
+comunque eseguite attraverso queste funzioni.
+
+In genere si usa un \textit{signal set} per specificare quali segnali si vuole
+bloccare, o per riottenere dalle varie funzioni di gestione la maschera dei
+segnali attivi. Essi possono essere definiti in due diverse maniere,
+aggiungendo i segnali voluti ad un insieme vuoto ottenuto con
+\func{sigemptyset} o togliendo quelli che non servono da un insieme completo
+ottenuto con \func{sigfillset}. Infine \func{sigismember} permette di vericare
+la presenza di uno specifico segnale in un \textit{signal set}.
+
 
 \subsection{La funzione \func{sigaction}}
 \label{sec:sig_sigaction}
 
 
 \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 è:
+La funzione principale dell'interfaccia standard POSIX per i segnali è
+\func{sigaction}, essa ha sostanzialemente le stesse funzioni di
+\func{signal}, permette cioè di specificare come un segnale può essere gestito
+da un processo. Il suo prototipo è:
 
 \begin{prototype}{signal.h}{int sigaction(int signum, const struct sigaction
     *act, struct sigaction *oldact)} 
 
 \begin{prototype}{signal.h}{int sigaction(int signum, const struct sigaction
     *act, struct sigaction *oldact)} 
@@ -1637,13 +1711,34 @@ tutta una serie di nuove funzioni la principale delle quali 
     errore, nel qual caso \var{errno} assumerà i valori:
   \begin{errlist}
   \item[\macro{EINVAL}] Si è specificato un numero di segnale invalido o si è
     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.
+    cercato di installare il manipolatore per \macro{SIGKILL} o
+    \macro{SIGSTOP}.
+  \item[\macro{EFAULT}] Si sono specificati indirizzi non validi.
   \end{errlist}}
 \end{prototype}
 
   \end{errlist}}
 \end{prototype}
 
-La struttura \var{sigaction} è anch'essa definita dallo standard POSIX, che
-prevede abbia la forma: 
+La funzione serve ad installare una nuova azione per il segnale
+\param{signum}; si parla di azione e non di manipolatore come nel caso di
+\func{signal}, in quanto la funzione consente di specificare le varie
+caratteristiche della risposta al segnale, non solo la funzione del
+manipolatore.  Lo standard POSIX raccomanda di usare sempre questa funzione al
+posto di \func{signal} (che in genere viene definita tramite essa), in quanto
+offre un controllo completo su tutti gli aspetti della gestione di un segnale,
+sia pure al prezzo di una maggiore complessità d'uso.
+
+Se il puntatore \param{act} non è nullo, la funzione installa la nuova azione
+da esso specificata, se \param{oldact} non è nullo il valore dell'azione
+corrente viene restituito indietro.  Questo permette (specificando \param{act}
+nullo e \param{oldact} non nullo) di superare uno dei limiti di \func{signal},
+che non consente di ottenere l'azione corrente senza installarne una nuova.
+
+Entrambi i puntatori fanno riferimento alla struttura \var{sigaction}, tramite
+la quale si specificano tutte le caratteristiche dell'azione associata ad un
+segnale.  Anch'essa è descritta dallo standard POSIX ed in Linux è definita
+secondo quanto riportato in \figref{fig:sig_sigaction}. Il campo
+\var{sa\_restorer}, non previsto dallo standard, è obsoleto e non deve essere
+più usato.
+
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
@@ -1662,9 +1757,29 @@ struct sigaction {
   \label{fig:sig_sigaction}
 \end{figure}
 
   \label{fig:sig_sigaction}
 \end{figure}
 
+Come 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}).
+
+
+
+
+
+\subsection{La gestione del blocco dei segnali}
+\label{sec:sig_sigmask}
+
+Una delle informazioni che ciascun processo porta con se è l'insieme
+(anch'esso un signal set) dei segnali bloccati (la cosiddetta \textit{signal
+  mask}, mantenuta nel campo \var{blocked} di \var{task\_struct}); abbiamo
+accennato in \secref{sec:proc_fork} che essa viene ereditata da un processo 
 
 
 
 
-\subsection{Le funzioni \func{sigprocmask} e \func{sigpending}}
+\subsection{Le funzioni \func{sigpending} e \func{sigsuspend}}
 \label{sec:sig_sigpending}
 
 
 \label{sec:sig_sigpending}
 
 
@@ -1675,8 +1790,6 @@ struct sigaction {
 \label{sec:sig_reentrant}
 
 
 \label{sec:sig_reentrant}
 
 
-, affrontando inoltre le varie problematiche di programmazione che si devono
-tenere presenti quando si ha a che fare con essi.