Finito, spero, con i tempi
[gapil.git] / system.tex
index b617a0c7a15a76af716c1cdbfb0338ac89611afe..18cee493a4d73befeffd46495823ddb867ee9cd8 100644 (file)
@@ -1,4 +1,4 @@
-fo \chapter{La gestione del sistema, delle risorse, e degli errori}
+\chapter{La gestione del sistema, delle risorse, e degli errori}
 \label{cha:system}
 
 In questo capitolo tratteremo varie interfacce che attengono agli aspetti più
@@ -1804,8 +1804,9 @@ ricevuto lo stato di terminazione, e lo stesso vale per \var{tms\_cstime}.
 
 Si tenga conto che l'aggiornamento di \var{tms\_cutime} e \var{tms\_cstime}
 viene eseguito solo quando una chiamata a \func{wait} o \func{waitpid} è
-ritornata. Per questo motivo se un figlio termina prima di altri suoi figli,
-questi ``nipoti'' non potranno essere considerati nel calcolo di questi tempi.
+ritornata. Per questo motivo se un processo figlio termina prima di ricevere
+lo stato di teminazione di tutti i suoi figli, questi processi ``nipoti'' non
+verranno considerati nel calcolo di questi tempi.
 
 
 
@@ -1816,7 +1817,7 @@ Come anticipato in \secref{sec:sys_unix_time} il \textit{calendar time} 
 mantenuto dal kernel in una variabile di tipo \type{time\_t}, che usualmente
 corrisponde ad un tipo nativo (in Linux è un intero a 32 bit).  Il valore
 corrente del \textit{calendar time}, che indicheremo come \textsl{tempo di
-  sistema} può essere ottenuto con la funzione \func{time} che lo restituisce
+  sistema}, può essere ottenuto con la funzione \func{time} che lo restituisce
 in nel suddetto formato; il suo prototipo è:
 \begin{prototype}{time.h}{time\_t time(time\_t *t)}
   Legge il valore corrente del \textit{calendar time}.
@@ -1824,8 +1825,8 @@ in nel suddetto formato; il suo prototipo 
   \bodydesc{La funzione ritorna il valore del \textit{calendar time} in caso
     di successo e -1 in caso di errore, che può essere solo \macro{EFAULT}.}
 \end{prototype}
-\noindent dove \param{t}, se non nullo, è l'indirizzo su cui salvare il valore
-di ritorno.
+\noindent dove \param{t}, se non nullo, deve essere  l'indirizzo di una
+variabile su cui duplicare il valore di ritorno.
 
 Analoga a \func{time} è la funzione \func{stime} che serve per effettuare
 l'operazione inversa, e cioè per settare il tempo di sistema qualora questo
@@ -1844,7 +1845,11 @@ altrimenti la chiamata fallir
 Data la scarsa precisione nell'uso di \type{time\_t} (che ha una risoluzione
 massima di un secondo) quando si devono effettuare operazioni sui tempi di
 norma l'uso delle funzioni precedenti è sconsigliato, ed esse sono di solito
-sostituite da \func{gettimeofday} e \func{settimeofday}, i cui prototipi sono:
+sostituite da \func{gettimeofday} e \func{settimeofday},\footnote{le due
+  funzioni \func{time} e \func{stime} sono più antiche e derivano da SVr4,
+  \func{gettimeofday} e \func{settimeofday} sono state introdotte da BSD, ed
+  in BSD4.3 sono indicate come sostitute delle precedenti.}  mentre i cui
+prototipi sono:
 \begin{functions}
   \headdecl{sys/time.h}
   \headdecl{time.h}
@@ -1864,18 +1869,17 @@ sostituite da \func{gettimeofday} e \func{settimeofday}, i cui prototipi sono:
     \macro{EPERM}.}
 \end{functions}
 
