Correzioni di claudio
[gapil.git] / process.tex
index 3c1b49d899442a9a0a418a581fbc9a71fa6a1288..93ac41119150c0af0bb9222a3f4164b3c1b4c03d 100644 (file)
@@ -2,29 +2,28 @@
 \label{cha:process_interface}
 
 Come accennato nell'introduzione il processo è l'unità di base con cui un
-sistema unix alloca ed utilizza le risorse.  Questo capitolo tratterà
-l'interfaccia base fra il sistema e i processi, su come vengono passati i
-parametri, come viene gestita e allocata la memoria, su come un processo può
-richiedere servizi al sistema, su cosa deve fare quando ha finito la sua
+sistema unix-like alloca ed utilizza le risorse.  Questo capitolo tratterà
+l'interfaccia base fra il sistema e i processi, come vengono passati i
+parametri, come viene gestita e allocata la memoria, come un processo può
+richiedere servizi al sistema e cosa deve fare quando ha finito la sua
 esecuzione. Nella sezione finale accenneremo ad alcune problematiche generiche
 di programmazione.
 
 In genere un programma viene eseguito quando un processo lo fa partire
 eseguendo una funzione della famiglia \func{exec}; torneremo su questo e
-sulla la creazione e gestione dei processi nel prossimo capitolo, in questo
+sulla creazione e gestione dei processi nel prossimo capitolo. In questo
 affronteremo l'avvio e il funzionamento di un singolo processo partendo dal
-punto di vista del programma posto in esecuzione.
-
+punto di vista del programma  che viene messo in esecuzione.
 
 
 \section{Esecuzione e conclusione di un programma}
 
-Una delle concetti base relativi ai processi è che un processo esegue sempre
-uno ed un solo programma: si possono avere più processi che eseguono lo stesso
-programma ma ciascun processo vedrà la sua copia del codice (in realtà il
-kernel fa si che tutte le parti uguali siano condivise) avrà un suo spazio di
-indirizzi, variabili proprie e sarà eseguito in maniera completamente
-indipendente da tutti gli altri. 
+Uno dei concetti base di Unix è che un processo esegue sempre uno ed un solo
+programma: si possono avere più processi che eseguono lo stesso programma ma
+ciascun processo vedrà la sua copia del codice (in realtà il kernel fa si che
+tutte le parti uguali siano condivise), avrà un suo spazio di indirizzi,
+variabili proprie e sarà eseguito in maniera completamente indipendente da
+tutti gli altri.
 
 Anche quando all'interno di un programma possono essere presenti più
 \textsl{filoni} di esecuzione (i cosiddetti \textit{thread}), o questo possa
@@ -33,18 +32,19 @@ posto in esecuzione esso apparir
 discorso dei \textit{thread} comunque in Linux necessita di una trattazione a
 parte per la peculiarità dell'implementazione).
 
+
 \subsection{La funzione \func{main}} 
 \label{sec:proc_main}
 
 Quando un programma viene lanciato il kernel esegue una opportuna routine di
-avvio, usando il programma \cmd{ld-linux.so}, è questo programma che prima
-carica le librerie condivise che servono al programma, effettua il link
-dinamico del codice e poi alla fine lo esegue. Infatti, a meno di non aver
-specificato il flag \texttt{-static} durante la compilazione, tutti i
-programmi in Linux sono incompleti e necessitano di essere linkati alle
-librerie condivise quando vengono avviati.  La procedura è controllata da
-alcune variabili di ambiente e dal contenuto di \file{/etc/ld.so.conf}, i
-dettagli sono riportati nella man page di \cmd{ld.so}.
+avvio, usando il programma \cmd{ld-linux.so}.  Questo programma prima carica
+le librerie condivise che servono al programma, poi effettua il link dinamico
+del codice e alla fine lo esegue. Infatti, a meno di non aver specificato il
+flag \texttt{-static} durante la compilazione, tutti i programmi in Linux sono
+incompleti e necessitano di essere linkati alle librerie condivise quando
+vengono avviati.  La procedura è controllata da alcune variabili di ambiente e
+dal contenuto di \file{/etc/ld.so.conf}. I dettagli sono riportati nella man
+page di \cmd{ld.so}.
 
 Il sistema fa partire qualunque programma chiamando la funzione \func{main};
 sta al programmatore chiamare così la funzione principale del programma da cui
