\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 caratteristiche 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 lettura delle caratteristiche del sistema}
\label{sec:sys_characteristics}

In questa sezione tratteremo le varie modalità con cui un programma può
ottenere informazioni riguardo alle capacità del sistema. Ogni sistema infatti
è contraddistinto da un gran numero di limiti e costanti che lo
caratterizzano, e che possono dipendere da fattori molteplici, come
l'architettura hardware, l'implementazione del kernel e delle librerie, le
opzioni di configurazione.

La definizione di queste caratteristiche ed il tentativo di provvedere dei
meccanismi generali che i programmi potessero usare per ricavarle è uno degli
aspetti più complessi e controversi coi cui i vari standard si sono dovuti
confrontare, spesso con risultati spesso tutt'altro che chiari. Proveremo
comunque a dare una descrizione dei principali metodi previsti dai vari
standard per ricavare sia le caratteristiche specifiche del sistema, che
quelle dei file.


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

Quando si devono determinare le le caratteristiche generali del sistema ci si
trova di fronte a diverse possibilità; alcune di queste infatti possono
dipendere dall'architettura dell'hardware (come le dimensioni dei tipi
interi), o dal sistema operativo (come la presenza o meno dei \textit{saved
  id}) , altre invece possono dipendere dalle opzioni con cui si è costruito
il sistema (ad esempio da come si è compilato il kernel), o dalla
configurazione del medesimo; per questo motivo in generale sono necessari due
tipi diversi 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 ovviamente necessarie delle funzioni; la situazione
è complicata dal fatto che ci sono molti casi in cui alcuni di questi limiti
sono fissi in una implementazione mentre possono variare in un altra. Tutto
questo crea una ambiguità che non è sempre possibile risolvere in maniera
chiara; in generale quello che succede è che quando i limiti del sistema sono
fissi essi vengono definiti come macro nel file \file{limits.h}, se invece
possono variare, il loro valore sarà ottenibile tramite la funzione
\func{sysconf} (che esamineremo in \secref{sec:sys_sysconf}).

Lo standard ANSI C definisce dei limiti che sono tutti fissi, pertanto questo
saranno sempre disponibili al momento della compilazione; un elenco, ripreso
da \file{limits.h}, è riportato in \tabref{tab:sys_ansic_macro}. Come si può
vedere per la maggior parte questi limiti attengono alle dimensioni dei dati
interi, che sono in genere fissati dall'architettura hardware (le analoghe
informazioni per i dati in virgola mobile sono definite a parte, ed
accessibili includendo \file{float.h}). Lo standard prevede anche un'altra
costante, \macro{FOPEN\_MAX}, che può non essere fissa e che pertanto non è
definita in \file{limits.h}; essa deve essere definita in \file{stdio.h} ed
avere un valore minimo di 8.

\begin{table}[htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|r|l|}
    \hline
    \textbf{Macro}&\textbf{Valore}&\textbf{Significato}\\
    \hline
    \hline
    \macro{MB\_LEN\_MAX}&       16  & massima dimensione di un 
                                      carattere multibyte\\
    \macro{CHAR\_BIT} &          8  & bit di \type{char}\\
    \macro{UCHAR\_MAX}&        255  & massimo di \type{unsigned char}\\
    \macro{SCHAR\_MIN}&       -128  & minimo di \type{signed char}\\
    \macro{SCHAR\_MAX}&        127  & massimo di \type{signed char}\\
    \macro{CHAR\_MIN} &\footnotemark& minimo di \type{char}\\
    \macro{CHAR\_MAX} &\footnotemark& massimo di \type{char}\\
    \macro{SHRT\_MIN} &     -32768  & minimo di \type{short}\\
    \macro{SHRT\_MAX} &      32767  & massimo di \type{short}\\
    \macro{USHRT\_MAX}&      65535  & massimo di \type{unsigned short}\\
    \macro{INT\_MAX}  & 2147483647  & minimo di \type{int}\\
    \macro{INT\_MIN}  &-2147483648  & minimo di \type{int}\\
    \macro{UINT\_MAX} & 4294967295  & massimo di \type{unsigned int}\\
    \macro{LONG\_MAX} & 2147483647  & massimo di \type{long}\\
    \macro{LONG\_MIN} &-2147483648  & minimo di \type{long}\\
    \macro{ULONG\_MAX}& 4294967295  & massimo di \type{unsigned long}\\
    \hline                
  \end{tabular}
  \caption{Macro definite in \file{limits.h} in conformità allo standard
    ANSI C.}
  \label{tab:sys_ansic_macro}