-Queste funzioni utilizzano una struttura di tipo \var{timeval} che consente di
-indicare intervalli o tempi con precisioni maggiori del secondo, in realtà le
-\acr{glibc} provvedono due rappresentazioni alternative del \textit{calendar
-  time}, le strutture \var{timeval} e \var{timespec}, le cui definizioni sono
-riportate in \figref{fig:sys_timeval_struct} e che consentono rispettivamente
-precisioni del microsecondo e del nanosecondo.\footnote{la precisione è solo
-  astratta, l'orologio di sistema normalmente non è in grado di misuare dei
-  tempi con precisioni simili.}
+Queste funzioni utilizzano una struttura di tipo \var{timeval}, la cui
+definizione, insieme a quella della analoga \var{timespec}, è riportata in
+\figref{fig:sys_timeval_struct}. Le \acr{glibc} infatti provvedono queste due
+rappresentazioni alternative del \textit{calendar time} che rispetto a
+\type{time\_t} consentono rispettivamente precisioni del microsecondo e del
+nanosecondo.\footnote{la precisione è solo teorica, la precisione reale della
+  misura del tempo dell'orologio di sistema non dipende dall'uso di queste
+  strutture.}
 
 \begin{figure}[!htb]
-  \footnotesize
-  \centering
+  \footnotesize \centering
   \begin{minipage}[c]{15cm}
     \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
 struct timeval 
@@ -1891,21 +1895,24 @@ struct timespec {
   \end{minipage} 
   \normalsize 
   \caption{Le strutture \var{timeval} e \var{timespec} usate per una
-    rappresetnazione ad alta risoluzione del \textit{calendar time}.}
+    rappresentazione ad alta risoluzione del \textit{calendar time}.}
   \label{fig:sys_timeval_struct}
 \end{figure}
 
-Come nel caso di \func{stime} anche \func{settimeofday} può essere utilizzata
-solo da un processo coi privilegi di amministratore.  Il secondo parametro di
-entrambe le funzioni è una struttura \var{timezone}, che storicamente veniva
-utilizzata per specificare appunto la \textit{timezone}, cioè l'insieme del
-fuso orario e delle convenzioni per l'ora legale. Questo parametro è obsoleto
-e in Linux non è mai stato utilizzato e non è supportato né dalle vecchie
-\textsl{libc5}, né dalle \textsl{glibc}, e deve essere settato a \macro{NULL}.
+Come nel caso di \func{stime} anche \func{settimeofday} (e qualunque funzione
+vada a modificare l'orologio di sistema, come quelle che tratteremo in
+seguito) può essere utilizzata solo da un processo coi privilegi di
+amministratore.  Il secondo parametro di entrambe le funzioni è una struttura
+\var{timezone}, che storicamente veniva utilizzata per specificare appunto la
+\textit{timezone}, cioè l'insieme del fuso orario e delle convenzioni per
+l'ora legale che permettevano il passaggio dal tempo universale all'ora
+locale. Questo parametro è obsoleto e in Linux non è mai stato utilizzato e
+non è supportato né dalle vecchie \textsl{libc5}, né dalle \textsl{glibc}:
+pertanto deve essere sempre settato a \macro{NULL}.
 
 Modificare l'orologio di sistema con queste funzioni è comunque problematico,
-in quanto esse effettuano un cambiamento immediato, così ad esempio se si
-porta avanti l'orologio si possono perdere delle esecuzioni di \cmd{cron}
+in quanto esse effettuano un cambiamento immediato. Ad esempio se si porta
+avanti l'orologio si possono perdere delle esecuzioni di \cmd{cron}
 programmate nell'intervallo che si è saltato. Per questo motivo la modalità
 più corretta per settare l'ora è quella di usare la funzione \func{adjtime},
 il cui prototipo è:
@@ -1923,24 +1930,299 @@ sistema in modo che esso sia sempre monotonicamente crescente. Il valore di
 \param{delta} esprime il valore di cui si vuole spostare l'orologio; se è
 positivo l'orologio sarà accelerato per un certo tempo in modo da guadagnare
 il tempo richiesto, altrimenti sarà rallentato. Il secondo parametro viene