@@ -130,7 +130,7 @@ prototipo della funzione 
   Causa la conclusione ordinaria del programma restituendo il valore
   \var{status} al processo padre.
 
-  La funzione non ritorna. Il processo viene terminato
+  \bodydesc{La funzione non ritorna. Il processo viene terminato.}
 \end{prototype}
 
 La funzione \func{exit} è pensata per una conclusione pulita di un programma
@@ -149,10 +149,10 @@ prototipo della funzione 
   Causa la conclusione immediata del programma restituendo il valore
   \var{status} al processo padre.
 
-  La funzione non ritorna. Il processo viene terminato.
+  \bodydesc{La funzione non ritorna. Il processo viene terminato.}
 \end{prototype}
 
-La funzione chiude tutti i file descriptor appartenenti al processo (sui tenga
+La funzione chiude tutti i file descriptor appartenenti al processo (si tenga
 presente che questo non comporta il salvataggio dei dati bufferizzati degli
 stream), fa si che ogni figlio del processo sia ereditato da \cmd{init}
 (vedi \secref{cha:process_handling}), manda un segnale \macro{SIGCHLD} al
@@ -181,11 +181,11 @@ certo numero funzioni che verranno eseguite all'uscita dal programma (sia per
 la chiamata ad \func{exit} che per il ritorno di \func{main}). La prima
 funzione che si può utilizzare a tal fine è:
 \begin{prototype}{stdlib.h}{void atexit(void (*function)(void))}
-  Registra la funzione \var{function} per essere chiamata all'uscita dal
+  Registra la funzione \param{function} per essere chiamata all'uscita dal
   programma. 
-
-  La funzione restituisce 0 in caso di successo e -1 in caso di fallimento,
-  \texttt{errno} non viene settata.
+  
+  \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+    fallimento, \var{errno} non viene settata.}
 \end{prototype}
 
 La funzione richiede come argomento l'indirizzo della opportuna da chiamare
@@ -198,9 +198,9 @@ sistemi), il cui prototipo 
   Registra la funzione \var{function} per essere chiamata all'uscita dal
   programma. Tutte le funzioni registrate vengono chiamate in ordine inverso
   rispetto a quello di registrazione.
-
-  La funzione restituisce 0 in caso di successo e -1 in caso di fallimento,
-  \var{errno} non viene settata.
+  
+  \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+    fallimento, \var{errno} non viene settata.}
 \end{prototype}
 
 In questo caso la funzione da chiamare prende due parametri, il primo dei
@@ -233,7 +233,7 @@ Lo schema delle modalit
 
 \begin{figure}[htb]
   \centering
