Risistemati i prototipi delle funzioni, adesso dovrebbero essere un
[gapil.git] / prochand.tex
index c9e4e156feda9fe814caf0bd04beb171ef61b093..8c8a67190e98a67d4502897f1611bf83bb8e8a40 100644 (file)
@@ -8,16 +8,20 @@ base per l'allocazione e l'uso delle risorse del sistema.
 Nel precedente capitolo abbiamo visto come funziona un singolo processo, in
 questo capitolo affronteremo i dettagli della creazione e della distruzione
 dei processi, della gestione dei loro attributi e privilegi, e di tutte le
-funzioni a questo connesse.
+funzioni a questo connesse. Infine nella sezione finale affronteremo alcune
+problematiche generiche della programmazione in ambiente multitasking.
+
 
 
 \section{Introduzione}
 \label{sec:proc_gen}
 
 Partiremo con una introduzione generale ai concetti che stanno alla base della
-gestione dei processi in unix. Introdurremo in questa sezione l'architettura
-della gestione dei processi e le sue principali caratteristiche, e daremo una
-panoramica sull'uso delle principali funzioni per la gestione dei processi.
+gestione dei processi in un sistema unix-like. Introdurremo in questa sezione
+l'architettura della gestione dei processi e le sue principali
+caratteristiche, e daremo una panoramica sull'uso delle principali funzioni
+per la gestione dei processi.
+
 
 \subsection{La gerarchia dei processi}
 \label{sec:proc_hierarchy}
@@ -30,35 +34,35 @@ qualunque processo pu
 numero unico, il cosiddetto \textit{process identifier} o, più brevemente, 
 \acr{pid}.
 
-Una seconda caratteristica è che la generazione di un processo è una
-operazione separata rispetto al lancio di un programma. In genere la sequenza
-è sempre quella di creare un nuovo processo, il quale eseguirà, in un passo
-successivo, il programma voluto: questo è ad esempio quello che fa la shell
-quando mette in esecuzione il programma che gli indichiamo nella linea di
-comando.
-
-Una terza caratteristica è che ogni processo viene sempre generato da un altro
-che viene chiamato processo padre (\textit{parent process}). Questo vale per
-tutti i processi, con una sola eccezione: dato che ci deve essere un punto di
-partenza esiste sempre un processo speciale (che normalmente è
+Una seconda caratteristica di un sistema unix è che la generazione di un
+processo è una operazione separata rispetto al lancio di un programma. In
+genere la sequenza è sempre quella di creare un nuovo processo, il quale
+eseguirà, in un passo successivo, il programma voluto: questo è ad esempio
+quello che fa la shell quando mette in esecuzione il programma che gli
+indichiamo nella linea di comando.
+
+Una terza caratteristica è che ogni processo è sempre stato generato da un
+altro, che viene chiamato processo padre (\textit{parent process}). Questo
+vale per tutti i processi, con una sola eccezione: dato che ci deve essere un
+punto di partenza esiste un processo speciale (che normalmente è
 \cmd{/sbin/init}), che viene lanciato dal kernel alla conclusione della fase
-di avvio, essendo questo il primo processo lanciato dal sistema ha sempre il
+di avvio; essendo questo il primo processo lanciato dal sistema ha sempre il
 \acr{pid} uguale a 1 e non è figlio di nessun altro processo.
 
 Ovviamente \cmd{init} è un processo speciale che in genere si occupa di far
 partire tutti gli altri processi necessari al funzionamento del sistema,
 inoltre \cmd{init} è essenziale per svolgere una serie di compiti
-amministrativi nelle operazioni ordinarie del sistema (torneremo si alcuni di
+amministrativi nelle operazioni ordinarie del sistema (torneremo su alcuni di
 essi in \secref{sec:proc_termination}) e non può mai essere terminato. La
 struttura del sistema comunque consente di lanciare al posto di \cmd{init}
-qualunque altro programma (e in casi di emergenza, ad esempio se il file di
-\cmd{init} si fosse corrotto, è ad esempio possibile lanciare una shell al suo
-posto, passando la riga \cmd{init=/bin/sh} come parametro di avvio).
+qualunque altro programma, e in casi di emergenza (ad esempio se il file di
+\cmd{init} si fosse corrotto) è ad esempio possibile lanciare una shell al suo
+posto, passando la riga \cmd{init=/bin/sh} come parametro di avvio.
 
 \begin{figure}[!htb]
   \footnotesize
 \begin{verbatim}
-[piccardi@selidor piccardi]$ pstree -n 
+[piccardi@gont piccardi]$ pstree -n 
 init-+-keventd
      |-kapm-idled
      |-kreiserfsd
@@ -103,7 +107,7 @@ Dato che tutti i processi attivi nel sistema sono comunque generati da
   kernel, (come \cmd{keventd}, \cmd{kswapd}, etc.)} si possono classificare i
 processi con la relazione padre/figlio in una organizzazione gerarchica ad
 albero, in maniera analoga a come i file sono organizzati in un albero di
-directory (si veda \secref{sec:file_file_struct}); in \nfig\ si è mostrato il
+directory (si veda \secref{sec:file_file_struct}); in \curfig\ si è mostrato il
 risultato del comando \cmd{pstree} che permette di mostrare questa struttura,
 alla cui base c'è \cmd{init} che è progenitore di tutti gli altri processi.
 
@@ -186,12 +190,13 @@ ottenuti da programma usando le funzioni:
 \begin{functions}
 \headdecl{sys/types.h}
 \headdecl{unistd.h}
-\funcdecl{pid\_t getpid(void)} restituisce il pid del processo corrente.
-\funcdecl{pid\_t getppid(void)} restituisce il pid del padre del processo
+\funcdecl{pid\_t getpid(void)} Restituisce il pid del processo corrente.
+\funcdecl{pid\_t getppid(void)} Restituisce il pid del padre del processo
     corrente.
-Entrambe le funzioni non riportano condizioni di errore. 
+
+\bodydesc{Entrambe le funzioni non riportano condizioni di errore.}
 \end{functions}
-esempi dell'uso di queste funzioni sono riportati in
+\noindent esempi dell'uso di queste funzioni sono riportati in
 \figref{fig:proc_fork_code}, nel programma di esempio \file{ForkTest.c}.
 
 Il fatto che il \acr{pid} sia un numero univoco per il sistema lo rende il
@@ -205,10 +210,17 @@ Tutti i processi figli dello stesso processo padre sono detti
 \textit{sibling}, questa è una delle relazioni usate nel \textsl{controllo di
   sessione}, in cui si raggruppano i processi creati su uno stesso terminale,
 o relativi allo stesso login. Torneremo su questo argomento in dettaglio in
-\secref{cap:session}, dove esamineremo i vari identificativi associati ad un
-processo e le varie relazioni fra processi utilizzate per definire una
+\secref{cha:session}, dove esamineremo gli altri identificativi associati ad
+un processo e le varie relazioni fra processi utilizzate per definire una
 sessione.
 
+Oltre al \acr{pid} e al \acr{ppid}, e a quelli usati per il controllo di
+sessione, ad ogni processo sono associati altri identificatori, usati per il
+controllo di accesso, che servono per determinare se il processo può o meno
+eseguire le operazioni richieste, a seconda dei privilegi e dell'identità di
+chi lo ha posto in esecuzione; su questi torneremo in dettagli più avanti in
+\secref{sec:proc_perms}.
+
 
 \subsection{La funzione \func{fork}}
 \label{sec:proc_fork}
@@ -218,21 +230,22 @@ processi: come si 
 attraverso l'uso di questa funzione, essa quindi riveste un ruolo centrale
 tutte le volte che si devono scrivere programmi che usano il multitasking.  Il
 prototipo della funzione è:
-
 \begin{functions}
   \headdecl{sys/types.h} 
   \headdecl{unistd.h} 
   \funcdecl{pid\_t fork(void)} 
-  Restituisce zero al padre e il \acr{pid} al figlio in caso di successo,
-  ritorna -1 al padre (senza creare il figlio) in caso di errore;
-  \texttt{errno} può assumere i valori:
+  Crea un nuovo processo.
+  
+  \bodydesc{Restituisce zero al padre e il \acr{pid} al figlio in caso di
+    successo, ritorna -1 al padre (senza creare il figlio) in caso di errore;
+    \var{errno} può assumere i valori:
   \begin{errlist}
-  \item \macro{EAGAIN} non ci sono risorse sufficienti per creare un'altro
+  \item[\macro{EAGAIN}] non ci sono risorse sufficienti per creare un'altro
     processo (per allocare la tabella delle pagine e le strutture del task) o
     si è esaurito il numero di processi disponibili.
-  \item \macro{ENOMEM} non è stato possibile allocare la memoria per le
+  \item[\macro{ENOMEM}] non è stato possibile allocare la memoria per le
     strutture necessarie al kernel per creare il nuovo processo.
-  \end{errlist}
+  \end{errlist}}
 \end{functions}
 
 Dopo il successo dell'esecuzione di una \func{fork} sia il processo padre che
@@ -368,6 +381,8 @@ periodo di attesa.
 Se eseguiamo il comando senza specificare attese (come si può notare in
 \texttt{\small 17--19} i valori di default specificano di non attendere),
 otterremo come output sul terminale:
+
+\footnotesize
 \begin{verbatim}
 [piccardi@selidor sources]$ ./forktest 3
 Process 1963: forking 3 child
@@ -384,6 +399,7 @@ Child 3, parent 1963, exiting
 Spawned 3 child, pid 1966 
 Go to next child 
 \end{verbatim} %$
+\normalsize
 
 Esaminiamo questo risultato: una prima conclusione che si può trarre è non si
 può dire quale processo fra il padre ed il figlio venga eseguito per
@@ -422,6 +438,8 @@ Un secondo aspetto molto importante nella creazione dei processi figli 
 quello dell'interazione dei vari processi con i file; per illustrarlo meglio
 proviamo a redirigere su un file l'output del nostro programma di test, quello
 che otterremo è:
+
+\footnotesize
 \begin{verbatim}
 [piccardi@selidor sources]$ ./forktest 3 > output
 [piccardi@selidor sources]$ cat output
@@ -448,6 +466,7 @@ Go to next child
 Spawned 3 child, pid 1970 
 Go to next child 
 \end{verbatim}
+\normalsize
 che come si vede è completamente diverso da quanto ottenevamo sul terminale.
 
 Il comportamento delle varie funzioni di interfaccia con i file è analizzato
@@ -481,10 +500,9 @@ Quello che succede 
 lo stesso avviene anche per tutti i figli; la funzione \func{fork} infatti ha
 la caratteristica di duplicare (allo stesso modo in cui lo fa la funzione
 \func{dup}, trattata in \secref{sec:file_dup}) nei figli tutti i file
-descriptor aperti nel padre, il che comporta che padre e figli condividono
-le stesse voci della file table (per la spiegazione di questi termini si veda
-\secref{sec:file_sharing} e referenza a figura da fare) e quindi anche
-l'offset corrente nel file.
+descriptor aperti nel padre, il che comporta che padre e figli condividono le
+stesse voci della file table (per la spiegazione di questi termini si veda
+\secref{sec:file_sharing}) e quindi anche l'offset corrente nel file.
 
 In questo modo se un processo scrive sul file aggiornerà l'offset sulla file
 table, e tutti gli altri processi che condividono la file table vedranno il
@@ -518,37 +536,41 @@ sequenza impredicibile. Le modalit
 \end{enumerate}
 
 Oltre ai file aperti i processi figli ereditano dal padre una serie di altre
-proprietà comuni; in dettaglio avremo che dopo l'esecuzione di una \func{fork}
-padre e figlio avranno in comune:
-\begin{itemize}
-\item i file aperti (e gli eventuali flag di \textit{close-on-exec} se
-  settati).
+proprietà; la lista dettagliata delle proprietà che padre e figlio hanno in
+comune dopo l'esecuzione di una \func{fork} è la seguente:
+\begin{itemize*}
+\item i file aperti e gli eventuali flag di \textit{close-on-exec} (vedi
+\secref{sec:proc_exec} e \secref{sec:file_fcntl}) se settati.
 \item gli identificatori per il controllo di accesso: il \textit{real user
     id}, il \textit{real group id}, l'\textit{effective user id},
   l'\textit{effective group id} e i \textit{supplementary group id} (vedi
-  \secref{tab:proc_uid_gid}).
+  \secref{sec:proc_user_group}).
 \item gli identificatori per il controllo di sessione: il \textit{process
-    group id} e il \textit{session id} e il terminale di controllo.
-\item i flag \acr{suid} e \acr{suid} (vedi \secref{sec:file_suid_sgid}).
+    group id} e il \textit{session id} e il terminale di controllo (vedi
+  \secref{sec:sess_xxx} e \secref{sec:sess_xxx}).
+\item i flag di \acr{suid} e \acr{sgid} (vedi \secref{sec:file_suid_sgid}).
 \item la directory di lavoro e la directory radice (vedi
   \secref{sec:file_work_dir}).
 \item la maschera dei permessi di creazione (vedi \secref{sec:file_umask}).
