Aggiunte funzioni di gestione per le varibili di ambiente
[gapil.git] / system.tex
1 \chapter{La gestione del sistema}
2 \label{cha:system}
3
4
5
6
7
8 \subsection{La misura del tempo in unix}
9 \label{sec:intro_unix_time}
10
11 Storicamente i sistemi unix-like hanno sempre mantenuto due distinti valori
12 per i tempi all'interno del sistema, essi sono rispettivamente chiamati
13 \textit{calendar time} e \textit{process time}, secondo le definizioni:
14 \begin{itemize}
15 \item \textit{calendar time}: è il numero di secondi dalla mezzanotte del
16   primo gennaio 1970, in tempo universale coordinato (o UTC), data che viene
17   usualmente indicata con 00:00:00 Jan, 1 1970 (UTC) e chiamata \textit{the
18     Epoch}. Questo tempo viene anche chiamato anche GMT (Greenwich Mean Time)
19   dato che l'UTC corrisponde all'ora locale di Greenwich.  È il tempo su cui
20   viene mantenuto l'orologio del calcolatore, e viene usato ad esempio per
21   indicare le date di modifica dei file o quelle di avvio dei processi. Per
22   memorizzare questo tempo è stato riservato il tipo primitivo \func{time\_t}.
23 \item \textit{process time}: talvolta anche detto tempo di CPU. Viene misurato
24   in \textit{clock tick}, corrispondenti al numero di interruzioni effettuate
25   dal timer di sistema, e che per Linux avvengono ogni centesimo di
26   secondo\footnote{eccetto per la piattaforma alpha dove avvengono ogni
27     millesimo di secondo}. Il dato primitivo usato per questo tempo è
28   \func{clock\_t}, inoltre la costante \macro{HZ} restituisce la frequenza di
29   operazione del timer, e corrisponde dunque al numero di tick al secondo.  Lo
30   standard POSIX definisce allo stesso modo la costante \macro{CLK\_TCK});
31   questo valore può comunque essere ottenuto con \func{sysconf} (vedi
32   \secref{sec:sys_limits}).
33 \end{itemize}
34
35 In genere si usa il \textit{calendar time} per tenere le date dei file e le
36 informazioni analoghe che riguardano i tempi di ``orologio'', usati ad esempio
37 per i demoni che compiono lavori amministrativi ad ore definite, come
38 \cmd{cron}. Di solito questo vene convertito automaticamente dal valore in UTC
39 al tempo locale, utilizzando le opportune informazioni di localizzazione
40 (specificate in \file{/etc/timezone}). E da tenere presente che questo tempo è
41 mantenuto dal sistema e non corrisponde all'orologio hardware del calcolatore.
42
43 Il \textit{process time} di solito si esprime in secondi e viene usato appunto
44 per tenere conto dei tempi di esecuzione dei processi. Per ciascun processo il
45 kernel tiene tre di questi tempi: 
46 \begin{itemize*}
47 \item \textit{clock time}
48 \item \textit{user time}
49 \item \textit{system time}
50 \end{itemize*}
51 il primo è il tempo ``reale'' (viene anche chiamato \textit{wall clock time})
52 dall'avvio del processo, e misura il tempo trascorso fino alla sua
53 conclusione; chiaramente un tale tempo dipende anche dal carico del sistema e
54 da quanti altri processi stavano girando nello stesso periodo. Il secondo
55 tempo è quello che la CPU ha speso nell'esecuzione delle istruzioni del
56 processo in user space. Il terzo è il tempo impiegato dal kernel per eseguire
57 delle system call per conto del processo medesimo (tipo quello usato per
58 eseguire una \func{write} su un file). In genere la somma di user e system
59 time viene chiamato \textit{CPU time}. 
60
61
62
63 \section{La gestione degli errori}
64 \label{sec:intro_errors}
65
66 La gestione degli errori è in genere una materia complessa. Inoltre il modello
67 utilizzato dai sistema unix-like è basato sull'architettura a processi, e
68 presenta una serie di problemi nel caso lo si debba usare con i thread.
69 Esamineremo in questa sezione le sue caratteristiche principali.
70
71
72 \subsection{La variabile \func{errno}}
73 \label{sec:intro_errno}
74
75 Quasi tutte le funzioni delle librerie del C sono in grado di individuare e
76 riportare condizioni di errore, ed è una buona norma di programmazione
77 controllare sempre che le funzioni chiamate si siano concluse correttamente.
78
79 In genere le funzioni di libreria usano un valore speciale per indicare che
80 c'è stato un errore. Di solito questo valore è -1 o un puntatore nullo o la
81 costante \macro{EOF} (a seconda della funzione); ma questo valore segnala solo
82 che c'è stato un errore, non il tipo di errore. 
83
84 Per riportare il tipo di errore il sistema usa la variabile globale
85 \var{errno}\footnote{L'uso di una variabile globale può comportare alcuni
86   problemi (ad esempio nel caso dei thread) ma lo standard ISO C consente
87   anche di definire \var{errno} come un \textit{modifiable lvalue}, quindi si
88   può anche usare una macro, e questo è infatti il modo usato da Linux per
89   renderla locale ai singoli thread }, definita nell'header \file{errno.h}, la
90 variabile è in genere definita come \var{volatile} dato che può essere
91 cambiata in modo asincrono da un segnale (per una descrizione dei segnali si
92 veda \secref{cha:signals}), ma dato che un manipolatore di segnale scritto
93 bene salva e ripristina il valore della variabile, di questo non è necessario
94 preoccuparsi nella programmazione normale.
95
96 I valori che può assumere \var{errno} sono riportati in \capref{cha:errors},
97 nell'header \file{errno.h} sono anche definiti i nomi simbolici per le
98 costanti numeriche che identificano i vari errori; essi iniziano tutti per
99 \macro{E} e si possono considerare come nomi riservati. In seguito faremo
100 sempre rifermento a tali valori, quando descriveremo i possibili errori
101 restituiti dalle funzioni. Il programma di esempio \cmd{errcode} stampa il
102 codice relativo ad un valore numerico con l'opzione \cmd{-l}.
103
104 Il valore di \var{errno} viene sempre settato a zero all'avvio di un
105 programma, gran parte delle funzioni di libreria settano \var{errno} ad un
106 valore diverso da zero in caso di errore. Il valore è invece indefinito in
107 caso di successo, perché anche se una funzione ha successo, può chiamarne
108 altre al suo interno che falliscono, modificando così \var{errno}.
109
110 Pertanto un valore non nullo di \var{errno} non è sintomo di errore (potrebbe
111 essere il risultato di un errore precedente) e non lo si può usare per
112 determinare quando o se una chiamata a funzione è fallita.  La procedura da
113 seguire è sempre quella di controllare \var{errno} immediatamente dopo aver
114 verificato il fallimento della funzione attraverso il suo codice di ritorno.
115
116
117 \subsection{Le funzioni \func{strerror} e \func{perror}}
118 \label{sec:intro_strerror}
119
120 Benché gli errori siano identificati univocamente dal valore numerico di
121 \var{errno} le librerie provvedono alcune funzioni e variabili utili per
122 riportare in opportuni messaggi le condizioni di errore verificatesi.  La
123 prima funzione che si può usare per ricavare i messaggi di errore è
124 \func{strerror}, il cui prototipo è:
125 \begin{prototype}{string.h}{char * strerror(int errnum)} 
126   La funzione ritorna una stringa (statica) che descrive l'errore il cui
127   codice è passato come parametro.
128 \end{prototype}
129
130 In generale \func{strerror} viene usata passando \var{errno} come parametro;
131 nel caso si specifichi un codice sbagliato verrà restituito un messaggio di
132 errore sconosciuto. La funzione utilizza una stringa statica che non deve
133 essere modificata dal programma e che è utilizzabile solo fino ad una chiamata
134 successiva a \func{strerror}; nel caso si usino i thread è
135 provvista\footnote{questa funzione è una estensione GNU, non fa parte dello
136   standard POSIX} una versione apposita:
137 \begin{prototype}{string.h}
138 {char * strerror\_r(int errnum, char * buff, size\_t size)} 
139   La funzione è analoga a \func{strerror} ma ritorna il messaggio in un buffer
140   specificato da \var{buff} di lunghezza massima (compreso il terminatore)
141   \var{size}.
142 \end{prototype}
143 \noindent
144 che utilizza un buffer che il singolo thread deve allocare, per evitare i
145 problemi connessi alla condivisione del buffer statico. Infine, per completare
146 la caratterizzazione dell'errore, si può usare anche la variabile
147 globale\footnote{anche questa è una estensione GNU}
148 \var{program\_invocation\_short\_name} che riporta il nome del programma
149 attualmente in esecuzione.
150
151 Una seconda funzione usata per riportare i codici di errore in maniera
152 automatizzata sullo standard error (vedi \secref{sec:file_std_descr}) è
153 \func{perror}, il cui prototipo è:
154 \begin{prototype}{stdio.h}{void perror (const char *message)} 
155   La funzione stampa il messaggio di errore relativo al valore corrente di
156   \var{errno} sullo standard error; preceduto dalla stringa \var{message}.
157 \end{prototype}
158 i messaggi di errore stampati sono gli stessi di \func{strerror}, (riportati
159 in \capref{cha:errors}), e, usando il valore corrente di \var{errno}, si
160 riferiscono all'ultimo errore avvenuto. La stringa specificata con
161 \var{message} viene stampato prime del messaggio d'errore, seguita dai due
162 punti e da uno spazio, il messaggio è terminato con un a capo.
163
164 Il messaggio può essere riportato anche usando altre variabili globali
165 dichiarate in \file{errno.h}:
166 \begin{verbatim}
167    const char *sys_errlist[];
168    int sys_nerr;
169 \end{verbatim}
170 la prima contiene i puntatori alle stringhe di errore indicizzati da
171 \var{errno}; la seconda esprime il valore più alto per un codice di errore,
172 l'utilizzo di questa stringa è sostanzialmente equivalente a quello di
173 \func{strerror}.
174
175 In \nfig\ è riportata la sezione attinente del codice del programma
176 \cmd{errcode}, che può essere usato per stampare i messaggi di errore e le
177 costanti usate per identificare i singoli errori; il sorgente completo del
178 programma è allegato nel file \file{ErrCode.c} e contiene pure la gestione
179 delle opzioni e tutte le definizioni necessarie ad associare il valore
180 numerico alla costante simbolica. In particolare si è riportata la sezione che
181 converte la stringa passata come parametro in un intero (\texttt{\small
182   1--2}), controllando con i valori di ritorno di \func{strtol} che la
183 conversione sia avvenuta correttamente (\texttt{\small 4--10}), e poi stampa,
184 a seconda dell'opzione scelta il messaggio di errore (\texttt{\small 11--14})
185 o la macro (\texttt{\small 15--17}) associate a quel codice.
186
187 \begin{figure}[!htb]
188   \footnotesize
189   \begin{lstlisting}{}
190     /* convert string to number */
191     err = strtol(argv[optind], NULL, 10);
192     /* testing error condition on conversion */
193     if (err==LONG_MIN) {
194         perror("Underflow on error code");
195         return 1;
196     } else if (err==LONG_MIN) {
197         perror("Overflow on error code");
198         return 1;
199     }
200     /* conversion is fine */
201     if (message) {
202         printf("Error message for %d is %s\n", err, strerror(err));
203     }
204     if (label) {
205         printf("Error label for %d is %s\n", err, err_code[err]);
206     }
207   \end{lstlisting}
208   \caption{Codice per la stampa del messaggio di errore standard.}
209   \label{fig:intro_err_mess}
210 \end{figure}
211
212
213 \subsection{Valori e limiti del sistema}
214 \label{sec:sys_limits}
215