\end{table}

\footnotetext[1]{il valore può essere 0 o \macro{SCHAR\_MIN} a seconda che il
  sistema usi caratteri con segno o meno.} 

\footnotetext[2]{il valore può essere \macro{UCHAR\_MAX} o \macro{SCHAR\_MAX}
  a seconda che il sistema usi caratteri con segno o meno.}

A questi valori lo standard ISO C90 ne aggiunge altri tre, relativi al tipo
\type{long long} introdotto con il nuovo standard, i relativi valori sono in
\tabref{tab:sys_isoc90_macro}.

\begin{table}[htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|r|l|}
    \hline
    \textbf{Macro}&\textbf{Valore}&\textbf{Significato}\\
    \hline
    \hline
    \macro{LLONG\_MAX}& 9223372036854775807& massimo di \type{long long}\\
    \macro{LLONG\_MIN}&-9223372036854775808& minimo di \type{long long}\\
    \macro{ULLONG\_MAX}&18446744073709551615&
    massimo di \type{unsigned long long}\\
    \hline                
  \end{tabular}
  \caption{Macro definite in \file{limits.h} in conformità allo standard
    ISO C90.}
  \label{tab:sys_isoc90_macro}
\end{table}

Ovviamente le dimensioni dei vari tipi di dati sono solo una piccola parte
delle caratteristiche del sistema; mancano completamente tutte quelle che
dipendono dalla implementazione dello stesso; questo per i sistemi unix-like è
stato definito in gran parte dallo standard POSIX.1, che tratta anche i limiti
delle caratteristiche dei file che vedremo in \secref{sec:sys_file_limits}.

Purtroppo la sezione dello standard che tratta questi argomenti è una delle
meno chiare\footnote{tanto che Stevens, in \cite{APUE}, la porta come esempio
  di ``standardese''.}, ad esempio lo standard prevede che ci siano 13 macro
che descrivono le caratteristiche del sistema (7 per le caratteristiche
generiche, riportate in \tabref{tab:sys_generic_macro}, e 6 per le
caratteristiche dei file, riportate in \tabref{tab:sys_file_macro}).

\begin{table}[htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|r|p{8cm}|}
    \hline
    \textbf{Macro}&\textbf{Valore}&\textbf{Significato}\\
    \hline
    \hline
    \macro{ARG\_MAX} &131072& dimensione massima degli argomenti
                              passati ad una funzione della famiglia
                              \func{exec}.\\ 
    \macro{CHILD\_MAX} & 999& numero massimo di processi contemporanei
                              che un utente può eseguire.\\
    \macro{OPEN\_MAX}  & 256& numero massimo di file che un processo
                              può mantenere aperti in contemporanea.\\
    \macro{STREAM\_MAX}&   8& massimo numero di stream aperti per
                              processo in contemporanea.\\
    \macro{TZNAME\_MAX}&   6& dimensione massima del nome di una
                              \texttt{timezone} (vedi ).\\ 
    \macro{NGROUPS\_MAX}& 32& numero di gruppi supplementari per
                              processo (vedi \secref{sec:proc_access_id}).\\
    \macro{SSIZE\_MAX}&32767& valore massimo del tipo \type{ssize\_t}.\\
    \hline
    \hline
  \end{tabular}
  \caption{Macro .}
  \label{tab:sys_generic_macro}
\end{table}