-\item la maschera dei segnali.
-\item i segmenti di memoria condivisa agganciati al processo. 
-\item i limiti sulle risorse
+\item la maschera dei segnali bloccati e le azioni installate  (vedi
+\secref{sec:sig_xxx}).
+\item i segmenti di memoria condivisa agganciati al processo (vedi
+\secref{sec:ipc_xxx}). 
+\item i limiti sulle risorse (vedi  \secref{sec:sys_xxx}).
 \item le variabili di ambiente (vedi \secref{sec:proc_environ}).
-\end{itemize}
-le differenze invece sono:
-\begin{itemize}
+\end{itemize*}
+le differenze fra padre e figlio dopo la \func{fork} invece sono:
+\begin{itemize*}
 \item il valore di ritorno di \func{fork}.
 \item il \textit{process id}. 
 \item il \textit{parent process id} (quello del figlio viene settato al
   \acr{pid} del padre).
-\item i valori dei tempi di esecuzione (\var{tms\_utime}, \var{tms\_stime},
-  \var{tms\_cutime}, \var{tms\_uetime}) che nel figlio sono posti a zero.
-\item i \textit{file lock}, che non vengono ereditati dal figlio.
-\item gli allarmi pendenti, che per il figlio vengono cancellati.
-\end{itemize}
+\item i valori dei tempi di esecuzione (vedi \secref{sec:sys_xxx}) che
+  nel figlio sono posti a zero.
+\item i \textit{file lock} (vedi \secref{sec:file_locking}), che non
+  vengono ereditati dal figlio.
+\item gli allarmi ed i segnali pendenti (vedi \secref{sec:sig_xxx}), che per il figlio vengono cancellati.
+\end{itemize*}
 
 
 \subsection{La funzione \func{vfork}}
@@ -601,18 +623,20 @@ Qualunque sia la modalit
 comunque una serie di operazioni: chiude tutti i file aperti, rilascia la
 memoria che stava usando, e così via; l'elenco completo delle operazioni
 eseguite alla chiusura di un processo è il seguente:
-\begin{itemize}
+\begin{itemize*}
 \item tutti i descrittori dei file sono chiusi.
 \item viene memorizzato lo stato di terminazione del processo.
 \item ad ogni processo figlio viene assegnato un nuovo padre.
-\item viene inviato il segnale \macro{SIGCHLD} al processo padre.
+\item viene inviato il segnale \macro{SIGCHLD} al processo padre (vedi
+  \secref{sec:sig_xxx}) .
 \item se il processo è un leader di sessione viene mandato un segnale di
-  \macro{SIGHUP} a tutti i processi in background e il terminale di controllo
-  viene disconnesso.
-\item se la conclusione di un processe rende orfano un \textit{process group}
-  ciascun membro del gruppo viene bloccato, e poi gli vengono inviati in
-  successione i segnali \macro{SIGHUP} e \macro{SIGCONT}.
-\end{itemize}
+  \macro{SIGHUP} a tutti i processi in background e il terminale di
+  controllo viene disconnesso (vedi \secref{sec:sess_xxx}).
+\item se la conclusione di un processo rende orfano un \textit{process
+    group} ciascun membro del gruppo viene bloccato, e poi gli vengono
+  inviati in successione i segnali \macro{SIGHUP} e \macro{SIGCONT}
+  (vedi \secref{sec:sess_xxx}).
+\end{itemize*}
 ma al di la di queste operazioni è necessario poter disporre di un meccanismo
 ulteriore che consenta di sapere come questa terminazione è avvenuta; dato che
 in un sistema unix-like tutto viene gestito attraverso i processi il
@@ -620,7 +644,7 @@ meccanismo scelto consiste nel riportare lo stato di terminazione
 (\textit{termination status}) di cui sopra al processo padre.
 
 Nel caso di conclusione normale, lo stato di uscita del processo viene
-caratterizzato tremite il valore del cosiddetto \textit{exit status}, cioè il
+caratterizzato tramite il valore del cosiddetto \textit{exit status}, cioè il
 valore passato alle funzioni \func{exit} o \func{\_exit} (o dal valore di
 ritorno per \func{main}).  Ma se il processo viene concluso in maniera anomala
 il programma non può specificare nessun \textit{exit status}, ed è il kernel
@@ -637,7 +661,7 @@ secondo.
 La scelta di riportare al padre lo stato di terminazione dei figli, pur
 essendo l'unica possibile, comporta comunque alcune complicazioni: infatti se
 alla sua creazione è scontato che ogni nuovo processo ha un padre, non è detto
-che sia così alla sua conclusione, dato che il padre protrebbe essere già
+che sia così alla sua conclusione, dato che il padre potrebbe essere già
 terminato (si potrebbe avere cioè quello che si chiama un processo
 \textsl{orfano}). 
 
@@ -650,6 +674,8 @@ avr
 di terminazione.  Come verifica di questo comportamento possiamo eseguire il
 comando \cmd{forktest} imponendo a ciascun processo figlio due
 secondi di attesa prima di uscire, il risultato è:
+
+\footnotesize
 \begin{verbatim}
 [piccardi@selidor sources]$ ./forktest -c2 3
 Process 1972: forking 3 child
@@ -666,6 +692,7 @@ Go to next child
 Child 2, parent 1, exiting
 Child 1, parent 1, exiting
 \end{verbatim}
+\normalsize
 come si può notare in questo caso il processo padre si conclude prima dei
 figli, tornando alla shell, che stampa il prompt sul terminale: circa due
 secondi dopo viene stampato a video anche l'output dei tre figli che
@@ -679,14 +706,14 @@ informazioni riguardo ai processi che sta terminando.
 
 Questo viene fatto mantenendo attiva la voce nella tabella dei processi, e
 memorizzando alcuni dati essenziali, come il \acr{pid}, i tempi di CPU usati