-  \includegraphics[width=12cm]{img/proc_beginend.eps}
+  \includegraphics[width=12cm]{img/proc_beginend}
   \caption{Schema dell'avvio e della conclusione di un programma.}
   \label{fig:proc_prog_start_stop}
 \end{figure}
@@ -390,7 +390,7 @@ programma C viene suddiviso nei seguenti segmenti:
 
 \begin{figure}[htb]
   \centering
-  \includegraphics[width=5cm]{img/memory_layout.eps}
+  \includegraphics[width=5cm]{img/memory_layout}
   \caption{Disposizione tipica dei segmenti di memoria di un processo}
   \label{fig:proc_mem_layout}
 \end{figure}
@@ -563,13 +563,13 @@ segmento di stack della funzione corrente. La sintassi 
   di successo e \macro{NULL} in caso di fallimento, nel qual caso
   \var{errno} viene settata a \macro{ENOMEM}.
 \end{prototype}
-ma in questo caso non è più necessario liberare la memoria in quanto questa
-viene rilasciata automaticamente al ritorno della funzione.
+\noindent ma in questo caso non è più necessario liberare la memoria in quanto
+questa viene rilasciata automaticamente al ritorno della funzione.
 
 Come è evidente questa funzione ha molti vantaggi, e permette di evitare i
 problemi di memory leak non essendo più necessaria la deallocazione esplicita;
 una delle ragioni principali per usarla è però che funziona anche quando si
-usa \func{longjump} per uscire con un salto non locale da una funzione (vedi
+usa \func{longjmp} per uscire con un salto non locale da una funzione (vedi
 \secref{sec:proc_longjmp}),
 
 Un altro vantaggio e che in Linux la funzione è molto veloce e non viene
@@ -600,21 +600,23 @@ avere con le variabili automatiche, su cui torneremo in
 L'uso di queste funzioni è necessario solo quando si voglia accedere alle
 analoghe system call a cui fanno da interfaccia (ad esempio per implementare
 una propria versione di \func{malloc}. Le funzioni sono:
-\begin{prototype}{unistd.h}{int *brk(void end\_data\_segment)}
+\begin{functions}
+  \headdecl{unistd.h}
+  \funcdecl{int brk(void *end\_data\_segment)}
   Sposta la fine del segmento dei dati all'indirizzo specificato da
   \var{end\_data\_segment}.
   
-  La funzione restituisce 0 in caso di successo e -1 in caso di fallimento,
-  nel qual caso \var{errno} viene settata a \macro{ENOMEM}.
-\end{prototype}
-\begin{prototype}{unistd.h}{int *sbrk(ptrdiff\_t increment)}
-  Incrementa lo spazio dati di un programma di \var{increment}. Un valore
-  zero restituisce l'attuale posizione della fine del segmento dati.
+  La funzione restituisce 0 in caso di successo e -1 in caso di
+    fallimento, nel qual caso \var{errno} viene settata a \macro{ENOMEM}.
+
+  \funcdecl{void *sbrk(ptrdiff\_t increment)} Incrementa lo spazio dati di un
+  programma di \var{increment}. Un valore zero restituisce l'attuale posizione
+  della fine del segmento dati.
   
   La funzione restituisce il puntatore all'inizio della nuova zona di memoria
   allocata in caso di successo e \macro{NULL} in caso di fallimento, nel qual
   caso \macro{errno} viene settata a \macro{ENOMEM}.
-\end{prototype}
+\end{functions}
 
 Queste funzioni sono state deliberatamente escluse dallo standard POSIX.1 e
 per i programmi normali è opportuno usare le funzioni di allocazione standard
@@ -707,28 +709,21 @@ Le funzioni per bloccare e sbloccare singole sezioni di memoria sono
   \var{len} byte. Tutte le pagine che contengono una parte dell'intervallo
   sono mantenute in RAM per tutta la durata del blocco.
 
-  La funzione ritorna 0 in caso di successo e -1 in caso di errore, nel qual
-  caso \var{errno} è settata ad uno dei valori seguenti:
-  \begin{errlist}
-  \item \macro{ENOMEM} alcuni indirizzi dell'intervallo specificato non
-    corripondono allo spazio di indirizzi del processo o si è ecceduto il
-    numero massimo consentito di pagine bloccate.
-  \item \macro{EPERM} il processo non ha i privilegi richiesti per
-    l'operazione. 
-  \item \macro{EINVAL} \var{len} non è un valore positivo.
-  \end{errlist}
-  
   \funcdecl{int munlock(const void *addr, size\_t len)}
-  Alloca \var{size} byte nello heap. La memoria non viene inizializzata.
+  Sblocca l'intervallo di memoria da \var{addr} per \var{len} byte.  
 
-  Sblocca l'intervallo di memoria da \var{addr} per \var{len} byte.  La
-  funzione ritorna 0 in caso di successo e -1 in caso di errore, nel qual caso
-  \var{errno} è settata ad uno dei valori seguenti:
+  
+  \bodydesc{Entrambe le funzioni ritornano 0 in caso di successo e -1 in
+    caso di errore, nel qual caso \var{errno} è settata ad uno dei
+    valori seguenti:
   \begin{errlist}
-  \item \macro{ENOMEM} alcuni indirizzi dell'intervallo specificato non
-    corripondono allo spazio di indirizzi del processo.
-  \item \macro{EINVAL} \var{len} non è un valore positivo.
+  \item[\macro{ENOMEM}] alcuni indirizzi dell'intervallo specificato non
+    corrispondono allo spazio di indirizzi del processo o si è ecceduto
+    il numero massimo consentito di pagine bloccate.
+  \item[\macro{EINVAL}] \var{len} non è un valore positivo.
   \end{errlist}
+  e, per \func{mlock}, anche \macro{EPERM} quando il processo non ha i
+  privilegi richiesti per l'operazione.}
 \end{functions}
 
 Altre due funzioni, \func{mlockall} e \func{munlockall}, consentono di
@@ -741,23 +736,22 @@ queste funzioni sono:
   \funcdecl{int mlockall(int flags)}
   Blocca la paginazione per lo spazio di indirizzi del processo corrente. 
   
-  Codici di ritorno ed errori sono gli stessi di \func{mlock}.
-
   \funcdecl{int munlockall(void)}
   Sblocca la paginazione per lo spazio di indirizzi del processo corrente. 
   
-  Codici di ritorno ed errori sono gli stessi di \func{munlock}.
+  \bodydesc{Codici di ritorno ed errori sono gli stessi di \func{mlock}
+    e \func{munlock}.}
 \end{functions}
 
 Il parametro \var{flags} di \func{mlockall} permette di controllarne il
 comportamento; esso può essere specificato come l'OR aritmetico delle due
 costanti: 
-\begin{description*}
-\item \macro{MCL\_CURRENT} blocca tutte le pagine correntemente mappate nello
+\begin{basedescript}{\desclabelwidth{2.5cm}}
+\item[\macro{MCL\_CURRENT}] blocca tutte le pagine correntemente mappate nello
   spazio di indirizzi del processo.
-\item \macro{MCL\_FUTURE} blocca tutte le pagine che saranno mappate nello
+\item[\macro{MCL\_FUTURE}] blocca tutte le pagine che saranno mappate nello
   spazio di indirizzi del processo.
-\end{description*}
+\end{basedescript}
 
 Con \func{mlockall} si può bloccare tutte le pagine mappate nello spazio di
 indirizzi del processo, sia che comprendano il segmento di testi, di dati, lo
@@ -816,12 +810,12 @@ Per gestire le opzioni all'interno dei argomenti a linea di comando passati in
 che ha il seguente prototipo:
 \begin{prototype}{unistd.h}
 {int getopt(int argc, char * const argv[], const char * optstring)}
-La funzione esegue il parsing degli argomenti passati da linea di comando
+Esegue il parsing degli argomenti passati da linea di comando
 riconoscendo le possibili opzioni segnalate con \var{optstring}.
 
-Ritorna il carattere che segue l'opzione, \cmd{':'} se manca un parametro
-all'opzione, \cmd{'?'} se l'opzione è sconosciuta, e -1 se non esistono altre
-opzioni.
+\bodydesc{Ritorna il carattere che segue l'opzione, \cmd{':'} se manca un
+  parametro all'opzione, \cmd{'?'} se l'opzione è sconosciuta, e -1 se non
+  esistono altre opzioni.}
 \end{prototype}
 
 Questa funzione prende come argomenti le due variabili \var{argc} e \var{argv}
@@ -845,7 +839,7 @@ ritornato il carattere \texttt{':'}, infine se viene incontrato il valore
 \cmd{--} la scansione viene considerata conclusa, anche se vi sono altri
 elementi di \var{argv} che cominciano con il carattere \texttt{'-'}.
 
-\begin{figure}[htbp]
+\begin{figure}[htb]
   \footnotesize
     \begin{lstlisting}{}
     opterr = 0;  /* don't want writing to stderr */
@@ -960,7 +954,7 @@ un esempio del contenuto dell'ambiente, in si 
 variabili che normalmente sono definite dal sistema, è riportato in \nfig.
 \begin{figure}[htb]
   \centering
-  \includegraphics[width=11cm]{img/environ_var.eps}
+  \includegraphics[width=11cm]{img/environ_var}
   \caption{Esempio di lista delle variabili di ambiente.}
   \label{fig:proc_envirno_list}
 \end{figure}
@@ -968,7 +962,7 @@ variabili che normalmente sono definite dal sistema, 
 Per convenzione le stringhe che definiscono l'ambiente sono tutte del tipo
 \textsl{\texttt{nome=valore}}. Inoltre alcune variabili, come quelle elencate
 in \curfig, sono definite dal sistema per essere usate da diversi programmi e
-funzioni: per queste c'è l'ulteriore convezione di usare nomi espressi in
+funzioni: per queste c'è l'ulteriore convenzione di usare nomi espressi in
 caratteri maiuscoli.
 
 Il kernel non usa mai queste variabili, il loro uso e la loro interpretazione è
@@ -986,9 +980,138 @@ l'editor preferito da invocare in caso di necessit
 
 Gli standard POSIX e XPG3 definiscono alcune di queste variabili (le più
 comuni), come riportato in \ntab. GNU/Linux le supporta tutte e ne definisce
-anche altre: per una lista parziale si può controllare \cmd{man environ}.
+anche altre: per una lista più completa si può controllare \cmd{man environ}.
+
+\begin{table}[htb]
+  \centering
+  \begin{tabular}[c]{|l|c|c|c|p{7cm}|}
+    \hline
+    \textbf{Variabile} & \textbf{POSIX} & \textbf{XPG3} 
+    & \textbf{Linux} & \textbf{Descrizione} \\
+    \hline
+    \hline
+    \macro{USER} & $\bullet$ & $\bullet$ & $\bullet$ & Nome utente\\
+    \macro{LOGNAME} & $\bullet$ & $\bullet$ & $\bullet$ & Nome utente\\
+    \macro{HOME} & $\bullet$ & $\bullet$ & $\bullet$ & 
+    Directory base dell'utente\\
+    \macro{LANG} & $\bullet$ & $\bullet$ & $\bullet$ & Localizzazione\\
+    \macro{PATH} & $\bullet$ & $\bullet$ & $\bullet$ & Elenco delle directory
+    dei programmi\\
+    \macro{PWD} & $\bullet$ & $\bullet$ & $\bullet$ & Directory corrente\\
+    \macro{SHELL} & $\bullet$ & $\bullet$ & $\bullet$ & Shell in uso\\
+    \macro{TERM} & $\bullet$ & $\bullet$ & $\bullet$ & Tipo di terminale\\
+    \macro{PAGER} & $\bullet$ & $\bullet$ & $\bullet$ & Programma per vedere i
+    testi\\
+    \macro{EDITOR} & $\bullet$ & $\bullet$ & $\bullet$ & Editor di default\\
+    \macro{BROWSER} & $\bullet$ & $\bullet$ & $\bullet$ & Browser di default\\
+    \hline
+  \end{tabular}
+  \caption{Variabile di ambiente più comuni definite da vari standard}
+  \label{tab:proc_env_var}
+\end{table}
+
+Lo standard ANSI C, pur non entrando nelle specifiche di come sono strutturati
+i contenuti, definisce la funzione \func{getenv} che permette di ottenere i
+valori delle variabili di ambiente, il suo prototipo è:
+\begin{prototype}{stdlib.h}{char *getenv(const char *name)}
+  Esamina l'ambiente del processo cercando una stringa che corrisponda a
+  quella specificata da \param{name}. 
+  
+  \bodydesc{La funzione ritorna \macro{NULL} se non trova nulla, o il
+    puntatore alla stringa che corrisponde (di solito nella forma
+    \texttt{NOME=valore}).}
+\end{prototype}
+
+Oltre a questa funzione di lettura, che è l'unica definita dallo standard ANSI
+C, in seguito sono state proposte altre da utilizzare per settare e per
+cancellare le variabili di ambiente presenti; uno schema delle funzioni
+previste nei vari standard unix e disponibili in Linux è riportato in \ntab.
 
+\begin{table}[htb]
+  \centering
+  \begin{tabular}[c]{|l|c|c|c|c|c|c|}
+    \hline
+    \textbf{Funzione} & \textbf{ANSI C} & \textbf{POSIX.1} & \textbf{XPG3} & 
+    \textbf{SVr4} & \textbf{BSD} & \textbf{Linux} \\
+    \hline
+    \hline
+    \func{getenv} & $\bullet$ &  $\bullet$ & $\bullet$ & 
+      $\bullet$ & $\bullet$ & $\bullet$ \\
+    \func{setenv} &   &   &    & 
+        & $\bullet$ & $\bullet$ \\
+    \func{unsetenv} &  &   &    & 
+        & $\bullet$ & $\bullet$ \\
+    \func{putenv} &  & opz.  & $\bullet$ & 
+        & $\bullet$ & $\bullet$ \\
+    \func{clearenv} &  & opz.  &    & 
+        &  &  \\
+    \hline
+  \end{tabular}
+  \caption{Funzioni per la gestione delle variabili di ambiente.}
+  \label{tab:proc_env_func}
+\end{table}
+
+In Linux solo le prime quattro funzioni di \curtab\ sono definite; delle tre
+restanti le prime due, \func{putenv} e \func{setenv} servono per assegnare
+nuove variabili di ambiente, i loro prototipi sono i seguenti:
+\begin{functions}
+  \headdecl{stdlib.h} 
+  
+  \funcdecl{int putenv(char *string)} Aggiunge la stringa \param{string}
+  all'ambiente.
+  
+  \funcdecl{int setenv(const char *name, const char *value, int overwrite)}
+  Setta la variabile di ambiente \param{name} al valore \param{value}.
+  
+  \bodydesc{Entrambe le funzioni ritornano 0 in caso di successo e -1 per un
+    errore, che è sempre \macro{ENOMEM}.}
+\end{functions}
+\noindent la terza è:
+\begin{functions}
+  \headdecl{stdlib.h}
+  
+  \funcdecl{void unsetenv(const char *name)}
+  Rimuove la variabile di ambiente \param{name}.  
+\end{functions}
 
+Per cancellare una variabile di ambiente si usa \func{unsetenv}, che elimina
+ogni occorrenza della variabile, se la variabile specificata non esiste non
+succede nulla, e non è previsto (dato che la funzione è \type{void}) nessuna
+segnalazione di errore. 
+
+Per modificare o aggiungere una variabile di ambiente si possono usare le
+funzioni \func{setenv} e \func{putenv}. La prima permette di specificare
+separatamente nome e valore della variabile di ambiente, inoltre il valore di
+\param{overwrite} specifica il comportamento della funzione nel caso la
+variabile esista già, sovrascrivendola se diverso da zero, lasciandola
+immutata se uguale a zero.
+
+La seconda funzione prende come parametro una stringa analoga quella
+restituita da \func{getenv}, e sempre nella forma \texttt{NOME=valore}. Se la
+variabile specificata non esiste la stringa sarà aggiunta all'ambiente, se
+invece esiste il suo valore sarà settato a quello specificato da
+\func{string}. Si tenga presente che, seguendo lo standard SUSv2, le
+\acr{glibc} successive alla versione 2.1.2 aggiungono\footnote{il
+  comportamento è lo stesso delle vecchie \acr{libc4} e \acr{libc5}; nelle
+  \acr{glibc}, dalla versione 2.0 alla 2.1.1, veniva invece fatta una copia,
+  seguendo il comportamento di BSD4.4; dato che questo può dar luogo a perdite
+  di memoria e non rispetta lo standard il comportamento è stato modificato a
+  partire dalle 2.1.2, eliminando anche, sempre in conformità a SUSv2,
+  l'attributo \type{const} dal prototipo.} \func{string} alla lista delle
+variabili di ambiente; pertanto ogni cambiamento alla stringa in questione si
+riflette automaticamente sull'ambiente, e quindi si deve evitare di passare
+alla funzione variabili automatiche (per evitare i problemi esposti in
+\secref{sec:proc_auto_var}).
+
+Si tenga infine presente che se si passa a \func{putenv} solo il nome di una
+variabile (cioè \param{string} è nella forma \texttt{NAME} e non contiene un
+\var{=}) allora questa viene cancellata dall'ambiente. Infine se la chiamata
+di \func{putenv} comporta la necessità di allocare una nuova versione del
+vettore \var{environ} questo sarà allocato, ma la versione corrente sarà
+deallocata solo se anch'essa risultante da una allocazione fatta in precedenza
+da un'altra \func{putenv}, il vettore originale (in genere piazzato al di
+sopra dello stack, vedi \figref{fig:proc_mem_layout}), o la memoria associata
+alle variabili di ambiente eliminate non viene comunque liberata.
 
 
 \section{Problematiche di programmazione generica}
@@ -1044,6 +1167,17 @@ informazioni sulle dimensioni delle strutture degli indirizzi utilizzate,
 viene usato questo meccanismo.
 
 
+\subsection{Il passaggio di un numero variabile di argomenti}
+\label{sec:proc_variadic}
+
+Come vedremo nei capitoli successivi, non sempre è possibile specificare
+un numero fisso di parametri per una funzione.  Lo standard ISO C
+prevede la possibilità di definire delle \textit{varadic function} che
+abbiano un numero variabile di argomenti, ma non provvede nessun
+meccanismo con cui queste funzioni possono accedere a questi argomenti.
+
+(NdT il resto è da fare).
+
 \subsection{Potenziali problemi con le variabili automatiche}
 \label{sec:proc_auto_var}
 
@@ -1072,6 +1206,39 @@ efficiente, quello dell'uscita in caso di errore.
 
 Il C però non consente di effettuare un salto ad una label definita in
 un'altra funzione, per cui se l'errore avviene in funzioni profondamente
-annidate occorre usare la funzione \func{longjump}. 
+annidate occorre usare quello che viene chiamato un salto \textsl{non-locale};
+questo viene fatto usando salvando il contesto dello stack nel punto in cui si
+vuole tornare in caso di errore, e ripristinandolo quando l'occorrenza capita.
 
 
+La funzione che permette di salvare il contesto dello stack è \func{setjmp},
+il cui prototipo è:
+
+\begin{functions}
+  \headdecl{setjmp.h}
+  \funcdecl{void setjmp(jmp\_buf env)}
+  
+  Salva il contesto dello stack in \param{env} per un successivo uso da parte
+  di \func{longjmp}. Il contesto viene invalidato se la routine che ha
+  chiamato \func{setjmp} ritorna.
+  
+  \bodydesc{La funzione ritorna zero quando è chiamata direttamente e un
+    valore diverso da zero quando ritorna da una chiamata di \func{longjmp}
+    che usa il contesto salvato in precedenza.}
+\end{functions}
+
+
+Per poter effettuare un salto non locale si usa la funzione \func{longjmp}; il
+suo prototipo è:
+\begin{functions}
+  \headdecl{setjmp.h}
+  \funcdecl{void longjmp(jmp\_buf env, int val)}
+  
+  Ripristina il contesto dello stack salvato dall'ultima chiamata di
+  \func{setjmp} con l'argomento \param{env}. Il programma prosegue dal ritorno
+  di \func{setjmp} con un valore \param{val}. Il valore di \param{val} deve
+  essere diverso da zero, se viene specificato 0 sarà usato 1 al suo posto.
+
+  \bodydesc{La funzione non ritorna.}
+\end{functions}
+