Lo standard prevede che queste macro devono essere definite in \file{limits.h}
quando i valori a cui fanno riferimento sono fissi, e altrimenti devono essere
lasciate indefinite, ed i loro valori dei limiti devono essere accessibili
solo attraverso \func{sysconf}.  Si tenga presente poi che alcuni di questi
limiti possono assumere valori molto elevati (come \macro{CHILD\_MAX}), e non
è pertanto il caso di utilizzarli per allocare staticamente della memoria.

A complicare la faccenda si aggiunge il fatto che POSIX.1 prevede una serie di
altre macro (che iniziano sempre con \code{\_POSIX\_}) che definiscono i
valori minimi le stesse caratteristiche devono avere, perché una
implementazione possa dichiararsi conforme allo standard; detti valori sono
riportati in \tabref{tab:sys_posix1_general}.

\begin{table}[htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|r|p{8cm}|}
    \hline
    \textbf{Macro}&\textbf{Valore}&\textbf{Significato}\\
    \hline
    \hline
    \macro{\_POSIX\_ARG\_MAX}    & 4096& dimensione massima degli argomenti
                                         passati ad una funzione della famiglia
                                         \func{exec}.\\ 
    \macro{\_POSIX\_CHILD\_MAX}  &    6& numero massimo di processi
                                         contemporanei che un utente può 
                                         eseguire.\\
    \macro{\_POSIX\_OPEN\_MAX}   &   16& numero massimo di file che un processo
                                         può mantenere aperti in 
                                         contemporanea.\\
    \macro{\_POSIX\_STREAM\_MAX} &    8& massimo numero di stream aperti per
                                         processo in contemporanea.\\
    \macro{\_POSIX\_TZNAME\_MAX} &     & dimensione massima del nome di una
                                         \texttt{timezone} (vedi ).\\ 
    \macro{\_POSIX\_NGROUPS\_MAX}&    0& numero di gruppi supplementari per
                                         processo (vedi 
                                         \secref{sec:proc_access_id}).\\
    \macro{\_POSIX\_SSIZE\_MAX}  &32767& valore massimo del tipo 
                                         \type{ssize\_t}.\\
    \macro{\_POSIX\_AIO\_LISTIO\_MAX}&2& \\
    \macro{\_POSIX\_AIO\_MAX}    &    1& \\
    \hline                
    \hline                
  \end{tabular}
  \caption{Macro dei valori minimi delle caratteristiche generali del sistema
    per la conformità allo standard POSIX.1.}
  \label{tab:sys_posix1_general}
\end{table}

In genere questi valori non servono a molto, la loro unica utilità è quella di
indicare un limite superiore che assicura la portabilità senza necessità di
ulteriori controlli. Tuttavia molti di essi sono ampiamente superati in tutti
i sistemi POSIX in uso oggigiorno. Per questo è sempre meglio utilizzare i
valori ottenuti da \func{sysconf}.

\begin{table}[htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Macro}&\textbf{Significato}\\
    \hline
    \hline
    \macro{\_POSIX\_JOB\_CONTROL}& il sistema supporta il 
                                   \textit{job control} (vedi 
                                   \secref{sec:sess_xxx}).\\
    \macro{\_POSIX\_SAVED\_IDS}  & il sistema supporta i \textit{saved id} 
                                   (vedi \secref{sec:proc_access_id}). 
                                   per il controllo di accesso dei processi\\
    \macro{\_POSIX\_VERSION}     & fornisce la versione dello standard POSIX.1
                                   supportata nel formato YYYYMML (ad esempio 
                                   199009L).\\
    \hline
  \end{tabular}
  \caption{Alcune macro definite in \file{limits.h} in conformità allo standard
    POSIX.1.}
  \label{tab:sys_posix1_other}
\end{table}

Oltre ai precedenti valori (e a quelli relativi ai file elencati in
\tabref{tab:sys_posix1_file}), che devono essere obbligatoriamente definiti,
lo standard POSIX.1 ne prevede parecchi altri.  La lista completa si trova
dall'header file \file{bits/posix1\_lim.h} (da non usare mai direttamente, è
incluso automaticamente all'interno di \file{limits.h}); di questi vale la
pena menzionare quelli di uso più comune, riportati in
\tabref{tab:sys_posix1_other}, che permettono di ricavare alcune
caratteristiche del sistema (come il supporto del \textit{job control} o dei
\textit{saved id}).

