Finito con alarm e abort.
authorSimone Piccardi <piccardi@gnulinux.it>
Mon, 4 Mar 2002 23:36:36 +0000 (23:36 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Mon, 4 Mar 2002 23:36:36 +0000 (23:36 +0000)
signal.tex

index 90885ffd70e750208ae212cd8dbedd9bc5a3a2b1..3bc1af18268fc02f28356d0a52e9988d0fd3d5f5 100644 (file)
@@ -823,7 +823,7 @@ indenfinitamente, che per questo vengono chiamate \textsl{lente}. Un elenco
 dei casi in cui si presenta questa situazione è il seguente:
 \begin{itemize*}
 \item lettura da file che possono bloccarsi in attesa di dati non ancora
 dei casi in cui si presenta questa situazione è il seguente:
 \begin{itemize*}
 \item lettura da file che possono bloccarsi in attesa di dati non ancora
-  presenti (come per certi dispositivi, la rete o le pipe).
+  presenti (come per certi file di dispositivo, la rete o le pipe).
 \item scrittura sugli stessi file, nel caso in cui dati non possano essere
   accettati immediatamente.
 \item apertura di un file di dipositivo che richiede operazioni non immediate
 \item scrittura sugli stessi file, nel caso in cui dati non possano essere
   accettati immediatamente.
 \item apertura di un file di dipositivo che richiede operazioni non immediate
@@ -1047,8 +1047,6 @@ La funzione provvede 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 si un segnale di
 \macro{SIGALARM} dopo il numero di secondi specificato da \param{seconds}.
 un'interruzione nel futuro, (ad esempio per effettuare una qualche operazione
 dopo un certo periodo di tempo), programmando l'emissione si un segnale di
 \macro{SIGALARM} dopo il numero di secondi specificato da \param{seconds}.
-Chiaramente la precisione è determinata da quella dell'orologio di sistema, e
-sono sempre possibili ritardi in caso di un sistema eccessivamente carico.
 
 Se si specifica per \param{seconds} un valore nullo non verrà inviato nessun
 segnale; siccome alla chiamata viene cancellato ogni precedente allarme,
 
 Se si specifica per \param{seconds} un valore nullo non verrà inviato nessun
 segnale; siccome alla chiamata viene cancellato ogni precedente allarme,
@@ -1076,10 +1074,14 @@ timer per ciascun processo:
 \end{itemize}
 
 Il timer usato da \func{alarm} è il \textit{clock time}, e corrisponde cioè al
 \end{itemize}
 
 Il timer usato da \func{alarm} è il \textit{clock time}, e corrisponde cioè al
-tempo reale.  Dato che \func{alarm} non consente di usare gli altri timer, e
-non può specificare intervalli con precisione maggiore al secondo le
-\acr{glibc} provvedono la funzione \func{setitimer} che permette un controllo
-completo, a scapito di un uso molto più complesso. Il suo prototipo è:
+tempo reale. La funzione, pur essendo molto semplice, presenta numerosi
+limiti: non consente di usare gli altri timer, non può specificare intervalli
+con precisione maggiore del secondo e genera il segnale una sola volta.
+
+Per ovviare a questi limiti Linux deriva da BSD la funzione \func{setitimer}
+che permette di usare un timer qualunque e l'invio di segnali periodici, al
+costo però di una maggiore complessità d'uso e di una minore portabilità. Il
+suo prototipo è:
 \begin{prototype}{sys/time.h}{int setitimer(int which, const struct
     itimerval *value, struct itimerval *ovalue)} 
   
 \begin{prototype}{sys/time.h}{int setitimer(int which, const struct
     itimerval *value, struct itimerval *ovalue)} 
   
@@ -1091,9 +1093,9 @@ completo, a scapito di un uso molto pi
     \macro{EFAULT}.}
 \end{prototype}
 
     \macro{EFAULT}.}
 \end{prototype}
 
-Il valore di \param{which} permette di specificare quale dei tre timer usare;
-i possibili valori sono riportati in \tabref{tab:sig_setitimer_values}.
-
+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]
   \centering
   \begin{tabular}[c]{|l|l|}
 \begin{table}[htb]
   \centering
   \begin{tabular}[c]{|l|l|}