-dal processo (vedi \secref{sec:intro_unix_time}) e lo stato di terminazione
+dal processo (vedi \secref{sec:sys_unix_time}) e lo stato di terminazione
 \footnote{NdA verificare esattamente cosa c'è!}, mentre la memoria in uso ed i
 file aperti vengono rilasciati immediatamente. I processi che sono terminati,
 ma il cui stato di terminazione non è stato ancora ricevuto dal padre sono
 chiamati \textit{zombie}, essi restano presenti nella tabella dei processi ed
 in genere possono essere identificati dall'output di \cmd{ps} per la presenza
 di una \cmd{Z} nella colonna che ne indica lo stato. Quando il padre
-effettuarà la lettura dello stato di uscita anche questa informazione, non più
+effettuerà la lettura dello stato di uscita anche questa informazione, non più
 necessaria, verrà scartata e la terminazione potrà dirsi completamente
 conclusa.
 
@@ -695,6 +722,8 @@ condizione: lanciamo il comando \cmd{forktest} in background, indicando al
 processo padre di aspettare 10 secondi prima di uscire; in questo caso, usando
 \cmd{ps} sullo stesso terminale (prima dello scadere dei 10 secondi)
 otterremo:
+
+\footnotesize
 \begin{verbatim}
 [piccardi@selidor sources]$ ps T
   PID TTY      STAT   TIME COMMAND
@@ -705,6 +734,7 @@ otterremo:
   571 pts/0    Z      0:00 [forktest <defunct>]
   572 pts/0    R      0:00 ps T
 \end{verbatim} %$
+\normalsize 
 e come si vede, dato che non si è fatto nulla per riceverne lo stato di
 terminazione, i tre processi figli sono ancora presenti pur essendosi
 conclusi, con lo stato di zombie e l'indicazione che sono stati terminati.
@@ -734,7 +764,7 @@ di terminare il processo che li ha generati, in modo che \cmd{init} possa
 adottarli e provvedere a concludere la terminazione.
 
 
-\subsection{Le funzioni \texttt{wait} e  \texttt{waitpid}}
+\subsection{Le funzioni \func{wait} e  \func{waitpid}}
 \label{sec:proc_wait}
 
 Abbiamo già accennato come uno degli usi possibili delle capacità multitasking
@@ -752,28 +782,33 @@ prototipo 
 \funcdecl{pid\_t wait(int * status)} 
 
 Sospende il processo corrente finché un figlio non è uscito, o finché un
-segnale termina il processo o chiama una funzione di gestione. Se un figlio è
-già uscito la funzione ritorna immediatamente. Al ritorno lo stato di
-termininazione del processo viene salvato nella variabile puntata da
-\var{status} e tutte le informazioni relative al processo (vedi
-\secref{sec:proc_termination}) vengono rilasciate.
+segnale termina il processo o chiama una funzione di gestione. 
 
+\bodydesc{
 La funzione restituisce il \acr{pid} del figlio in caso di successo e -1 in
 caso di errore; \var{errno} può assumere i valori:
   \begin{errlist}
-  \item \macro{EINTR} la funzione è stata interrotta da un segnale.
+  \item[\macro{EINTR}] la funzione è stata interrotta da un segnale.
   \end{errlist}
+}
 \end{functions}
+\noindent
 è presente fin dalle prime versioni di unix; la funzione ritorna alla
-conclusione del primo figlio (o immediatamente se un figlio è già uscito). Nel
-caso un processo abbia più figli il valore di ritorno permette di identificare
-qual'è quello che è uscito.
-
-Questa funzione però ha il difetto di essere poco flessibile, in quanto
-ritorna all'uscita di un figlio qualunque. Nelle occasioni in cui è necessario
-attendere la conclusione di un processo specifico occorre predisporre un
-meccanismo che tenga conto dei processi già terminati, e ripeta la chiamata
-alla funzione nel caso il processo cercato sia ancora attivo.
+conclusione del primo figlio (o immediatamente se un figlio è già
+uscito). Se un figlio è già uscito la funzione ritorna immediatamente.
+
+Al ritorno lo stato di termininazione del processo viene salvato nella
+variabile puntata da \var{status} e tutte le informazioni relative al
+processo (vedi \secref{sec:proc_termination}) vengono rilasciate.  Nel
+caso un processo abbia più figli il valore di ritorno permette di
+identificare qual'è quello che è uscito.
+
+Questa funzione ha il difetto di essere poco flessibile, in quanto
+ritorna all'uscita di un figlio qualunque. Nelle occasioni in cui è
+necessario attendere la conclusione di un processo specifico occorre
+predisporre un meccanismo che tenga conto dei processi già terminati, e
+provveda a ripetere la chiamata alla funzione nel caso il processo
+cercato sia ancora attivo.
 
 Per questo motivo lo standard POSIX.1 ha introdotto la funzione \func{waitpid}
 che effettua lo stesso servizio, ma dispone di una serie di funzionalità più
@@ -784,16 +819,17 @@ questa funzione; il suo prototipo 
 \headdecl{sys/types.h}
 \headdecl{sys/wait.h}
 \funcdecl{pid\_t waitpid(pid\_t pid, int * status, int options)} 
+Attende la conclusione di un processo figlio.
 
-La funzione restituisce il \acr{pid} del processo che è uscito, 0 se è stata
-specificata l'opzione \macro{WNOHANG} e il processo non è uscito e -1 per un
-errore, nel qual caso \var{errno} assumerà i valori:
+\bodydesc{La funzione restituisce il \acr{pid} del processo che è uscito, 0 se
+  è stata specificata l'opzione \macro{WNOHANG} e il processo non è uscito e
+  -1 per un errore, nel qual caso \var{errno} assumerà i valori:
   \begin{errlist}
-  \item \macro{EINTR} se non è stata specificata l'opzione \macro{WNOHANG} e
+  \item[\macro{EINTR}] se non è stata specificata l'opzione \macro{WNOHANG} e
     la funzione è stata interrotta da un segnale.
-  \item \macro{ECHILD} il processo specificato da \var{pid} non esiste o non è
+  \item[\macro{ECHILD}] il processo specificato da \var{pid} non esiste o non è
     figlio del processo chiamante.
-  \end{errlist}
+  \end{errlist}}
 \end{functions}
 
 Le differenze principali fra le due funzioni sono che \func{wait} si blocca
@@ -804,6 +840,7 @@ base del valore specificato tramite la variabile \var{pid}, secondo lo
 specchietto riportato in \ntab:
 \begin{table}[!htb]
   \centering
+  \footnotesize
   \begin{tabular}[c]{|c|p{10cm}|}
     \hline
     \textbf{Valore} & \textbf{Significato}\\
@@ -831,7 +868,7 @@ processo figlio non 
 di sessione, trattato in \capref{cha:session}) che fa ritornare la funzione
 anche per i processi figli che sono bloccati ed il cui stato non è stato
 ancora riportato al padre. Il valore dell'opzione deve essere specificato come
-mashera binaria ottenuta con l'OR delle suddette costanti con zero.
+maschera binaria ottenuta con l'OR delle suddette costanti con zero.
 
 La terminazione di un processo figlio è chiaramente un evento asincrono
 rispetto all'esecuzione di un programma e può avvenire in un qualunque
@@ -852,6 +889,7 @@ certezza che la chiamata a \func{wait} non si bloccher
 
 \begin{table}[!htb]
   \centering
+  \footnotesize
   \begin{tabular}[c]{|c|p{10cm}|}
     \hline
     \textbf{Macro} & \textbf{Descrizione}\\
@@ -862,16 +900,16 @@ certezza che la chiamata a \func{wait} non si bloccher
     \macro{WEXITSTATUS(s)} & Restituisce gli otto bit meno significativi dello
     stato di uscita del processo (passato attraverso \func{\_exit}, \func{exit}
     o come valore di ritorno di \func{main}). Può essere valutata solo se
-    \macro{WIFEXITED} ha restitituito un valore non nullo.\\
+    \macro{WIFEXITED} ha restituito un valore non nullo.\\
     \macro{WIFSIGNALED(s)} & Vera se il processo figlio è terminato
     in maniera anomala a causa di un segnale che non è stato catturato (vedi
     \secref{sec:sig_notification}).\\
     \macro{WTERMSIG(s)}    & restituisce il numero del segnale che ha causato
     la terminazione anomala del processo.  Può essere valutata solo se
-    \macro{WIFSIGNALED} ha restitituito un valore non nullo.\\
+    \macro{WIFSIGNALED} ha restituito un valore non nullo.\\
     \macro{WCOREDUMP(s)}   & Vera se il processo terminato ha generato un
     file si \textit{core dump}. Può essere valutata solo se