Oltre allo standard POSIX.1, anche lo standard POSIX.2 definisce una serie di
altre macro. Siccome queste sono principalmente attinenti a limiti relativi
alle applicazioni di sistema presenti (come quelli su alcuni parametri delle
espressioni regolari o del comando \cmd{bc}), non li tratteremo
esplicitamente, se ne trova una menzione completa nell'header file
\file{bits/posix2\_lim.h}, e alcuni di loro sono descritti nella man page di
\func{sysconf} e nel manuale delle \acr{glibc}.


\subsection{La funzione \func{sysconf}}
\label{sec:sys_sysconf}

Come accennato in \secref{sec:sys_limits} quando uno dei limiti o delle
caratteristiche del sistema può variare, è necessario ottenerne il valore
attraverso la funzione \func{sysconf}, per non dover essere costretti a
ricompilare un programma tutte le volte che si cambiano le opzioni con cui è
compilato il kernel, o alcuni dei parametri modificabili a run time. Il suo
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}

La funzione prende come argomento un intero che specifica quale dei limiti si
vuole conoscere; uno specchietto contenente i principali valori disponibili in
Linux è riportato in \tabref{tab:sys_sysconf_par}; l'elenco completo è
contenuto in \file{bits/confname}, ed una lista più esaustiva, con le relative
spiegazioni, si può trovare nel manuale delle \acr{glibc}. 

\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}&
      La dimensione massima degli argomenti passati ad una funzione
      della famiglia \func{exec}.\\
      \texttt{\_SC\_CHILD\_MAX}&\macro{\_CHILD\_MAX}&
      Il numero massimo di processi contemporanei che un utente può
      eseguire.\\
      \texttt{\_SC\_OPEN\_MAX}&\macro{\_OPEN\_MAX}&
      Il numero massimo di file che un processo può mantenere aperti in
      contemporanea.\\
      \texttt{\_SC\_STREAM\_MAX}& \macro{STREAM\_MAX}&
      Il massimo numero di stream che un processo può mantenere aperti in
      contemporanea. Questo limite previsto anche dallo standard ANSI C, che
      specifica la macro {FOPEN\_MAX}.\\
      \texttt{\_SC\_TZNAME\_MAX}&\macro{TZNAME\_MAX}&
      La dimensione massima di un nome di una \texttt{timezone} (vedi ).\\
      \texttt{\_SC\_NGROUPS\_MAX}&\macro{NGROUP\_MAX}&
      Massimo numero di gruppi supplementari che può avere un processo (vedi
      \secref{sec:proc_access_id}).\\ 
      \texttt{\_SC\_SSIZE\_MAX}&\macro{SSIZE\_MAX}& 
      valore massimo del tipo di dato \type{ssize\_t}.\\
      \texttt{\_SC\_CLK\_TCK}& \macro{CLK\_TCK} &
      Il numero di \textit{clock tick} al secondo, cioè la frequenza delle
      interruzioni del timer di sistema (vedi \secref{sec:proc_priority}).\\
      \texttt{\_SC\_JOB\_CONTROL}&\macro{\_POSIX\_JOB\_CONTROL}&
      Indica se è supportato il \textit{job control} (vedi
      \secref{sec:sess_xxx}) in stile POSIX.\\
      \texttt{\_SC\_SAVED\_IDS}&\macro{\_POSIX\_SAVED\_IDS}&
      Indica se il sistema supporta i \textit{saved id} (vedi
      \secref{sec:proc_access_id}).\\ 
      \texttt{\_SC\_VERSION}& \macro{\_POSIX\_VERSION} &
      Indica il mese e l'anno di approvazione della revisione dello standard
      POSIX.1 a cui il sistema fa riferimento, nel formato YYYYMML, la
      revisione più recente è 199009L, che indica il Settembre 1990.\\
     \hline
    \end{tabular}
  \caption{Parametri del sistema leggibili dalla funzione \func{sysconf}.}
  \label{tab:sys_sysconf_par}