-usato, se non nullo, per ricavare il valore del precedente aggiustamento.
+usato, se non nullo, per ricevere il valore dell'ultimo aggiustamento
+effettuto.
 
 Linux poi prevede un'altra funzione, \func{adjtimex}, che consente un
-aggiustamento più dettagliato permettendo anche di modificare anche la
-velocità dell'orologio di sistema. Il suo prototipo è:
-\begin{prototype}{sys/time.h}
+aggiustamento molto più dettagliato, permettendo ad esempio anche di
+modificare anche la velocità dell'orologio di sistema.  Il suo prototipo è:
+\begin{prototype}{sys/timex.h}
 {int adjtimex(struct timex *buf)} 
   
   Aggiusta del valore \param{delta} l'orologio di sistema.
   
-  \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
-  errore, nel qual caso \var{errno} assumerà il valore \macro{EPERM}.}
+  \bodydesc{La funzione restituisce lo stato dell'orologio (un valore $>0$) in
+    caso di successo e -1 in caso di errore, nel qual caso \var{errno}
+    assumerà i valori \macro{EFAULT}, \macro{EINVAL} ed \macro{EPERM}.}
 \end{prototype}
 
+La funzione richiede una struttura di tipo \var{timex}, la cui definizione,
+così come effettuata in \file{sys/timex.h}, è riportata in
+\figref{fig:sys_timex_struct}. L'azione della funzione dipende dal valore del
+campo \var{mode}, che specifica quale parametro dell'orologio di sistema,
+specificato in un opportuno campo di \var{timex}, deve essere settato. Un
+valore nullo serve per leggere i parametri correnti; i valori diversi da zero
+devono essere specificati come OR binario delle costanti riportate in
+\secref{tab:sys_timex_mode}.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
+struct timex {
+    unsigned int modes;   /* mode selector */
+    long int offset;      /* time offset (usec) */
+    long int freq;        /* frequency offset (scaled ppm) */
+    long int maxerror;    /* maximum error (usec) */
+    long int esterror;    /* estimated error (usec) */
+    int status;           /* clock command/status */
+    long int constant;    /* pll time constant */
+    long int precision;   /* clock precision (usec) (read only) */
+    long int tolerance;   /* clock frequency tolerance (ppm) (read only) */
+    struct timeval time;  /* (read only) */
+    long int tick;        /* (modified) usecs between clock ticks */
+    long int ppsfreq;     /* pps frequency (scaled ppm) (ro) */
+    long int jitter;      /* pps jitter (us) (ro) */
+    int shift;            /* interval duration (s) (shift) (ro) */
+    long int stabil;      /* pps stability (scaled ppm) (ro) */
+    long int jitcnt;      /* jitter limit exceeded (ro) */
+    long int calcnt;      /* calibration intervals (ro) */
+    long int errcnt;      /* calibration errors (ro) */
+    long int stbcnt;      /* stability limit exceeded (ro) */
+};
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \var{timex} per il controllo dell'orologio di sistema.}
+  \label{fig:sys_timex_struct}
+\end{figure}
+
+La funzione utilizza il meccanismo di David L. Mills, descritto nell'RFC~1305,
+che è alla base del protocollo NTP; la funzione è specifica di Linux e non
+deve essere usata se la portabilità è un requisito, le \acr{glibc} provvedono
+anche un suo omonimo \func{ntp\_adjtime}.  La trattazione completa di questa
+funzione necessita di una lettura approfondita del meccanismo descritto
+nell'RFC~1305, ci limitiamo a descrivere in \tabref{tab:sys_timex_mode} i
+principali valori utilizzabili per il campo \var{mode}, un elenco più
+dettagliato del significato dei vari campi della struttura \var{timex} può
+essere ritrovato in \cite{glibc}.
+
+\begin{table}[htb]
+  \footnotesize
+  \centering
+  \begin{tabular}[c]{|l|c| p{10cm}|}
+    \hline
+    \textbf{Nome} & \textbf{Valore} & \textbf{Significato}\\
+    \hline
+    \hline
+    \macro{ADJ\_OFFSET}         & 0x0001 & Setta la differenza fra il tempo
+                                           reale e l'orologio di sistema, che 
+                                           deve essere indicata in microsecondi
+                                           nel campo \var{offset} di
+                                           \var{timex}.\\ 
+    \macro{ADJ\_FREQUENCY}      & 0x0002 & Setta la differenze in frequenza
+                                           fra il tempo reale e l'orologio di
+                                           sistema, che deve essere indicata
+                                           in parti per milione nel campo
+                                           \var{frequency} di \var{timex}.\\
+    \macro{ADJ\_MAXERROR}       & 0x0004 & Setta il valore massimo dell'errore
+                                           sul tempo, espresso in microsecondi 
+                                           nel campo \var{maxerror} di
+                                           \var{timex}.\\ 
+    \macro{ADJ\_ESTERROR}       & 0x0008 & Setta la stima dell'errore
+                                           sul tempo, espresso in microsecondi 
+                                           nel campo \var{esterror} di
+                                           \var{timex}.\\
+    \macro{ADJ\_STATUS}         & 0x0010 & Setta alcuni
+                                           valori di stato interni usati dal
+                                           sistema nella gestione
+                                           dell'orologio specificati nel campo
+                                           \var{status} di \var{timex}.\\ 
+    \macro{ADJ\_TIMECONST}      & 0x0020 & Setta la larghezza di banda del PLL
+                                           implementato dal kernel,
+                                           specificato nel campo
+                                           \var{constant} di \var{timex}.\\ 
+    \macro{ADJ\_TICK}           & 0x4000 & Setta il valore dei tick del timer
+                                           in microsecondi, espresso nel campo
+                                           \var{tick} di \var{timex}.\\ 
+    \macro{ADJ\_OFFSET\_SINGLESHOT}&0x8001&Setta uno spostamento una tantum 
+                                           dell'orologio secondo il valore del
+                                           campo \var{offset} simulando il
+                                           comportamento di \func{adjtime}.\\ 
+    \hline
+  \end{tabular}
+  \caption{Costanti per l'assegnazione del valore del campo \var{mode} della
+    struttura \var{timex}.} 
+  \label{tab:sys_timex_mode}
+\end{table}
+
+Il valore delle costanti per \var{mode} può essere anche espresso, secondo la
+sintassi specificata per la forma equivalente di questa funzione definita come
+\func{ntp\_adjtime}, utilizzando il prefisso \macro{MOD} al posto di
+\macro{ADJ}.
+
+\begin{table}[htb]
+  \footnotesize
+  \centering
+  \begin{tabular}[c]{|l|c| p{10cm}|}
+    \hline
+    \textbf{Nome} & \textbf{Valore} & \textbf{Significato}\\
+    \hline
+    \hline
+    \macro{TIME\_OK}   & 0 & L'orologio è sincronizzato.\\ 
+    \macro{TIME\_INS}  & 1 & insert leap second.\\ 
+    \macro{TIME\_DEL}  & 2 & delete leap second.\\ 
+    \macro{TIME\_OOP}  & 3 & leap second in progress.\\ 
+    \macro{TIME\_WAIT} & 4 & leap second has occurred.\\ 
+    \macro{TIME\_BAD}  & 5 & L'orologio non è sincronizzato.\\ 
+    \hline
+  \end{tabular}
+  \caption{Possibili valori di ritorno di \func{adjtimex}.} 
+  \label{tab:sys_adjtimex_return}
+\end{table}
+
+La funzione ritorna un valore positivo che esprime lo stato dell'orologio di
+sistema; questo può assumere i valori riportati in
+\tabref{tab:sys_adjtimex_return}.  Un valore di -1 viene usato per riportare
+un errore; al solito se si cercherà di modificare l'orologio di sistema
+(specificando un \var{mode} diverso da zero) senza avere i privilegi di
+amministratore si otterrà un errore di \macro{EPERM}.
+
 
 \subsection{La gestione delle date.}
 \label{sec:sys_date}
 