-    \macro{WIFSIGNALED} ha restitituito un valore non nullo\footnote{questa
+    \macro{WIFSIGNALED} ha restituito un valore non nullo\footnote{questa
     macro non è definita dallo standard POSIX.1, ma è presente come estensione
     sia in Linux che in altri unix}.\\
     \macro{WIFSTOPPED(s)}  & Vera se il processo che ha causato il ritorno di
@@ -879,7 +917,7 @@ certezza che la chiamata a \func{wait} non si bloccher
     l'opzione \macro{WUNTRACED}. \\
     \macro{WSTOPSIG(s)}    & restituisce il numero del segnale che ha bloccato
     il processo, Può essere valutata solo se \macro{WIFSTOPPED} ha
-    restitituito un valore non nullo. \\
+    restituito un valore non nullo. \\
     \hline
   \end{tabular}
   \caption{Descrizione delle varie macro di preprocessore utilizzabili per 
@@ -887,7 +925,6 @@ certezza che la chiamata a \func{wait} non si bloccher
   \label{tab:proc_status_macro}
 \end{table}
 
-
 Entrambe le funzioni restituiscono lo stato di terminazione del processo
 tramite il puntatore \var{status} (se non interessa memorizzare lo stato si
 può passare un puntatore nullo). Il valore restituito da entrambe le funzioni
@@ -908,14 +945,16 @@ Si tenga conto che nel caso di conclusione anomala il valore restituito da
 \file{signal.h}, e stampato usando le funzioni definite in
 \secref{sec:sig_strsignal}.
 
+
+\subsection{Le funzioni \func{wait3} e \func{wait4}}
+\label{sec:proc_wait4}
+
 Linux, seguendo una estensione di BSD, supporta altre due funzioni per la
 lettura dello stato di terminazione di un processo, analoghe a \func{wait} e
 \func{waitpid}, ma che prevedono un ulteriore parametro attraverso il quale il
 kernel può restituire al processo padre ulteriori informazioni sulle risorse
-usate dal processo terminato e dai vari figli. 
-Queste funzioni diventano accessibili definendo la costante \macro{\_USE\_BSD}
-sono:
-
+usate dal processo terminato e dai vari figli.  Queste funzioni, che diventano
+accessibili definendo la costante \macro{\_USE\_BSD}, sono:
 \begin{functions}
   \headdecl{sys/times.h} 
   \headdecl{sys/types.h} 
@@ -923,16 +962,17 @@ sono:
   \headdecl{sys/resource.h}
   \funcdecl{pid\_t wait4(pid\_t pid, int * status, int options, struct rusage
     * rusage)} 
-  La funzione è identica a \func{waitpid} sia per comportamento che per i
+  È identica a \func{waitpid} sia per comportamento che per i
   valori dei parametri, ma restituisce in \var{rusage} un sommario delle
-  risorse usate dal processo (per i dettagli vedi \secref{sec:xxx_limit_res})
-  \funcdecl{pid\_t wait3(int *status, int options, struct rusage *rusage)}  
-  Prima versione, equivalente a \func{wait4(-1, \&status, opt, rusage)} ormai
-  deprecata in favore di \func{wait4}.
+  risorse usate dal processo (per i dettagli vedi \secref{sec:sys_xxx})
+  \funcdecl{pid\_t wait3(int *status, int options, struct rusage *rusage)}
+  Prima versione, equivalente a \func{wait4(-1, \&status, opt, rusage)} è
+  ormai deprecata in favore di \func{wait4}.
 \end{functions}
+\noindent 
 la struttura \type{rusage} è definita in \file{sys/resource.h}, e viene
 utilizzata anche dalla funzione \func{getrusage} per ottenere le risorse di
-sistema usate dal processo; in Linux è definita come:
+sistema usate dal processo; la sua definizione è riportata in \nfig.
 \begin{figure}[!htb]
   \footnotesize
   \centering
@@ -959,18 +999,20 @@ struct rusage {
     \end{lstlisting}
   \end{minipage} 
   \normalsize 
-  \caption{La struttura \texttt{rusage} per la lettura delle informazioni dei 
+  \caption{La struttura \var{rusage} per la lettura delle informazioni dei 
     delle risorse usate da un processo.}
   \label{fig:proc_rusage_struct}
 \end{figure}
-In genere includere esplicitamente \file{<sys/time.h>} non è più necessario,
-ma aumenta la portabiltà, e serve in caso si debba accedere ai campi di
-\var{rusage} definiti come \type{struct timeval}. La struttura è ripresa dalla
-versione 4.3 Reno di BSD, attualmente (con il kernel 2.4.x) i soli campi che
-sono mantenuti sono: \var{ru\_utime}, \var{ru\_stime}, \var{ru\_minflt},
-\var{ru\_majflt}, e \var{ru\_nswap}.
-
-\subsection{Le funzioni \texttt{exec}}
+
+In genere includere esplicitamente \file{<sys/time.h>} non è più
+necessario, ma aumenta la portabilità, e serve in caso si debba accedere
+ai campi di \var{rusage} definiti come \type{struct timeval}. La
+struttura è ripresa da BSD 4.3, attualmente (con il kernel 2.4.x) i soli
+campi che sono mantenuti sono: \var{ru\_utime}, \var{ru\_stime},
+\var{ru\_minflt}, \var{ru\_majflt}, e \var{ru\_nswap}.
+
+
+\subsection{Le funzioni \func{exec}}
 \label{sec:proc_exec}
 
 Abbiamo già detto che una delle modalità principali con cui si utilizzano i
@@ -986,44 +1028,45 @@ Ci sono sei diverse versioni di \func{exec} (per questo la si 
 famiglia di funzioni) che possono essere usate per questo compito, che in
 realtà (come mostrato in \figref{fig:proc_exec_relat}), costituiscono un
 front-end a \func{execve}. Il prototipo  di quest'ultima è:
-
 \begin{prototype}{unistd.h}
 {int execve(const char * filename, char * const argv [], char * const envp[])}
+  Esegue il programma contenuto nel file \param{filename}.
   
-  La funzione esegue il file o lo script indicato da \var{filename},
-  passandogli la lista di argomenti indicata da \var{argv} e come ambiente la
-  lista di stringhe indicata da \var{envp}; entrambe le liste devono essere
-  terminate da un puntatore nullo. I vettori degli argomenti e dell'ambiente
-  possono essere acceduti dal nuovo programma quando la sua funzione
-  \func{main} è dichiarata nella forma \func{main(int argc, char *argv[], char
-    *envp[])}.
-
-  La funzione ritorna -1 solo in caso di errore, nel qual caso caso la
-  variabile \texttt{errno} è settata come:
+  \bodydesc{La funzione ritorna -1 solo in caso di errore, nel qual caso
+    caso la \var{errno} può assumere i valori:
   \begin{errlist}
-  \item \macro{EACCES} il file non è eseguibile, oppure il filesystem è
+  \item[\macro{EACCES}] il file non è eseguibile, oppure il filesystem è
     montato in \cmd{noexec}, oppure non è un file normale o un interprete.
-  \item \macro{EPERM} il file ha i bit \acr{suid} o \acr{sgid} ma l'utente non
+  \item[\macro{EPERM}] il file ha i bit \acr{suid} o \acr{sgid} ma l'utente non
     è root o il filesystem è montato con \cmd{nosuid}, oppure
-  \item \macro{ENOEXEC} il file è in un formato non eseguibile o non
+  \item[\macro{ENOEXEC}] il file è in un formato non eseguibile o non
     riconosciuto come tale, o compilato per un'altra architettura.
-  \item \macro{ENOENT} il file o una delle librerie dinamiche o l'inteprete
+  \item[\macro{ENOENT}] il file o una delle librerie dinamiche o l'interprete
     necessari per eseguirlo non esistono.
-  \item \macro{ETXTBSY} L'eseguibile è aperto in scrittura da uno o più
+  \item[\macro{ETXTBSY}] L'eseguibile è aperto in scrittura da uno o più
     processi. 
-  \item \macro{EINVAL} L'eseguibile ELF ha più di un segmento
-    \macro{PF\_INTERP}, cioè chiede di essere eseguito da più di un interprete.
-  \item \macro{ELIBBAD} Un interprete ELF non è in un formato  riconoscibile.
+  \item[\macro{EINVAL}] L'eseguibile ELF ha più di un segmento
+    \macro{PF\_INTERP}, cioè chiede di essere eseguito da più di un
+    interprete.
+  \item[\macro{ELIBBAD}] Un interprete ELF non è in un formato
+    riconoscibile.
   \end{errlist}
   ed inoltre anche \macro{EFAULT}, \macro{ENOMEM}, \macro{EIO},
   \macro{ENAMETOOLONG}, \macro{E2BIG}, \macro{ELOOP}, \macro{ENOTDIR},
-  \macro{ENFILE}, \macro{EMFILE}.
+  \macro{ENFILE}, \macro{EMFILE}.}
 \end{prototype}
 
+La funzione \func{exec} esegue il file o lo script indicato da
+\var{filename}, passandogli la lista di argomenti indicata da \var{argv}
+e come ambiente la lista di stringhe indicata da \var{envp}; entrambe le
+liste devono essere terminate da un puntatore nullo. I vettori degli
+argomenti e dell'ambiente possono essere acceduti dal nuovo programma
+quando la sua funzione \func{main} è dichiarata nella forma
+\func{main(int argc, char *argv[], char *envp[])}.
+
 Le altre funzioni della famiglia servono per fornire all'utente una serie
 possibile di diverse interfacce per la creazione di un nuovo processo. I loro
 prototipi sono:
-
 \begin{functions}
 \headdecl{unistd.h}
 \funcdecl{int execl(const char *path, const char *arg, ...)} 
@@ -1037,9 +1080,9 @@ Sostituiscono l'immagine corrente del processo con quella indicata nel primo
 argomento. I parametri successivi consentono di specificare gli argomenti a
 linea di comando e l'ambiente ricevuti dal nuovo processo.
 
-Queste funzioni ritornano solo in caso di errore, restituendo -1; nel qual
-caso \var{errno} andrà ad assumere i valori visti in precedenza per
-\func{execve}.
+\bodydesc{Queste funzioni ritornano solo in caso di errore, restituendo
+  -1; nel qual caso \var{errno} andrà ad assumere i valori visti in
+  precedenza per \func{execve}.}
 \end{functions}
 
 Per capire meglio le differenze fra le funzioni della famiglia si può fare
@@ -1063,7 +1106,6 @@ che deve essere terminata da un puntatore nullo.  In entrambi i casi vale la
 convenzione che il primo argomento (\var{arg0} o \var{argv[0]}) viene usato
 per indicare il nome del file che contiene il programma che verrà eseguito.
 
-
 \begin{table}[!htb]
   \footnotesize
   \centering
@@ -1093,120 +1135,638 @@ per indicare il nome del file che contiene il programma che verr
 
 La seconda differenza fra le funzioni riguarda le modalità con cui si
 specifica il programma che si vuole eseguire. Con lo mnemonico \func{p} si
-indicano le due funzioni che necessitano del \textit{pathname} assoluto del
-programma come valore del parametro \var{path}. Le altre quattro funzioni
-invece usano come parametro \var{file} un nome che viene cercato
-automaticamente fra i file presenti nella lista di directory specificate dalla
-variabile di ambiente \var{PATH}.
-
-
-La terza differenza è .
-
+indicano le due funzioni che replicano il comportamento della shell nello
+specificare il comando da eseguire; quando il parametro \var{file} non
+contiene una \file{/} esso viene considerato come un nome di programma, e
+viene eseguita automaticamente una ricerca fra i file presenti nella lista di
+directory specificate dalla variabile di ambiente \var{PATH}. Il file che
+viene posto in esecuzione è il primo che viene trovato. Se si ha un errore di
+permessi negati (cioè l'esecuzione della sottostante \func{execve} ritorna un
+\macro{EACCESS}), la ricerca viene proseguita nelle eventuali ulteriori
+directory indicate nel \var{PATH}, solo se non viene trovato nessun altro file
+viene finalmente restituito \macro{EACCESS}.
+
+Le altre quattro funzioni si limitano invece a cercare di eseguire il file
+indicato dal parametro \var{path}, che viene interpretato come il
+\textit{pathname} del programma.
+
+\begin{figure}[htb]
+  \centering
+  \includegraphics[width=13cm]{img/exec_rel}
+  \caption{La interrelazione fra le sei funzioni della famiglia \func{exec}}
+  \label{fig:proc_exec_relat}
+\end{figure}
 
+La terza differenza è come viene passata la lista delle variabili di ambiente.
+Con lo mnemonico \func{e} vengono indicate quelle funzioni che necessitano di
+un vettore di parametri \var{envp[]} analogo a quello usato per gli argomenti
+a riga di comando (terminato quindi da un \macro{NULL}), le altre usano il
+valore della variabile \var{environ} (vedi \secref{sec:proc_environ}) del
+processo di partenza per costruire l'ambiente.
+
+Oltre a mantenere lo stesso \acr{pid}, il nuovo programma fatto partire da
+\func{exec} assume anche una serie di altre proprietà del processo chiamante;
+la lista completa è la seguente:
+\begin{itemize*}
+\item il \textit{process ID} (\acr{pid}) ed il \textit{parent process ID}
+  (\acr{ppid}).
+\item il \textit{real user ID} ed il \textit{real group ID} (vedi
+  \secref{sec:proc_user_group}).
+\item i \textit{supplementary group ID} (vedi \secref{sec:proc_user_group}).
+\item il \textit{session ID} ed il \textit{process group ID} (vedi
+  \secref{sec:sess_xxx}).
+\item il terminale di controllo (vedi \secref{sec:sess_xxx}).
+\item il tempo restante ad un allarme.
+\item la directory radice e la directory di lavoro corrente (vedi
+  \secref{sec:file_work_dir}).
+\item la maschera di creazione dei file (\var{umask}, vedi
+  \secref{sec:file_umask}) ed i \textit{lock} sui file (vedi
+  \secref{sec:file_locking}).
+\item i segnali sospesi (\textit{pending}) e la maschera dei segnali (si veda
+  \secref{sec:sig_xxx}).
+\item i limiti sulle risorse (vedi \secref{sec:sys_limits})..
+\item i valori delle variabili \var{tms\_utime}, \var{tms\_stime},
+  \var{tms\_cutime}, \var{tms\_ustime} (vedi \secref{sec:xxx_xxx}).
+\end{itemize*}
+
+Oltre a questo i segnali che sono stati settati per essere ignorati nel
+processo chiamante mantengono lo stesso settaggio pure nel nuovo programma,
+tutti gli altri segnali vengono settati alla loro azione di default. Un caso
+speciale è il segnale \macro{SIGCHLD} che, quando settato a \macro{SIG\_IGN},
+può anche non essere resettato a \macro{SIG\_DFL} (si veda
+\secref{sec:sig_xxx}).
+
+La gestione dei file aperti dipende dal valore del flag di
+\textit{close-on-exec} per ciascun file descriptor (si veda
+\secref{sec:file_fcntl}); i file per cui è settato vengono chiusi, tutti gli
+altri file restano aperti. Questo significa che il comportamento di default è
+che i file restano aperti attraverso una \func{exec}, a meno di una chiamata
+esplicita a \func{fcntl} che setti il suddetto flag.
+
+Per le directory lo standard POSIX.1 richiede che esse vengano chiuse
+attraverso una \func{exec}, in genere questo è fatto dalla funzione
+\func{opendir} che effettua da sola il settaggio del flag di
+\textit{close-on-exec} sulle directory che apre, in maniera trasparente
+all'utente.
+
+Abbiamo detto che il \textit{real user ID} ed il \textit{real group ID}
+restano gli stessi all'esecuzione di \func{exec}; lo stesso vale per
+l'\textit{effective user ID} ed l'\textit{effective group ID}, tranne il caso
+in cui il file che si va ad eseguire ha o il \acr{suid} bit o lo \acr{sgid}
+bit settato, nel qual caso \textit{effective user ID} e \textit{effective
+  group ID} vengono settati rispettivamente all'utente o al gruppo cui il file
+appartiene (per i dettagli vedi \secref{sec:proc_perms}).
+
+Se il file da eseguire è in formato \emph{a.out} e necessita di librerie
+condivise, viene lanciato il \textit{linker} dinamico \cmd{ld.so} prima del
+programma per caricare le librerie necessarie ed effettuare il link
+dell'eseguibile. Se il programma è in formato ELF per caricare le librerie
+dinamiche viene usato l'interprete indicato nel segmento \macro{PT\_INTERP},
+in genere questo è \file{/lib/ld-linux.so.1} per programmi linkati con le
+\emph{libc5}, e \file{/lib/ld-linux.so.2} per programmi linkati con le
+\emph{glibc}. Infine nel caso il file sia uno script esso deve iniziare con
+una linea nella forma \cmd{\#!/path/to/interpreter} dove l'interprete indicato
+deve esse un valido programma (binario, non un altro script) che verrà
+chiamato come se si fosse eseguito il comando \cmd{interpreter [arg]
+  filename}.
 
 Con la famiglia delle \func{exec} si chiude il novero delle funzioni su cui è
-basato il controllo dei processi in unix: con \func{fork} si crea un nuovo
+basata la gestione dei processi in unix: con \func{fork} si crea un nuovo
 processo, con \func{exec} si avvia un nuovo programma, con \func{exit} e
-\func{wait} si effettua e si gestisce la conclusione dei programmi. Tutte le
+\func{wait} si effettua e verifica la conclusione dei programmi. Tutte le
 altre funzioni sono ausiliarie e servono la lettura e il settaggio dei vari
 parametri connessi ai processi.
 
 
+
 \section{Il controllo di accesso}
 \label{sec:proc_perms}
 
 In questa sezione esamineremo le problematiche relative al controllo di
-accesso dal punto di vista del processi; gli identificativi usati, come questi
-vengono modificati nella creazione e nel lancio di nuovi processi, e le varie
-funzioni per la loro manipolazione diretta.
+accesso dal punto di vista del processi; vedremo quali sono gli identificatori
+usati, come questi possono essere modificati nella creazione e nel lancio di
+nuovi processi, e le varie funzioni per la loro manipolazione diretta e tutte
+le problematiche connesse alla gestione accorta dei privilegi.
 
 
 \subsection{Utente e gruppo di un processo}
 \label{sec:proc_user_group}
 
-Abbiamo già accennato in \secref{sec:intro_multiuser} ad ogni utente ed gruppo
-sono associati due identificatori univoci, lo \acr{uid} e il \acr{gid} che li
-contraddistinguono nei confronti del kernel. Questi identificatori stanno alla
-base del sistema di permessi e protezioni di un sistema unix, e vengono usati
-anche nella gestione dei privilegi di accesso dei processi.
-
-In realtà ad ogni processo è associato un certo numero di identificatori, il
-cui elenco è riportato \ntab, in genere questi derivano direttamente
-dall'utente che ha lanciato il processo (attraverso i valori di \acr{uid} e
-\acr{gid}), e vengono usati sia per il controllo di accesso ai file che per la
-gestione dei privilegi associati ai processi stessi.
+Come accennato in \secref{sec:intro_multiuser} il modello base\footnote{in
+  realtà già esistono estensioni di questo modello base, che lo rendono più
+  flessibile e controllabile, come le \textit{capabilities}, le ACL per i file
+  o il \textit{Mandatory Access Control} di SELinux} di sicurezza di un
+sistema unix-like è fondato sui concetti di utente e gruppo, e sulla
+separazione fra l'amministratore (\textsl{root}, detto spesso anche
+\textit{superuser}) che non è sottoposto a restrizioni, ed il resto degli
+utenti, per i quali invece vengono effettuati i vari controlli di accesso.
+
+%Benché il sistema sia piuttosto semplice (è basato su un solo livello di
+% separazione) il sistema permette una
+%notevole flessibilità, 
+
+Abbiamo già accennato come il sistema associ ad ogni utente e gruppo due
+identificatori univoci, lo \acr{uid} e il \acr{gid}; questi servono al kernel
+per identificare uno specifico utente o un gruppo di utenti, per poi poter
+controllare che essi siano autorizzati a compiere le operazioni richieste.  Ad
+esempio in \secref{sec:file_access_control} vedremo come ad ogni file vengano
+associati un utente ed un gruppo (i suoi \textsl{proprietari}, indicati
+appunto tramite un \acr{uid} ed un \acr{gid}) che vengono controllati dal
+kernel nella gestione dei permessi di accesso.
+
+Dato che tutte le operazioni del sistema vengono compiute dai processi, è
+evidente che per poter implementare un controllo sulle operazioni occorre
+anche poter identificare chi è che ha lanciato un certo processo, e pertanto
+anche a ciascuno di essi è associato un utente e a un gruppo. 
+
+Un semplice controllo di una corrispondenza fra identificativi però non
+garantisce però sufficiente flessibilità per tutti quei casi in cui è
+necessario poter disporre di privilegi diversi, o dover impersonare un altro
+utente per un limitato insieme di operazioni. Per questo motivo in generale
+tutti gli unix prevedono che i processi abbiano almeno due gruppi di
+identificatori, chiamati rispettivamente \textit{real} ed \textit{effective}.
+
 \begin{table}[htb]
   \footnotesize
   \centering
-  \begin{tabular}[c]{|c|l|p{8cm}|}
+  \begin{tabular}[c]{|c|l|p{6.5cm}|}
     \hline
-    \textbf{Sigla} & \textbf{Significato} & \textbf{Utilizzo} \\ 
+    \textbf{Suffisso} & \textbf{Significato} & \textbf{Utilizzo} \\ 
     \hline
     \hline
-    \acr{ruid} & \textit{real user id} & indica l'utente reale che ha lanciato
+    \acr{uid}   & \textit{real user id} & indica l'utente che ha lanciato
     il programma\\ 
-    \acr{rgid} & \textit{real group id} & indica il gruppo reale dell'utente 
+    \acr{gid}   & \textit{real group id} & indica il gruppo dell'utente 
     che ha lanciato il programma \\ 
-    \acr{euid} & \textit{effective user id} & indica l'utente effettivo usato
-    dal programma \\ 
-    \acr{egid} & \textit{effective group id} & indica il gruppo effettivo usato
-    dal programma \\ 
-               & \textit{supplementary group id} & indica i gruppi cui
+    \acr{euid}  & \textit{effective user id} & indica l'utente usato
+    dal programma nel controllo di accesso \\ 
+    \acr{egid}  & \textit{effective group id} & indica il gruppo 
+    usato dal programma  nel controllo di accesso \\ 
+    --          & \textit{supplementary group id} & indica i gruppi cui
     l'utente appartiene  \\ 
-    \acr{suid} & \textit{saved user id} & indica l'utente  \\ 
-    \acr{sgid} & \textit{daved group id} & indica il gruppo  \\ 
+    --          & \textit{saved user id} &  copia dell'\acr{euid} iniziale\\ 
+    --          & \textit{saved group id} &  copia dell'\acr{egid} iniziale \\ 
     \acr{fsuid} & \textit{filesystem user id} & indica l'utente effettivo per
     il filesystem \\ 
     \acr{fsgid} & \textit{filesystem group id} & indica il gruppo effettivo
     per il filesystem  \\ 
     \hline
   \end{tabular}
-  \caption{Identificatori di utente e gruppo associati a ciascun processo.}
+  \caption{Identificatori di utente e gruppo associati a ciascun processo con
+    indicazione dei suffissi usate dalle varie funzioni di manipolazione.}
   \label{tab:proc_uid_gid}
 \end{table}
 
-Il \textit{real user id} e il \textit{real group id} indicano l'utente che ha
-lanciato il processo, e vengono settati al login al valore standard di
-\acr{uid} e \acr{gid} dell'utente letti direttamente da \file{/etc/passwd}.
-Questi non vengono mai cambiati nella creazione di nuovi processi e restano
-sempre gli stessi per tutti i processi avviati in una sessione. In realtà è
-possibile modificarli (vedi \secref{sec:proc_setuid}), ma solo per un processo
-che abbia i privilegi di amministratore (ed è così infatti che \cmd{login},
-che gira con i privilegi di amministratore, li setta ai valori corrispondenti
-all'utente che entra nel sistema).
-
-L'\textit{effective user id}, l'\textit{effective group id} e gli eventuali
-\textit{supplementary group id} sono gli identificativi usati per il controllo
-di accesso ai file secondo quanto descritto in dettaglio in
-\secref{sec:file_perm_overview}. Normalmente sono uguali al \textit{real user
-  id} e al \textit{real group id}, a meno che il file posto in esecuzione non
-abbia i bit \acr{suid} o \acr{sgid} settati, nel qual caso vengono settati
-rispettivamente all'\acr{uid} e \acr{gid} del file.
+Al primo gruppo appartengono il \textit{real user ID} e il \textit{real group
+  ID}: questi vengono settati al login ai valori corrispondenti all'utente con
+cui si accede al sistema (e relativo gruppo di default). Servono per
+l'identificazione dell'utente e normalmente non vengono mai cambiati. In
+realtà vedremo (in \secref{sec:proc_setuid}) che è possibile modificarli, ma
+solo ad un processo che abbia i privilegi di amministratore; questa
+possibilità è usata ad esempio da \cmd{login} che una volta completata la
+procedura di autenticazione lancia una shell per la quale setta questi
+identificatori ai valori corrispondenti all'utente che entra nel sistema.
+
+Al secondo gruppo appartengono l'\textit{effective user ID} e
+l'\textit{effective group ID} (a cui si aggiungono gli eventuali
+\textit{supplementary group id} dei gruppi dei quale l'utente fa parte).
+Questi sono invece gli identificatori usati nella verifiche dei permessi del
+processo e per il controllo di accesso ai file (argomento affrontato in
+dettaglio in \secref{sec:file_perm_overview}). 
+
+Questi identificatori normalmente sono identici ai corrispondenti del gruppo
+\textsl{reale} tranne nel caso in cui, come visto in \secref{sec:proc_exec},
+il programma che si è posto in esecuzione abbia i bit \acr{suid} o \acr{sgid}
+settati (il significato di questi bit è affrontato in dettaglio in
+\secref{sec:file_suid_sgid}). In questo caso essi saranno settati all'utente e
+al gruppo proprietari del file; questo consente, per programmi in cui ci sia
+necessità, di dare a qualunque utente normale privilegi o permessi di
+un'altro (o dell'amministratore).
+
+Come nel caso del \acr{pid} e del \acr{ppid} tutti questi identificatori
+possono essere letti dal processo attraverso delle opportune funzioni, i cui
+prototipi sono i seguenti:
+\begin{functions}
+  \headdecl{unistd.h}
+  \headdecl{sys/types.h}  
+  \funcdecl{uid\_t getuid(void)} Restituisce il \textit{real user ID} del
+  processo corrente.
+
+  \funcdecl{uid\_t geteuid(void)} Restituisce l'\textit{effective user ID} del
+  processo corrente.
+
+  \funcdecl{gid\_t getgid(void)} Restituisce il \textit{real group ID} del
+  processo corrente.
+
+  \funcdecl{gid\_t getegid(void)} Restituisce l'\textit{effective group ID} del
+  processo corrente.
+  
+  \bodydesc{Queste funzioni non riportano condizioni di errore.}
+\end{functions}
+
+In generale l'uso di privilegi superiori deve essere limitato il più
+possibile, per evitare abusi e problemi di sicurezza, per questo occorre anche
+un meccanismo che consenta ad un programma di rilasciare gli eventuali
+maggiori privilegi necessari, una volta che si siano effettuate le operazioni
+per i quali erano richiesti, e a poterli eventualmente recuperare in caso
+servano di nuovo.
+
+Questo in Linux viene fatto usando altri due gruppi di identificatori, il
+\textit{saved} ed il \textit{filesystem}, analoghi ai precedenti. Il primo
+gruppo è lo stesso usato in SVr4, e previsto dallo standard POSIX quando è
+definita la costante \macro{\_POSIX\_SAVED\_IDS}\footnote{in caso si abbia a
+  cuore la portabilità del programma su altri unix è buona norma controllare
+  sempre la disponibilità di queste funzioni controllando se questa costante è
+  definita}, il secondo gruppo è specifico di Linux e viene usato per
+migliorare la sicurezza con NFS.
 
 Il \textit{saved user id} e il \textit{saved group id} sono copie
 dell'\textit{effective user id} e dell'\textit{effective group id} del
-processo padre, e vengono settati all'avvio del processo, prima che
-\textit{effective user id} e \textit{effective group id} vengano modificati
-per tener conto di eventuali \acr{suid} o \acr{sgid}.
+processo padre, e vengono settati dalla funzione \func{exec} all'avvio del
+processo, come copie dell'\textit{effective user id} e dell'\textit{effective
+  group id} dopo che questo sono stati settati tenendo conto di eventuali
+\acr{suid} o \acr{sgid}.  Essi quindi consentono di tenere traccia di quale
+fossero utente e gruppo effettivi all'inizio dell'esecuzione di un nuovo
+programma.
+
+Il \textit{filesystem user id} e il \textit{filesystem group id} sono una
+estensione introdotta in Linux per rendere più sicuro l'uso di NFS (torneremo
+sull'argomento in \secref{sec:proc_setfsuid}). Essi sono una replica dei
+corrispondenti \textit{effective id}, ai quali si sostituiscono per tutte le
+operazioni di verifica dei permessi relativi ai file (trattate in
+\secref{sec:file_perm_overview}).  Ogni cambiamento effettuato sugli
+\textit{effective id} viene automaticamente riportato su di essi, per cui in
+condizioni normali se ne può tranquillamente ignorare l'esistenza, in quanto
+saranno del tutto equivalenti ai precedenti.
+
+Uno specchietto riassuntivo, contenente l'elenco completo degli identificatori
+di utente e gruppo associati dal kernel ad ogni processo, è riportato in
+\tabref{tab:proc_uid_gid}.
+
+
+\subsection{Le funzioni \func{setuid} e \func{setgid}}
+\label{sec:proc_setuid}
 
+Le due funzioni che vengono usate per cambiare identità (cioè utente e gruppo
+di appartenenza) ad un processo sono rispettivamente \func{setuid} e
+\func{setgid}; come accennato in \secref{sec:proc_user_group} in Linux esse
+seguono la semantica POSIX che prevede l'esistenza di \textit{saved user id} e
+\textit{saved group id}; i loro prototipi sono:
+\begin{functions}
+\headdecl{unistd.h}
+\headdecl{sys/types.h}
 
-\subsection{Le funzioni \texttt{setuid} e \texttt{setgid}}
-\label{sec:proc_setuid}
+\funcdecl{int setuid(uid\_t uid)} Setta l'\textit{user ID} del processo
+corrente.
+
+\funcdecl{int setgid(gid\_t gid)} Setta il \textit{group ID} del processo
+corrente.
+
+\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
+  di fallimento: l'unico errore possibile è \macro{EPERM}.}
+\end{functions}
+
+Il funzionamento di queste due funzioni è analogo, per cui considereremo solo
+la prima; la seconda si comporta esattamente allo stesso modo facendo
+riferimento al \textit{group id} invece che all'\textit{user id}.  Gli
+eventuali \textit{supplementary group id} non vengono modificati da nessuna
+delle funzioni che tratteremo in questa sezione.
+
+
+L'effetto della chiamata è diverso a seconda dei privilegi del processo; se
+l'\textit{effective user id} è zero (cioè è quello dell'amministratore di
+sistema) allora tutti gli identificatori (\textit{real}, \textit{effective}
+e \textit{saved}) vengono settati al valore specificato da \var{uid},
+altrimenti viene settato solo l'\textit{effective user id}, e soltanto se il
+valore specificato corrisponde o al \textit{real user id} o al \textit{saved
+  user id}. Negli altri casi viene segnalato un errore (con \macro{EPERM}).
+
+Come accennato l'uso principale di queste funzioni è quello di poter
+consentire ad un programma con i bit \acr{suid} o \acr{sgid} settati di
+riportare l'\textit{effective user id} a quello dell'utente che ha lanciato il
+programma, effettuare il lavoro che non necessita di privilegi aggiuntivi, ed
+eventualmente tornare indietro.
+
+Come esempio per chiarire dell'uso di queste funzioni prediamo quello con cui
+viene gestito l'accesso al file \file{/var/log/utmp}.  In questo file viene
+registrato chi sta usando il sistema al momento corrente; chiaramente non può
+essere lasciato aperto in scrittura a qualunque utente, che potrebbe
+falsificare la registrazione. Per questo motivo questo file (e l'analogo
+\file{/var/log/wtmp} su cui vengono registrati login e logout) appartengono ad
+un gruppo dedicato (\acr{utmp}) ed i programmi che devono accedervi (ad
+esempio tutti i programmi di terminale in X, o il programma \cmd{screen}
+che crea terminali multipli su una console) appartengono a questo gruppo ed
+hanno il bit \acr{sgid} settato.
+
+Quando uno di questi programmi (ad esempio \cmd{xterm}) viene lanciato la
+situazione degli identificatori è la seguente:
+\begin{eqnarray*}
+  \label{eq:1}
+  \textit{real group id}      &=& \textrm{\acr{gid} (del chiamante)} \\
+  \textit{effective group id} &=& \textrm{\acr{utmp}} \\
+  \textit{saved group id}     &=& \textrm{\acr{utmp}}
+\end{eqnarray*}
+in questo modo, dato che l'\textit{effective group id} è quello giusto, il
+programma può accedere a \file{/var/log/utmp} in scrittura ed aggiornarlo, a
+questo punto il programma può eseguire una \func{setgid(getgid())} per settare
+l'\textit{effective group id} a quello dell'utente (e dato che il \textit{real
+  group id} corrisponde la funzione avrà successo), in questo modo non sarà
+possibile lanciare dal terminale programmi che modificano detto file, in tal
+caso infatti la situazione degli identificatori sarebbe:
+\begin{eqnarray*}
+  \label{eq:2}
+  \textit{real group id}      &=& \textrm{\acr{gid} (invariato)}  \\
+  \textit{effective group id} &=& \textrm{\acr{gid}} \\
+  \textit{saved group id}     &=& \textrm{\acr{utmp} (invariato)}
+\end{eqnarray*}
+e ogni processo lanciato dal terminale avrebbe comunque \acr{gid} come
+\textit{effective group id}. All'uscita dal terminale, per poter di nuovo
+aggiornare lo stato di \file{/var/log/utmp} il programma eseguirà una
+\func{setgid(utmp)} (dove \var{utmp} è il valore numerico associato al gruppo
+\acr{utmp}, ottenuto ad esempio con una \func{getegid}), dato che in questo
+caso il valore richiesto corrisponde al \textit{saved group id} la funzione
+avrà successo e riporterà la situazione a:
+\begin{eqnarray*}
+  \label{eq:3}
+  \textit{real group id}      &=& \textrm{\acr{gid} (invariato)}  \\
+  \textit{effective group id} &=& \textrm{\acr{utmp}} \\
+  \textit{saved group id}     &=& \textrm{\acr{utmp} (invariato)}
+\end{eqnarray*}
+consentendo l'accesso a \file{/var/log/utmp}.
+
+Occorre però tenere conto che tutto questo non è possibile con un processo con
+i privilegi di root, in tal caso infatti l'esecuzione una \func{setuid}
+comporta il cambiamento di tutti gli identificatori associati al processo,
+rendendo impossibile riguadagnare i privilegi di amministratore.  Questo
+comportamento è corretto per l'uso che ne fa \cmd{login} una volta che crea
+una nuova shell per l'utente; ma quando si vuole cambiare soltanto
+l'\textit{effective user id} del processo per cedere i privilegi occorre
+ricorrere ad altre funzioni (si veda ad esempio \secref{sec:proc_seteuid}).
+
+
+\subsection{Le funzioni \func{setreuid} e \func{setresuid}}
+\label{sec:proc_setreuid}
+
+Queste due funzioni derivano da BSD che non supportando\footnote{almeno fino
+  alla versione 4.3+BSD TODO, verificare e aggiornare la nota} i \textit{saved
+  id} le usava per poter scambiare fra di loro effective e real id. I
+prototipi sono:
+\begin{functions}
+\headdecl{unistd.h}
+\headdecl{sys/types.h}
+
+\funcdecl{int setreuid(uid\_t ruid, uid\_t euid)} Setta il \textit{real user
+  ID} e l'\textit{effective user ID} del processo corrente ai valori
+specificati da \var{ruid} e \var{euid}.
+  
+\funcdecl{int setregid(gid\_t rgid, gid\_t egid)} Setta il \textit{real group
+  ID} e l'\textit{effective group ID} del processo corrente ai valori
+specificati da \var{rgid} e \var{egid}.
+
+\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
+  di fallimento: l'unico errore possibile è \macro{EPERM}.}
+\end{functions}
+
+I processi non privilegiati possono settare i \textit{real id} soltanto ai
+valori dei loro \textit{effective id} o \textit{real id} e gli
+\textit{effective id} ai valori dei loro \textit{real id}, \textit{effective
+  id} o \textit{saved id}; valori diversi comportano il fallimento della
+chiamata; l'amministratore invece può specificare un valore qualunque.
+Specificando un valore di -1 l'identificatore corrispondente viene lasciato
+inalterato.
+
+Con queste funzione si possono scambiare fra loro \textit{real id} e
+\textit{effective id}, e pertanto è possibile implementare un comportamento
+simile a quello visto in precedenza per \func{setgid}, cedendo i privilegi con
+un primo scambio, e recuperandoli, eseguito il lavoro non privilegiato, con un
+secondo scambio.
+
+In questo caso però occorre porre molta attenzione quando si creano nuovi
+processi nella fase intermedia in cui si sono scambiati gli identificatori, in
+questo caso infatti essi avranno un \textit{real id} privilegiato, che dovrà
+essere esplicitamente eliminato prima di porre in esecuzione un nuovo
+programma (occorrerà cioè eseguire un'altra chiamata dopo la \func{fork}, e
+prima della \func{exec} per uniformare i \textit{real id} agli
+\textit{effective id}) in caso contrario quest'ultimo potrebbe a sua volta
+effettuare uno scambio e riottenere privilegi non previsti.
+
+Lo stesso problema di propagazione dei privilegi ad eventuali processi figli
+si porrebbe per i \textit{saved id}. Queste funzioni derivano da
+un'implementazione che non ne prevede la presenza, e quindi non è possibile
+usarle per correggere la situazione come nel caso precedente, per questo
+motivo tutte le volte che uno degli identificatori viene modificato ad un
+valore diverso dal precedente \textit{real id}, il \textit{saved id} viene
+sempre settato al valore dell'\textit{effective id}.
+
+
+\subsection{Le funzioni \func{setresuid} e \func{setresgid}}
+\label{sec:proc_setresuid}
+
+Queste due funzioni sono una estensione introdotta in Linux dal kernel 2.1.44,
+e permettono un completo controllo su tutti gli identificatori (\textit{real},
+\textit{effective} e \textit{saved}), i prototipi sono:
+\begin{functions}
+\headdecl{unistd.h}
+\headdecl{sys/types.h}
+
+\funcdecl{int setresuid(uid\_t ruid, uid\_t euid, uid\_t suid)} Setta il
+\textit{real user ID}, l'\textit{effective user ID} e il \textit{saved user
+  ID} del processo corrente ai valori specificati rispettivamente da
+\var{ruid}, \var{euid} e \var{suid}.
+  
+\funcdecl{int setresgid(gid\_t rgid, gid\_t egid, gid\_t sgid)} Setta il
+\textit{real group ID}, l'\textit{effective group ID} e il \textit{saved group
+  ID} del processo corrente ai valori specificati rispettivamente da
+\var{rgid}, \var{egid} e \var{sgid}.
+
+\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
+  di fallimento: l'unico errore possibile è \macro{EPERM}.}
+\end{functions}
 