\end{table}

In generale ogni limite o caratteristica del sistema per cui è definita una
macro, sia dagli standard ANSI C e ISO C90, che da POSIX.1 e POSIX.2, può
essere ottenuto attraverso una chiamata a \func{sysconf}. Il valore si otterrà
speficando come valore del parametro \param{name} il nome ottenuto aggiungendo
\code{\_SC\_} ai nomi delle macro definite dai primi due, o sostituendolo a
\code{\_POSIX\_} per le macro definite dagli gli altri due.

In generale si dovrebbe fare uso di \func{sysconf} solo quando la relativa
macro non è definita, quindi con un codice analogo al seguente:
\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
get_child_max(void)
{
#ifdef CHILD_MAX
    return CHILD_MAX;
#else
    int val = sysconf(_SC_CHILD_MAX);
    if (val < 0) {
        perror("fatal error");
        exit(-1);
    }
    return val;
}
\end{lstlisting}
ma in realtà in Linux queste macro sono comunque definite e indicando un
limite generico, per cui è sempre meglio usare i valori restituiti da
quest'ultima.


\subsection{I limiti dei file}
\label{sec:sys_file_limits}

Come per le caratteristiche generali del sistema anche per i file esistono una
serie di limiti (come la lunghezza del nome del file o il numero massimo di
link) che dipendono sia dall'implementazione che dal filesystem in uso; anche
in questo caso lo standard prevede alcune macro che ne specificano il valore,
riportate in \tabref{tab:sys_file_macro}.

\begin{table}[htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|r|p{8cm}|}
    \hline
    \textbf{Macro}&\textbf{Valore}&\textbf{Significato}\\
    \hline
    \hline                
    \macro{NAME\_MAX}&  14  & lunghezza in byte di un nome di file. \\
    \macro{PATH\_MAX}& 256  & lunghezza in byte di pathname.\\
    \macro{PIPE\_BUF}& 512  & byte scrivibili atomicamente in una pipe\\
    \macro{LINK\_MAX}   &8  & numero massimo di link a un file\\
    \macro{MAX\_CANON}&255  & spazio disponibile nella coda di input
                              canonica del terminale\\
    \macro{MAX\_INPUT}&255  & spazio disponibile nella coda di input 
                              del terminale\\
    \hline                
  \end{tabular}
  \caption{Macro per i limiti sulle caratteristiche dei file.}
  \label{tab:sys_file_macro}
\end{table}

Come per i limiti di sistema POSIX.1 detta una serie di valori minimi per
queste caratteristiche, che ogni sistema che vuole essere conforme deve
rispettare; le relative macro sono riportate in \tabref{tab:sys_posix1_file},
e per esse vale lo stesso discorso fatto per le analoghe di
\tabref{tab:sys_posix1_general}.

\begin{table}[htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|r|p{8cm}|}
    \hline
    \textbf{Macro}&\textbf{Valore}&\textbf{Significato}\\
    \hline
    \hline
    \textbf{Macro}&\textbf{Valore}&\textbf{Significato}\\
    \macro{\_POSIX\_LINK\_MAX}   &8  & numero massimo di link a un file\\
    \macro{\_POSIX\_MAX\_CANON}&255  & spazio disponibile nella coda di input
                                       canonica del terminale\\
    \macro{\_POSIX\_MAX\_INPUT}&255  & spazio disponibile nella coda di input 
                                       del terminale\\
    \macro{\_POSIX\_NAME\_MAX}&  14  & lunghezza in byte di un nome di file. \\
    \macro{\_POSIX\_PATH\_MAX}& 256  & lunghezza in byte di pathname.\\
    \macro{\_POSIX\_PIPE\_BUF}& 512  & byte scrivibili atomicamente in una
                                       pipe\\
    \macro{\_POSIX\_MQ\_OPEN\_MAX}&  8& \\
    \macro{\_POSIX\_MQ\_PRIO\_MAX}& 32& \\
    \macro{\_POSIX\_FD\_SETSIZE}& 16 & \\
    \macro{\_POSIX\_DELAYTIMER\_MAX}& 32 & \\
    \hline
  \end{tabular}
  \caption{Macro dei valori minimi delle caratteristiche dei file per la
    conformità allo standard POSIX.1.}
  \label{tab:sys_posix1_file}