+Le funzioni viste al paragrafo precedente sono molto utili per trattare le
+operazioni elementari sui tempi, però le rappresentazioni del tempo ivi
+illustrate, se han senso per specificare un intervallo, non sono molto
+intuitive quando si deve esprimere un'ora o una data.  Per questo motivo è
+stata introdotta una ulteriore rappresentazione, detta \textit{broken-down
+  time}, che permette appunto di \textsl{suddividere} il \textit{calendar
+  time} usuale in ore, minuti, secondi, ecc.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
+struct tm {
+        int     tm_sec;         /* seconds */
+        int     tm_min;         /* minutes */
+        int     tm_hour;        /* hours */
+        int     tm_mday;        /* day of the month */
+        int     tm_mon;         /* month */
+        int     tm_year;        /* year */
+        int     tm_wday;        /* day of the week */
+        int     tm_yday;        /* day in the year */
+        int     tm_isdst;       /* daylight saving time */
+        long int tm_gmtoff;     /* Seconds east of UTC.  */
+        cost char *tm_zone;     /* Timezone abbreviation.  */
+};
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \var{tm} per una rappresentazione del tempo in termini
+    di ora, minuti, secondi, ecc.}
+  \label{fig:sys_tm_struct}
+\end{figure}
+
+Questo viene effettuato attraverso una opportuna struttura \var{tm}, la cui
+definizione è riportata in \figref{fig:sys_tm_struct}, ed è in genere questa
+struttura che si utilizza quando si deve specificare un tempo a partire dai
+dati naturali (ora e data), dato che essa consente anche di trattare la
+gestione del fuso orario e dell'ora legale.\footnote{in realtà i due campi
+  \var{tm\_gmtoff} e \var{tm\_zone} sono estensioni previste per da BSD e
+  dalle \acr{glibc}, che, quando è definita \macro{\_BSD\_SOURCE}, hanno la
+  forma in \figref{fig:sys_tm_struct}.}
+
+Le funzioni per la gestione del \textit{broken-down time} sono varie e vanno
+da quelle usate per convertire gli altri formati in questo, usando o meno
+l'ora locale o il tempo universale, a quelle per trasformare il valore di un
+tempo in una stringa contenente data ed ora, i loro prototipi sono:
+\begin{functions}
+  \headdecl{time.h}
+  \funcdecl{char *asctime(const struct tm *tm)} 
+  Produce una stringa con data e ora partendo da un valore espresso in
+  \textit{broken-down time}.
+
+  \funcdecl{char *ctime(const time\_t *timep)} 
+  Produce una stringa con data e ora partendo da un valore espresso in
+  in formato \type{time\_t}.
+  
+  \funcdecl{struct tm *gmtime(const time\_t *timep)} 
+  Converte il \textit{calendar time} dato in formato \type{time\_t} in un
+  \textit{broken-down time} espresso in UTC.
+
+  \funcdecl{struct tm *localtime(const time\_t *timep)} 
+  Converte il \textit{calendar time} dato in formato \type{time\_t} in un
+  \textit{broken-down time} espresso nell'ora locale.
+
+  \funcdecl{time\_t mktime(struct tm *tm)}   
+  Converte il \textit{broken-down time} in formato \type{time\_t}.
+  
+  \bodydesc{Tutte le funzioni restituiscono un puntatore al risultato in caso
+  di successo e \macro{NULL} in caso di errore, tranne che \func{mktime} che
+  restitusce direttamente il valore o -1 in caso di errore.}
+\end{functions}
+
+Le prime due funzioni, \func{asctime} e \func{ctime} servono per poter
+stampare in forma leggibile un tempo; esse restituiscono il puntatore ad una
+stringa, allocata staticamente, nella forma:
+\begin{verbatim}
+"Wed Jun 30 21:49:08 1993\n"
+\end{verbatim}
+e settano anche la variabile \var{tzname} con l'infomazione della \textit{time
+  zone} corrente; \func{ctime} è banalmente definita in termini di
+\func{asctime} come \code{asctime(localtime(t)}. Dato che l'uso di una stringa
+statica rende le funzioni non rientranti POSIX.1c e SUSv2 prevedono due
+sostitute rientranti, il cui nome è al solito ottenuto appendendo un
+\code{\_r}, che prendono un secondo parametro \code{char *buf}, in cui
+l'utente deve specificare il buffer su cui la stringa deve essere copiata
+(deve essere di almeno 26 caratteri).
+
+Le altre tre funzioni, \func{gmtime}, \func{localtime} e \func{mktime} servono
+per convertire il tempo dal formato \type{time\_t} a quello di \var{tm} e
+viceversa; \func{gmtime} effettua la conversione usando il tempo coordinato
+universale (UTC), cioè l'ora di Greenwich; mentre \func{localtime} usa l'ora
+locale; \func{mktime} esegue la conversione inversa.  
+
+Anche in questo caso le prime due funzioni restituiscono l'indirizzo di una
+struttura allocata staticamente, per questo sono state definite anche altre
+due versioni rientranti (con la solita estensione \code{\_r}), che prevedono
+un secondo parametro \code{struct tm *result}, fornito dal chiamante, che deve
+preallocare la struttura su cui sarà restituita la conversione.
+
+Come mostrato in \figref{fig:sys_tm_struct} il \textit{broken-down time}
+permette di tenere conto anche della differenza fra tempo universale e ora
+locale, compresa l'eventuale ora legale. Questo viene fatto attraverso le tre
+variabli globali mostrate in \figref{fig:sys_tzname}, cui si accede quando si
+include \file{time.h}. Queste variabili vengono settate quando si chiama una
+delle precedenti funzioni di conversione, oppure invocando direttamente la
+funzione \func{tzset}, il cui prototipo è:
+\begin{prototype}{sys/timex.h}
+{void tzset(void)} 
+  
+  Setta le variabili globali della \textit{time zone}.
+  
+  \bodydesc{La funzione non ritorna niente e non dà errori.}
+\end{prototype}
+
+La funzione inizializza le varaibili di \figref{fig:sys_tzname} a partire dal
+valore della variabile di ambiente \macro{TZ}, se quest'ultima non è definita
+verrà usato il file \file{/etc/localtime}.
+
+\begin{figure}[!htb]
+  \footnotesize
+  \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
+extern char *tzname[2];
+extern long timezone;
+extern int daylight;
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{Le variabili globali usate per la gestione delle \textit{time
+      zone}.}  
+  \label{fig:sys_tzname}
+\end{figure}
+
+La variabile \var{tzname} contiene due stringhe, che indicano i due nomi
+standard della \textit{time zone} corrente. La prima è il nome per l'ora
+solare, la seconda per l'ora legale.\footnote{anche se sono indicati come
+  \code{char *} non è il caso di modificare queste stringhe.} La variabile
+\var{timezone} indica la differenza di fuso orario in secondi, mentre
+\var{daylight} indica se è attiva o meno l'ora legale. 
+
 
 
 \section{La gestione degli errori}
@@ -1955,7 +2237,7 @@ Esamineremo in questa sezione le sue caratteristiche principali.
 \subsection{La variabile \var{errno}}
 \label{sec:sys_errno}
 
-Quasi tutte le funzioni delle librerie del C sono in grado di individuare e
+Quasi tutte le funzioni delle librerie del C sono in  grado di individuare e
 riportare condizioni di errore, ed è una buona norma di programmazione
 controllare sempre che le funzioni chiamate si siano concluse correttamente.