+I processi non privilegiati possono cambiare uno qualunque degli
+identificatori usando uno qualunque dei valori correnti di \textit{real id},
+\textit{effective id} o \textit{saved id}, l'amministratore può specificare i
+valori che vuole; un valore di -1 per un qualunque parametro lascia inalterato
+l'identificatore corrispondente.
 
-\subsection{Le funzioni \texttt{seteuid} e \texttt{setegid}}
+
+
+\subsection{Le funzioni \func{seteuid} e \func{setegid}}
 \label{sec:proc_seteuid}
 
+Queste funzioni sono un'estensione allo standard POSIX.1 (ma sono comunque
+supportate dalla maggior parte degli unix) e usate per cambiare gli
+\textit{effective id}; i loro prototipi sono:
+\begin{functions}
+\headdecl{unistd.h}
+\headdecl{sys/types.h}
+
+\funcdecl{int seteuid(uid\_t uid)} Setta l'\textit{effective user ID} del
+processo corrente a \var{uid}.
 
-\subsection{Le \textit{race condition}}
+\funcdecl{int setegid(gid\_t gid)} Setta l'\textit{effective group ID} del
+processo corrente a \var{gid}.
+
+\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
+  di fallimento: l'unico errore possibile è \macro{EPERM}.}
+\end{functions}
+
+Gli utenti normali possono settare l'\textit{effective id} solo al valore del
+\textit{real id} o del \textit{saved id}, l'amministratore può specificare
+qualunque valore. Queste funzioni sono usate per permettere a root di settare
+solo l'\textit{effective id}, dato che l'uso normale di \func{setuid} comporta
+il settaggio di tutti gli identificatori.
+
+\subsection{Le funzioni \func{setfsuid} e \func{setfsgid}}
+\label{sec:proc_setfsuid}
+
+Queste funzioni sono usate per settare gli identificatori usati da Linux per
+il controllo dell'accesso ai file. Come già accennato in
+\secref{sec:proc_user_group} in Linux è definito questo ulteriore gruppo di
+identificatori, che di norma sono assolutamente equivalenti agli
+\textit{effective id}, dato che ogni cambiamento di questi ultimi viene
+immediatamente riportato sui \textit{filesystem id}.
+
+C'è un solo caso in cui si ha necessità di introdurre una differenza fra
+\textit{effective id} e \textit{filesystem id}, ed è per ovviare ad un
+problema di sicurezza che si presenta quando si deve implementare un server
+NFS. Il server NFS infatti deve poter cambiare l'identificatore con cui accede
+ai file per assumere l'identità del singolo utente remoto, ma se questo viene
+fatto cambiando l'\textit{effective id} o il \textit{real id} il server si
+espone alla ricezione di eventuali segnali ostili da parte dell'utente di cui
+ha temporaneamente assunto l'identità.  Cambiando solo il \textit{filesystem
+  id} si ottengono i privilegi necessari per accedere ai file, mantenendo
+quelli originari per quanto riguarda tutti gli altri controlli di accesso.
+
+Le due funzioni usate per cambiare questi identificatori sono \func{setfsuid}
+e \func{setfsgid}, ovviamente sono specifiche di Linux e non devono essere
+usate se si intendono scrivere programmi portabili; i loro prototipi sono:
+\begin{functions}
+\headdecl{sys/fsuid.h}
+
+\funcdecl{int setfsuid(uid\_t fsuid)} Setta il \textit{filesystem user ID} del
+processo corrente a \var{fsuid}.
+
+\funcdecl{int setfsgid(gid\_t fsgid)} Setta l'\textit{filesystem group ID} del
+processo corrente a \var{fsgid}.
+
+\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
+  di fallimento: l'unico errore possibile è \macro{EPERM}.}
+\end{functions}
+
+Queste funzioni hanno successo solo se il processo chiamante ha i privilegi di
+amministratore o, per gli altri utenti, se il valore specificato coincide con
+uno dei \textit{real}, \textit{effective} o \textit{saved id}.
+
+
+\section{Problematiche di programmazione multitasking}
+\label{sec:proc_multi_prog}
+
+Benché i processi siano strutturati in modo da apparire il più possibile come
+indipendenti l'uno dall'altro, nella programmazione in un sistema multiutente
+occorre tenere conto di tutta una serie di problematiche che normalmente non
+esistono quando si ha a che fare con un sistema in cui viene eseguito un solo
+programma alla volta. 
+
+Pur non essendo tutto questo direttamente legato alla modalità specifica in
+cui il multitasking è implementato in un sistema unix-like, né al solo
+concetto di multitasking (le stesse problematiche si presentano ad esempio
+nella gestione degli interrupt hardware), in questa sezione conclusiva del
+capitolo in cui abbiamo affrontato la gestione dei processi, introdurremo
+sinteticamente queste problematiche, che ritroveremo a più riprese in capitoli
+successivi, con una breve definizione della terminologia e delle loro
+caratteristiche di fondo.
+
+
+\subsection{Le operazioni atomiche}
+\label{sec:proc_atom_oper}
+
+La nozione di \textsl{operazione atomica} deriva dal significato greco della
+parola atomo, cioè indivisibile; si dice infatti che una operazione è atomica
+quando si ha la certezza che, qualora essa venga effettuata, tutti i passaggi
+che devono essere compiuti per realizzarla verranno eseguiti senza possibilità
+di interruzione in una fase intermedia.
+
+In un ambiente multitasking il concetto è essenziale, dato che un processo può
+essere interrotto in qualunque momento dal kernel che mette in esecuzione un
+altro processo o dalla ricezione di un segnale; occorre pertanto essere
+accorti nei confronti delle possibili \textit{race condition} (vedi
+\secref{sec:proc_race_cond}) derivanti da operazioni interrotte in una fase in
+cui non erano ancora state completate.
+
+Nel caso dell'interazione fra processi la situazione è molto più semplice, ed
+occorre preoccuparsi della atomicità delle operazioni solo quando si ha a che
+fare con meccanismi di intercomunicazione (che esamineremo in dettaglio in
+\capref{cha:IPC}) o nella operazioni con i file (vedremo alcuni esempi in
+\secref{sec:file_atomic}). In questi casi in genere l'uso delle appropriate
+funzioni di libreria per compiere le operazioni necessarie è garanzia
+sufficiente di atomicità in quanto le system call con cui esse sono realizzate
+non possono essere interrotte (o subire interferenze pericolose) da altri
+processi.
+
+Nel caso dei segnali invece la situazione è molto più delicata, in quanto lo
+stesso processo, e pure alcune system call, possono essere interrotti in
+qualunque momento, e le operazioni di un eventuale \textit{signal handler}
+sono compiute nello stesso spazio di indirizzi del processo. Per questo anche
+solo il solo accesso o l'assegnazione di una variabile possono non essere più
+operazioni atomiche (torneremo su questi aspetti in \secref{sec:sign_xxx}).
+
+In questo caso il sistema provvede un tipo di dato, il \type{sig\_atomic\_t},
+il cui accesso è assicurato essere atomico.  In pratica comunque si può
+assumere che in ogni piattaforma su cui è implementato Linux il tipo
+\type{int} (e gli altri interi di dimensione inferiore) ed i puntatori sono
+atomici. Non è affatto detto che lo stesso valga per interi di dimensioni
+maggiori (in cui l'accesso può comportare più istruzioni in assembler) o per
+le strutture. In questi casi è anche opportuno marcare come \type{volatile} le
+variabili che possono essere interessate ad accesso condiviso, onde evitare
+problemi con le ottimizzazioni del codice.
+
+
+\subsection{Le \textit{race condition} e i \textit{deadlock}}
 \label{sec:proc_race_cond}
 
 Si definisce una \textit{race condition} il caso in cui diversi processi
 stanno cercando di fare qualcosa con una risorsa comune ed il risultato finale
 viene a dipendere dall'ordine di esecuzione dei medesimi. Ovviamente dato che
-l'ordine di esecuzione di un processo, senza appositi meccanismi di
-sincronizzazione, non è assolutamente prevedibile, queste situazioni sono
-fonti di errori molto subdoli, che possono verificarsi solo in condizioni
-particolari e quindi difficilmente riproducibili.
-
+l'ordine di esecuzione di un processo rispetto agli altri, senza appositi
+meccanismi di sincronizzazione, non è assolutamente prevedibile, queste
+situazioni sono fonti di errori molto subdoli, che possono verificarsi solo in
+condizioni particolari e quindi difficilmente riproducibili.
+
+Casi tipici di \textit{race condition} si hanno quando diversi processi
+accedono allo stesso file, o nell'accesso a meccanismi di intercomunicazione
+come la memoria condivisa. In questi casi, se non si dispone della possibilità
+di eseguire atomicamente le operazioni necessarie, occorre che le risorse
+condivise siano opportunamente protette da meccanismi di sincronizzazione
+(torneremo su queste problematiche di questo tipo in \secref{sec:ipc_semaph}).
+
+Un caso particolare di \textit{race condition} sono poi i cosiddetti
+\textit{deadlock}; l'esempio tipico è quello di un flag di ``occupazione'' che
+viene rilasciato da un evento asincrono fra il controllo (in cui viene trovato
+occupato) e la successiva messa in attesa, che a questo punto diventerà
+perpetua (da cui il nome di \textit{deadlock}) in quanto l'evento di sblocco
+del flag è stato perso fra il controllo e la messa in attesa.
+
+
+\subsection{Le funzioni rientranti}
+\label{sec:proc_reentrant}
+
+Si dice rientrante una funzione che può essere interrotta in qualunque momento
+ed essere chiamata da capo (da questo il nome) da un altro filone di
+esecuzione (thread e manipolatori di segnali sono i casi in cui occorre
+prestare attenzione a questa problematica) senza che questo comporti nessun
+problema.
+
+In genere una funzione non è rientrante se opera direttamente su memoria che
+non è nello stack. Ad esempio una funzione non è rientrante se usa una
+variabile globale o statica od un oggetto allocato dinamicamente che trova da
+sola: due chiamate alla stessa funzione interferiranno.  Una funzione può non
+essere rientrante se usa e modifica un oggetto che le viene fornito dal
+chiamante: due chiamate possono interferire se viene passato lo stesso
+oggetto. 
+
+Le glibc mettono a disposizione due macro di compilatore \macro{\_REENTRANT} e
+\macro{\_THREAD\_SAFE} per assicurare che siano usate delle versioni rientranti
+delle funzioni di libreria.