@@ -1111,10 +1113,132 @@ i possibili valori sono riportati in \tabref{tab:sig_setitimer_values}.
   \label{tab:sig_setitimer_values}
 \end{table}
 
   \label{tab:sig_setitimer_values}
 \end{table}
 
+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}.
+
+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
+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.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
+struct itimerval {
+    struct timeval it_interval; /* next value */
+    struct timeval it_value;    /* current value */
+};
+struct timeval {
+    long tv_sec;                /* seconds */
+    long tv_usec;               /* microseconds */
+};
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \var{itimerval}, che definisce i valori dei timer di
+    sistema.} 
+  \label{fig:sig_itimerval}
+\end{figure}
+
+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}.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
+unsigned int alarm(unsigned int seconds)
+{
+    struct itimerval old, new;
+    new.it_interval.tv_usec = 0;
+    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)
+        return 0;
+    else
+        return old.it_value.tv_sec;
+}
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{Definizione di \func{alarm} in termini di \func{setitimer}.} 
+  \label{fig:sig_alarm_def}
+\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 scandenza 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.
+
+Dato che sia \func{alarm} che \func{setitimer} non consentono di leggere il
+valore corrente di un timer senza modificarlo, è possibile usare la funzione
+\func{getitimer}, il cui prototipo è:
+\begin{prototype}{sys/time.h}{int getitimer(int which, struct
+    itimerval *value)}
+  
+  Legge in \param{value} il valore del timer specificato da \func{which}.
+  
+  \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+    errore e restituisce gli stessi errori di \func{getitimer}}
+\end{prototype}
+\noindent i cui parametri hanno lo stesso significato e formato di quelli di
+\func{setitimer}. 
+
+
+L'ultima funzione che permette l'invio diretto di un segnale è \func{abort};
+che, come accennato in \ref{sec:proc_termination}, permette di abortire
+l'esecuzione di un programma tramite l'invio di \macro{SIGABRT}. Il suo
+prototipo è:
+\begin{prototype}{stdlib.h}{void abort(void)}
+  
+  Abortisce il processo corrente.
+  
+  \bodydesc{La funzione non ritorna, il processo è terminato inviando il
+  segnale di \macro{SIGABRT}.}
+\end{prototype}
+
+La differenza fra questa funzione e l'uso di \func{raise} è che anche se il
+segnale è bloccato o ignorato, la funzione ha effetto lo stesso. Il segnale
+può però essere intercettato per effettuare eventuali operazioni di chiusura
+prima della terminazione del processo.
+
+Lo standard ANSI C richiede inoltre che anche se il manipolatore ritorna, la
+funzione non ritorni comunque. Lo standard POSIX.1 va oltre e richiede che se
+il processo non viene terminato direttamente dal manipolatore sia la stessa
+\func{abort} a farlo al ritorno dello stesso. Inoltre, sempre seguendo lo
+standard POSIX, prima della terminazione tutti i file aperti e gli stream
+saranno chiusi ed i buffer scaricati su disco. Non verranno invece eseguite le
+funzioni registrate con \func{at\_exit} e \func{on\_exit}.
+
 
 \subsection{Le funzioni \func{pause} e \func{sleep}}
 \label{sec:sig_pause_sleep}
 
 
 \subsection{Le funzioni \func{pause} e \func{sleep}}
 \label{sec:sig_pause_sleep}
 
+Il metodo tradizionale per fare attendere ad un processo fino all'arrivo di un
+segnale è quello di usare la funzione \func{pause}, il cui prototipo è:
+\begin{prototype}{unistd.h}{int pause(void)}
+  
+  Pone il processo in stato di sleep fino al ritorno di un manipolatore.
+  
+  \bodydesc{La funzione ritorna solo dopo che un segnale è stato ricevuto ed
+  il relativo manipilatore è ritornato, nel qual caso restituisce -1 e setta
+  \var{errno} a \macro{EINTR}.}
+\end{prototype}