\chapter{La gestione del sistema, delle risorse, e degli errori}
\label{cha:system}

In questo capitolo tratteremo varie interfacce che attengono agli aspetti più
generali del sistema, come quelle per la gestione di parametri e
configurazione, quelle per la lettura dei limiti e delle carattistiche dello
stesso, quelle per il controllo dell'uso delle risorse da parte dei processi,
quelle per la gestione dei tempi e degli errori.


\section{La configurazione del sistema}
\label{sec:sys_config}

In questa sezione esamineremo le macro e le funzioni che permettono di
conoscere e settare i parametri di configurazione del sistema, di ricavarme
limiti e caratteristiche, e di controllare i filesystem disponibili, montarli
e rimuoverli da programma.


\subsection{Limiti e parametri di sistema}
\label{sec:sys_sys_limits}

In qualunque sistema sono presenti un gran numero di parametri e costanti il
cui valore può essere definito dall'architettura dell'hardware,
dall'implementazione del sistema, dalle opzioni con cui si sono compilati il
kernel e le librerie o anche configurabili dall'amministratore all'avvio del
sistema o durente le sue attività.

Chiaramente per scrivere programmi portabili occorre poter determinare opzioni
disponibili e caratteristiche del sistema (come i valori massimi e minimi dei
vari tipi di variabili, o la presenza del supporto del supporto per
l'operazione che interessa). Inoltre alcuni di questi limiti devono poter
essere determinabili anche in corso di esecuzione del programma, per non dover
ricompilare tutti i programmi quando si usa una nuova versione del kernel o si
cambia una delle configurazioni del sistema. Per tutto questo sono necessari
due tipi di funzionalità:
\begin{itemize*}
\item la possibilità di determinare limiti ed opzioni al momento della
  compilazione.
\item la possibilità di determinare limiti ed opzioni durante l'esecuzione.
\end{itemize*}

La prima funzionalità si può ottenere includendo gli opportuni header file,
mentre per la seconda sono ovviamante necessarie delle funzioni; ci sono molti
casi però in cui alcuni di questi limiti sono fissi in una implementazione
mentre possono variare in un altra.

Lo standard ANSI C definisce dei limiti solo sulle dimensioni dei tipi dei
dati, che sono ovviamente fissi, gli standard POSIX.1 e POSIX.2 ne definiscono
molti altri attinenti alle caratteristiche del sistema (come il numero massimo
di figli, la lunghezza di un pathname, ecc.) che possono essere fissi o meno:
quando sono fissi vengono definiti come macro nel file \file{limits.h}, se
invece possono variare la macro corrispondente deve essere indefinita, ed il
loro valore sarà ottenibile tramite la funzione \func{sysconf}, il cui
prototipo è:
\begin{prototype}{unistd.h}{long sysconf(int name)}  
  Restituisce il valore del parametro di sistema \param{name}.
  
  \bodydesc{La funzione restituisce indietro il valore del parametro
    richiesto, o 1 se si tratta di un'opzione disponibile, 0 se l'opzione non
    è disponibile e -1 in caso di errore (ma \var{errno} non viene settata).}
\end{prototype}
\noindent ed i valori possibili disponibili in Linux per \param{name} sono
definiti in \ntab.

\begin{table}[htb]
  \centering
  \footnotesize
    \begin{tabular}[c]{|l|l|p{9cm}|}
      \hline
      \textbf{Parametro}&\textbf{macro sostituita} &\textbf{Significato}\\
      \hline
      \hline
      \texttt{\_SC\_ARG\_MAX} &\macro{ARG\_MAX}&
              The  maximum  length of the arguments to the exec()
              family of functions;  the  corresponding  macro  is
              . \\
       \texttt{\_SC\_CHILD\_MAX}&\macro{\_POSIX\_CHILD\_MAX}&
              The  number  of simultaneous processes per user id,
              the corresponding macro is .\\
       \texttt{\_SC\_CLK\_TCK}& \macro{CLK\_TCK} &
              The number of clock ticks per  second;  the  corre­
              sponding macro is.\\
       \texttt{\_SC\_STREAM\_MAX}& \macro{STREAM\_MAX}&
              The  maximum  number  of streams that a process can
              have open at any  time.    the corresponding standard C
              macro is \macro{FOPEN\_MAX}.\\
       \texttt{\_SC\_TZNAME\_MAX}&\macro{TZNAME\_MAX}&
              The maximum number of bytes in a timezone name, the
              corresponding macro is .\\
       \texttt{\_SC\_OPEN\_MAX}&\macro{\_POSIX\_OPEN\_MAX}&
              The maximum number of files that a process can have
              open  at  any  time,  the  corresponding  macro  is
              .\\
       \texttt{\_SC\_JOB\_CONTROL}&\macro{\_POSIX\_JOB\_CONTROL}&
              This indicates whether POSIX - style job control is
              supported,    the    corresponding     macro     is
              .\\
       \texttt{\_SC\_SAVED\_IDS}&\macro{\_POSIX\_SAVED\_IDS}&
              This  indicates  whether a process has a saved set-
              user-ID and a saved set-group-ID; the corresponding
              macro is\\
       \texttt{\_SC\_VERSION}& nessuna &
              indicates  the  year and month the POSIX.1 standard
              was  approved  in  the  format  YYYYMML;the   value
              199009L indicates the most recent revision, 1990.\\
     \hline
    \end{tabular}
  \caption{Parametri del sistema leggibili dalla funzione \func{sysconf}.}
  \label{tab:sys_sysconf_par}
\end{table}



\subsection{Opzioni e configurazione del sistema}
\label{sec:sys_sys_config}

La funzione \func{sysctl} ...



\subsection{La configurazione dei filesystem}
\label{sec:sys_file_config}

La funzione \func{statfs} ...

La funzione \func{pathconf} ...




\section{Limitazione ed uso delle risorse}
\label{sec:sys_limits}

In questa sezione esamimeremo le funzioni che permettono di esaminare e
controllare come le varie risorse del sistema (CPU, memoria, ecc.) vengono
utilizzate dai processi, e le modalità con cui è possibile imporre dei limiti
sul loro utilizzo.



\subsection{L'uso delle risorse}
\label{sec:sys_resource_use}


\subsection{Limiti sulle risorse}
\label{sec:sys_resource_limit}


\subsection{Le risorse di memoria}
\label{sec:sys_memory_res}


\subsection{Le risorse di processore}
\label{sec:sys_cpu_load}



\begin{figure}[!htb]
  \footnotesize
  \centering
  \begin{minipage}[c]{15cm}
    \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
struct rusage {
     struct timeval ru_utime; /* user time used */
     struct timeval ru_stime; /* system time used */
     long ru_maxrss;          /* maximum resident set size */
     long ru_ixrss;           /* integral shared memory size */
     long ru_idrss;           /* integral unshared data size */
     long ru_isrss;           /* integral unshared stack size */
     long ru_minflt;          /* page reclaims */
     long ru_majflt;          /* page faults */
     long ru_nswap;           /* swaps */
     long ru_inblock;         /* block input operations */
     long ru_oublock;         /* block output operations */
     long ru_msgsnd;          /* messages sent */
     long ru_msgrcv;          /* messages received */
     long ru_nsignals;   ;    /* signals received */
     long ru_nvcsw;           /* voluntary context switches */
     long ru_nivcsw;          /* involuntary context switches */
};
    \end{lstlisting}
  \end{minipage} 
  \normalsize 
  \caption{La struttura \var{rusage} per la lettura delle informazioni dei 
    delle risorse usate da un processo.}
  \label{fig:sys_rusage_struct}
\end{figure}




\var{tms\_utime}, \var{tms\_stime}, \var{tms\_cutime}, \var{tms\_uetime}



\section{La gestione dei tempi del sistema}
\label{sec:sys_time}

In questa sezione tratteremo le varie funzioni per la gestione delle
date e del tempo in un sistema unix-like, e quelle per convertire i vari
tempi nelle differenti rappresentazioni che vengono utilizzate.


\subsection{La misura del tempo in unix}
\label{sec:sys_unix_time}

Storicamente i sistemi unix-like hanno sempre mantenuto due distinti
valori per i tempi all'interno del sistema, essi sono rispettivamente
chiamati \textit{calendar time} e \textit{process time}, secondo le
definizioni:
\begin{itemize}
\item \textit{calendar time}: è il numero di secondi dalla mezzanotte del
  primo gennaio 1970, in tempo universale coordinato (o UTC), data che viene
  usualmente indicata con 00:00:00 Jan, 1 1970 (UTC) e chiamata \textit{the
    Epoch}. Questo tempo viene anche chiamato anche GMT (Greenwich Mean Time)
  dato che l'UTC corrisponde all'ora locale di Greenwich.  È il tempo su cui
  viene mantenuto l'orologio del calcolatore, e viene usato ad esempio per
  indicare le date di modifica dei file o quelle di avvio dei processi. Per
  memorizzare questo tempo è stato riservato il tipo primitivo \type{time\_t}.
\item \textit{process time}: talvolta anche detto tempo di CPU. Viene misurato
  in \textit{clock tick}, corrispondenti al numero di interruzioni effettuate
  dal timer di sistema, e che per Linux avvengono ogni centesimo di
  secondo\footnote{eccetto per la piattaforma alpha dove avvengono ogni
    millesimo di secondo}. Il dato primitivo usato per questo tempo è
  \type{clock\_t}, inoltre la costante \macro{HZ} restituisce la frequenza di
  operazione del timer, e corrisponde dunque al numero di tick al secondo.  Lo
  standard POSIX definisce allo stesso modo la costante \macro{CLK\_TCK});
  questo valore può comunque essere ottenuto con \func{sysconf} (vedi
  \secref{sec:sys_limits}).
\end{itemize}

In genere si usa il \textit{calendar time} per tenere le date dei file e le
informazioni analoghe che riguardano i tempi di ``orologio'', usati ad esempio
per i demoni che compiono lavori amministrativi ad ore definite, come
\cmd{cron}. Di solito questo vene convertito automaticamente dal valore in UTC
al tempo locale, utilizzando le opportune informazioni di localizzazione
(specificate in \file{/etc/timezone}). E da tenere presente che questo tempo è
mantenuto dal sistema e non corrisponde all'orologio hardware del calcolatore.

Il \textit{process time} di solito si esprime in secondi e viene usato appunto
per tenere conto dei tempi di esecuzione dei processi. Per ciascun processo il
kernel tiene tre di questi tempi: 
\begin{itemize*}
\item \textit{clock time}
\item \textit{user time}
\item \textit{system time}
\end{itemize*}
il primo è il tempo ``reale'' (viene anche chiamato \textit{wall clock time})
dall'avvio del processo, e misura il tempo trascorso fino alla sua
conclusione; chiaramente un tale tempo dipende anche dal carico del sistema e
da quanti altri processi stavano girando nello stesso periodo. Il secondo
tempo è quello che la CPU ha speso nell'esecuzione delle istruzioni del
processo in user space. Il terzo è il tempo impiegato dal kernel per eseguire
delle system call per conto del processo medesimo (tipo quello usato per
eseguire una \func{write} su un file). In genere la somma di user e system
time viene chiamato \textit{CPU time}. 





\section{La gestione degli errori}
\label{sec:sys_errors}

La gestione degli errori è in genere una materia complessa. Inoltre il modello
utilizzato dai sistema unix-like è basato sull'architettura a processi, e
presenta una serie di problemi nel caso lo si debba usare con i thread.
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
riportare condizioni di errore, ed è una buona norma di programmazione
controllare sempre che le funzioni chiamate si siano concluse correttamente.

In genere le funzioni di libreria usano un valore speciale per indicare che
c'è stato un errore. Di solito questo valore è -1 o un puntatore nullo o la
costante \macro{EOF} (a seconda della funzione); ma questo valore segnala solo
che c'è stato un errore, non il tipo di errore. 

Per riportare il tipo di errore il sistema usa la variabile globale
\var{errno}\footnote{L'uso di una variabile globale può comportare alcuni
  problemi (ad esempio nel caso dei thread) ma lo standard ISO C consente
  anche di definire \var{errno} come un \textit{modifiable lvalue}, quindi si
  può anche usare una macro, e questo è infatti il modo usato da Linux per
  renderla locale ai singoli thread.}, definita nell'header \file{errno.h}; la
variabile è in genere definita come \type{volatile} dato che può essere
cambiata in modo asincrono da un segnale (per una descrizione dei segnali si
veda \secref{cha:signals}), ma dato che un manipolatore di segnale scritto
bene salva e ripristina il valore della variabile, di questo non è necessario
preoccuparsi nella programmazione normale.

I valori che può assumere \var{errno} sono riportati in \capref{cha:errors},
nell'header \file{errno.h} sono anche definiti i nomi simbolici per le
costanti numeriche che identificano i vari errori; essi iniziano tutti per
\macro{E} e si possono considerare come nomi riservati. In seguito faremo
sempre rifermento a tali valori, quando descriveremo i possibili errori
restituiti dalle funzioni. Il programma di esempio \cmd{errcode} stampa il
codice relativo ad un valore numerico con l'opzione \cmd{-l}.

Il valore di \var{errno} viene sempre settato a zero all'avvio di un
programma, gran parte delle funzioni di libreria settano \var{errno} ad un
valore diverso da zero in caso di errore. Il valore è invece indefinito in
caso di successo, perché anche se una funzione ha successo, può chiamarne
altre al suo interno che falliscono, modificando così \var{errno}.

Pertanto un valore non nullo di \var{errno} non è sintomo di errore (potrebbe
essere il risultato di un errore precedente) e non lo si può usare per
determinare quando o se una chiamata a funzione è fallita.  La procedura da
seguire è sempre quella di controllare \var{errno} immediatamente dopo aver
verificato il fallimento della funzione attraverso il suo codice di ritorno.


\subsection{Le funzioni \func{strerror} e \func{perror}}
\label{sec:sys_strerror}

Benché gli errori siano identificati univocamente dal valore numerico di
\var{errno} le librerie provvedono alcune funzioni e variabili utili per
riportare in opportuni messaggi le condizioni di errore verificatesi.  La
prima funzione che si può usare per ricavare i messaggi di errore è
\func{strerror}, il cui prototipo è:
\begin{prototype}{string.h}{char * strerror(int errnum)} 
  Ritorna una stringa (statica) che descrive l'errore il cui codice è passato
  come parametro.
\end{prototype}

In generale \func{strerror} viene usata passando \var{errno} come parametro;
nel caso si specifichi un codice sbagliato verrà restituito un messaggio di
errore sconosciuto. La funzione utilizza una stringa statica che non deve
essere modificata dal programma e che è utilizzabile solo fino ad una chiamata
successiva a \func{strerror}; nel caso si usino i thread è
provvista\footnote{questa funzione è una estensione GNU, non fa parte dello
  standard POSIX} una versione apposita:
\begin{prototype}{string.h}
{char * strerror\_r(int errnum, char * buff, size\_t size)} 
  Analoga a \func{strerror} ma ritorna il messaggio in un buffer
  specificato da \param{buff} di lunghezza massima (compreso il terminatore)
  \param{size}.
\end{prototype}
\noindent
che utilizza un buffer che il singolo thread deve allocare, per evitare i
problemi connessi alla condivisione del buffer statico. Infine, per completare
la caratterizzazione dell'errore, si può usare anche la variabile
globale\footnote{anche questa è una estensione GNU}
\var{program\_invocation\_short\_name} che riporta il nome del programma
attualmente in esecuzione.

Una seconda funzione usata per riportare i codici di errore in maniera
automatizzata sullo standard error (vedi \secref{sec:file_std_descr}) è
\func{perror}, il cui prototipo è:
\begin{prototype}{stdio.h}{void perror (const char *message)} 
  Stampa il messaggio di errore relativo al valore corrente di \var{errno}
  sullo standard error; preceduto dalla stringa \var{message}.
\end{prototype}
i messaggi di errore stampati sono gli stessi di \func{strerror}, (riportati
in \capref{cha:errors}), e, usando il valore corrente di \var{errno}, si
riferiscono all'ultimo errore avvenuto. La stringa specificata con
\var{message} viene stampato prime del messaggio d'errore, seguita dai due
punti e da uno spazio, il messaggio è terminato con un a capo.

Il messaggio può essere riportato anche usando altre variabili globali
dichiarate in \file{errno.h}:
\begin{verbatim}
   const char *sys_errlist[];
   int sys_nerr;
\end{verbatim}
la prima contiene i puntatori alle stringhe di errore indicizzati da
\var{errno}; la seconda esprime il valore più alto per un codice di errore,
l'utilizzo di questa stringa è sostanzialmente equivalente a quello di
\func{strerror}.

In \nfig\ è riportata la sezione attinente del codice del programma
\cmd{errcode}, che può essere usato per stampare i messaggi di errore e le
costanti usate per identificare i singoli errori; il sorgente completo del
programma è allegato nel file \file{ErrCode.c} e contiene pure la gestione
delle opzioni e tutte le definizioni necessarie ad associare il valore
numerico alla costante simbolica. In particolare si è riportata la sezione che
converte la stringa passata come parametro in un intero (\texttt{\small
  1--2}), controllando con i valori di ritorno di \func{strtol} che la
conversione sia avvenuta correttamente (\texttt{\small 4--10}), e poi stampa,
a seconda dell'opzione scelta il messaggio di errore (\texttt{\small 11--14})
o la macro (\texttt{\small 15--17}) associate a quel codice.

\begin{figure}[!htb]
  \footnotesize
  \begin{lstlisting}{}
    /* convert string to number */
    err = strtol(argv[optind], NULL, 10);
    /* testing error condition on conversion */
    if (err==LONG_MIN) {
        perror("Underflow on error code");
        return 1;
    } else if (err==LONG_MIN) {
        perror("Overflow on error code");
        return 1;
    }
    /* conversion is fine */
    if (message) {
        printf("Error message for %d is %s\n", err, strerror(err));
    }
    if (label) {
        printf("Error label for %d is %s\n", err, err_code[err]);
    }
  \end{lstlisting}
  \caption{Codice per la stampa del messaggio di errore standard.}
  \label{fig:sys_err_mess}
\end{figure}


\section{La gestione di utenti e gruppi}
\label{sec:sys_user_group}


%%% Local Variables: 
%%% mode: latex
%%% TeX-master: "gapil"
%%% End: 