\end{table}

Tutti questi limiti sono definiti in \file{limits.h}; come nel caso precedente
il loro uso è di scarsa utilità in quanto ampiamente superati in tutte le
implementazioni moderne.


\subsection{La funzione \func{pathconf}}
\label{sec:sys_pathconf}

In generale i limiti per i file sono molto più soggetti ad essere variabili
rispetto ai precedenti limiti generali del sistema; ad esempio parametri come
la lunghezza del nome del file o il numero di link possono variare da
filesystem a filesystem; per questo motivo questi limiti devono essere sempre
controllati con la funzione \func{pathconf}, il cui prototipo è:
\begin{prototype}{unistd.h}{long pathconf(char *path, int name)}
  Restituisce il valore del parametro \param{name} per il file \param{path}.
  
  \bodydesc{La funzione restituisce indietro il valore del parametro
    richiesto, o -1 in caso di errore (ed \var{errno} viene settata ad uno
    degli errori possibili relativi all'accesso a \param{path}).}
\end{prototype}

E si noti come la funzione in questo caso richieda un parametro che specifichi
a quale file si fa riferimento, dato che il valore del limite cercato può
variare a seconda del filesystem. Una seconda versione della funzione,
\func{fpathconf}, opera su un file descriptor invece che su un pathname, il
suo prototipo è:
\begin{prototype}{unistd.h}{long fpathconf(int fd, int name)}
  Restituisce il valore del parametro \param{name} per il file \param{fd}.
  
  \bodydesc{È identica a \func{pathconf} solo che utilizza un file descriptor
    invece di un pathname; pertanto gli errori restituiti cambiano di
    conseguenza.}
\end{prototype}
\noindent ed il suo comportamento è identico a quello di \func{fpathconf}.


\subsection{La funzione \func{uname}}
\label{sec:sys_uname}

Una altra funzione che si può utilizzare per raccogliere informazioni riguardo
al sistema ed al computer su cui esso sta girando è \func{uname}, il suo
prototipo è:
\begin{prototype}{sys/utsname.h}{int uname(struct utsname *info)}
  Restituisce informazioni sul sistema nella struttura \param{info}.
  
  \bodydesc{La funzione ritorna 0 in caso di successo e -1 in caso di
  fallimento, nel qual caso \var{errno} viene settata a \macro{EFAULT}.}
\end{prototype}
\noindent la struttura è anch'essa definita in \file{sys/utsname.h} come:
\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
    struct utsname {
        char sysname[_UTSNAME_LENGTH];
        char nodename[_UTSNAME_LENGTH];
        char release[_UTSNAME_LENGTH];
        char version[_UTSNAME_LENGTH];
        char machine[_UTSNAME_LENGTH];
#ifdef _GNU_SOURCE
        char domainname[_UTSNAME_DOMAIN_LENGTH];
#endif
    };
\end{lstlisting}
ed i suoi menbri indicano rispettivamente:
\begin{itemize*}
\item il nome del systema operativo;
\item il nome della release del kernel;
\item il nome della versione del kernel;
\item il tipo di macchina in uso;
\item il nome della stazione;
\item il nome del domino (è una estensione recente).
\end{itemize*}



\section{Opzioni e configurazione del sistema}
\label{sec:sys_config}

In questa sezione prenderemo in esame le funzioni per leggere e settare i vari
parametri di configurazione del sistema. 


\subsection{La funzione \func{sysctl}}
\label{sec:sys_sysctl}

\subsection{Il filesystem \file{/proc}}
\label{sec:sys_proc_files}


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

\subsection{La funzione \func{statfs}}
\label{sec:sys_file_stafs}



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

In questa sezione esamineremo 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 riferimento 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: 
