+\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{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 che vedremo in
+\secref{sec:sess_xxx}, relativi al controllo di sessione), ad ogni processo
+vengono associati degli altri identificatori che vengono usati per il
+controllo di accesso. Questi servono per determinare se un processo può
+eseguire o meno le operazioni richieste, a seconda dei privilegi e
+dell'identità di chi lo ha posto in esecuzione; l'argomento è complesso e sarà
+affrontato in dettaglio in \secref{sec:proc_perms}.
+
+
+\subsection{La funzione \func{fork}}
+\label{sec:proc_fork}
+
+La funzione \func{fork} è la funzione fondamentale della gestione dei
+processi: come si è detto l'unico modo di creare un nuovo processo è
+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)}
+ Crea un nuovo processo.
+
+ \bodydesc{In caso di successo restituisce il \acr{pid} del figlio al padre e
+ zero al figlio; 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
+ 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
+ strutture necessarie al kernel per creare il nuovo processo.
+ \end{errlist}}
+\end{functions}
+
+Dopo il successo dell'esecuzione di una \func{fork} sia il processo padre che
+il processo figlio continuano ad essere eseguiti normalmente all'istruzione
+seguente la \func{fork}; il processo figlio è però una copia del padre, e
+riceve una copia dei segmenti di testo, stack e dati (vedi
+\secref{sec:proc_mem_layout}), ed esegue esattamente lo stesso codice del
+padre. Si tenga presente però che la memoria è copiata, non condivisa,
+pertanto padre e figlio vedono variabili diverse.
+
+Per quanto riguarda la gestione della memoria in generale il segmento di
+testo, che è identico, è condiviso e tenuto in read-only per il padre e per i
+figli. Per gli altri segmenti Linux utilizza la tecnica del \textit{copy on
+ write}\index{copy on write}; questa tecnica comporta che una pagina di
+memoria viene effettivamente copiata per il nuovo processo solo quando ci
+viene effettuata sopra una scrittura (e si ha quindi una reale differenza fra
+padre e figlio). In questo modo si rende molto più efficiente il meccanismo
+della creazione di un nuovo processo, non essendo più necessaria la copia di
+tutto lo spazio degli indirizzi virtuali del padre, ma solo delle pagine di
+memoria che sono state modificate, e solo al momento della modifica stessa.
+
+La differenza che si ha nei due processi è che nel processo padre il valore di
+ritorno della funzione \func{fork} è il \acr{pid} del processo figlio, mentre
+nel figlio è zero; in questo modo il programma può identificare se viene
+eseguito dal padre o dal figlio. Si noti come la funzione \func{fork} ritorni
+\textbf{due} volte: una nel padre e una nel figlio.
+
+La scelta di questi valori di ritorno non è casuale, un processo infatti può
+avere più figli, ed il valore di ritorno di \func{fork} è l'unico modo che gli
+permette di identificare quello appena creato; al contrario un figlio ha
+sempre un solo padre (il cui \acr{pid} può sempre essere ottenuto con
+\func{getppid}, vedi \secref{sec:proc_pid}) per cui si usa il valore nullo,
+che non è il \acr{pid} di nessun processo.
+
+\begin{figure}[!htb]
+ \footnotesize
+ \begin{lstlisting}{}
+#include <errno.h> /* error definitions and routines */
+#include <stdlib.h> /* C standard library */
+#include <unistd.h> /* unix standard library */
+#include <stdio.h> /* standard I/O library */
+#include <string.h> /* string functions */
+
+/* Help printing routine */
+void usage(void);
+
+int main(int argc, char *argv[])
+{
+/*
+ * Variables definition
+ */
+ int nchild, i;
+ pid_t pid;
+ int wait_child = 0;
+ int wait_parent = 0;
+ int wait_end = 0;
+ ... /* handling options */
+ nchild = atoi(argv[optind]);
+ printf("Test for forking %d child\n", nchild);
+ /* loop to fork children */
+ for (i=0; i<nchild; i++) {
+ if ( (pid = fork()) < 0) {
+ /* on error exit */
+ printf("Error on %d child creation, %s\n", i+1, strerror(errno));
+ exit(-1);
+ }
+ if (pid == 0) { /* child */
+ printf("Child %d successfully executing\n", ++i);
+ if (wait_child) sleep(wait_child);
+ printf("Child %d, parent %d, exiting\n", i, getppid());
+ exit(0);
+ } else { /* parent */
+ printf("Spawned %d child, pid %d \n", i+1, pid);
+ if (wait_parent) sleep(wait_parent);
+ printf("Go to next child \n");
+ }
+ }
+ /* normal exit */
+ if (wait_end) sleep(wait_end);
+ return 0;
+}
+ \end{lstlisting}
+ \caption{Esempio di codice per la creazione di nuovi processi.}
+ \label{fig:proc_fork_code}
+\end{figure}
+
+Normalmente la chiamata a \func{fork} può fallire solo per due ragioni, o ci
+sono già troppi processi nel sistema (il che di solito è sintomo che
+qualcos'altro non sta andando per il verso giusto) o si è ecceduto il limite
+sul numero totale di processi permessi all'utente (vedi \secref{sec:sys_xxx}).
+
+L'uso di \func{fork} avviene secondo due modalità principali; la prima è
+quella in cui all'interno di un programma si creano processi figli cui viene
+affidata l'esecuzione di una certa sezione di codice, mentre il processo padre
+ne esegue un'altra. È il caso tipico dei server di rete in cui il padre riceve
+ed accetta le richieste da parte dei client, per ciascuna delle quali pone in
+esecuzione un figlio che è incaricato di fornire il servizio.
+
+La seconda modalità è quella in cui il processo vuole eseguire un altro
+programma; questo è ad esempio il caso della shell. In questo caso il processo
+crea un figlio la cui unica operazione è quella fare una \func{exec} (di cui
+parleremo in \secref{sec:proc_exec}) subito dopo la \func{fork}.
+
+Alcuni sistemi operativi (il VMS ad esempio) combinano le operazioni di questa
+seconda modalità (una \func{fork} seguita da una \func{exec}) in un'unica
+operazione che viene chiamata \textit{spawn}. Nei sistemi unix-like è stato
+scelto di mantenere questa separazione, dato che, come per la prima modalità
+d'uso, esistono numerosi scenari in cui si può usare una \func{fork} senza
+aver bisogno di eseguire una \func{exec}. Inoltre, anche nel caso della
+seconda modalità d'uso, avere le due funzioni separate permette al figlio di
+cambiare gli attributi del processo (maschera dei segnali, redirezione
+dell'output, \textit{user id}) prima della \func{exec}, rendendo così
+relativamente facile intervenire sulle le modalità di esecuzione del nuovo
+programma.
+
+In \curfig\ si è riportato il corpo del codice del programma di esempio
+\cmd{forktest}, che ci permette di illustrare molte caratteristiche dell'uso
+della funzione \func{fork}. Il programma permette di creare un numero di figli
+specificato da linea di comando, e prende anche alcune opzioni per indicare
+degli eventuali tempi di attesa in secondi (eseguiti tramite la funzione
+\func{sleep}) per il padre ed il figlio (con \cmd{forktest -h} si ottiene la
+descrizione delle opzioni); il codice completo, compresa la parte che gestisce
+le opzioni a riga di comando, è disponibile nel file \file{ForkTest.c},
+distribuito insieme agli altri sorgenti degli esempi su
+\href{http://firenze.linux.it/~piccardi/gapil_source.tgz}
+{\texttt{http://firenze.linux.it/\~~\hspace{-2.0mm}piccardi/gapil\_source.tgz}}.
+
+Decifrato il numero di figli da creare, il ciclo principale del programma
+(\texttt{\small 24--40}) esegue in successione la creazione dei processi figli
+controllando il successo della chiamata a \func{fork} (\texttt{\small
+ 25--29}); ciascun figlio (\texttt{\small 31--34}) si limita a stampare il
+suo numero di successione, eventualmente attendere il numero di secondi
+specificato e scrivere un messaggio prima di uscire. Il processo padre invece
+(\texttt{\small 36--38}) stampa un messaggio di creazione, eventualmente
+attende il numero di secondi specificato, e procede nell'esecuzione del ciclo;
+alla conclusione del ciclo, prima di uscire, può essere specificato un altro
+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
+Spawned 1 child, pid 1964
+Child 1 successfully executing
+Child 1, parent 1963, exiting
+Go to next child
+Spawned 2 child, pid 1965
+Child 2 successfully executing
+Child 2, parent 1963, exiting
+Go to next child
+Child 3 successfully executing
+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 è che non
+si può dire quale processo fra il padre ed il figlio venga eseguito per
+primo\footnote{a partire dal kernel 2.5.2-pre10 è stato introdotto il nuovo
+ scheduler di Ingo Molnar che esegue sempre per primo il figlio; per
+ mantenere la portabilità è opportuno non fare comunque affidamento su questo
+ comportamento.} dopo la chiamata a \func{fork}; dall'esempio si può notare
+infatti come nei primi due cicli sia stato eseguito per primo il padre (con la
+stampa del \acr{pid} del nuovo processo) per poi passare all'esecuzione del
+figlio (completata con i due avvisi di esecuzione ed uscita), e tornare
+all'esecuzione del padre (con la stampa del passaggio al ciclo successivo),
+mentre la terza volta è stato prima eseguito il figlio (fino alla conclusione)
+e poi il padre.
+
+In generale l'ordine di esecuzione dipenderà, oltre che dall'algoritmo di
+scheduling usato dal kernel, dalla particolare situazione in si trova la
+macchina al momento della chiamata, risultando del tutto impredicibile.
+Eseguendo più volte il programma di prova e producendo un numero diverso di
+figli, si sono ottenute situazioni completamente diverse, compreso il caso in
+cui il processo padre ha eseguito più di una \func{fork} prima che uno dei
+figli venisse messo in esecuzione.
+
+Pertanto non si può fare nessuna assunzione sulla sequenza di esecuzione delle
+istruzioni del codice fra padre e figli, né sull'ordine in cui questi potranno
+essere messi in esecuzione. Se è necessaria una qualche forma di precedenza
+occorrerà provvedere ad espliciti meccanismi di sincronizzazione, pena il
+rischio di incorrere nelle cosiddette \textit{race condition} \index{race
+ condition} (vedi \secref{sec:proc_race_cond}.
+
+Si noti inoltre che essendo i segmenti di memoria utilizzati dai singoli
+processi completamente separati, le modifiche delle variabili nei processi
+figli (come l'incremento di \var{i} in \texttt{\small 31}) sono visibili solo
+a loro (ogni processo vede solo la propria copia della memoria), e non hanno
+alcun effetto sul valore che le stesse variabili hanno nel processo padre (ed
+in eventuali altri processi figli che eseguano lo stesso codice).
+
+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
+Process 1967: forking 3 child
+Child 1 successfully executing
+Child 1, parent 1967, exiting
+Test for forking 3 child
+Spawned 1 child, pid 1968
+Go to next child
+Child 2 successfully executing
+Child 2, parent 1967, exiting
+Test for forking 3 child
+Spawned 1 child, pid 1968
+Go to next child
+Spawned 2 child, pid 1969
+Go to next child
+Child 3 successfully executing
+Child 3, parent 1967, exiting
+Test for forking 3 child
+Spawned 1 child, pid 1968
+Go to next child
+Spawned 2 child, pid 1969
+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
+in gran dettaglio in \capref{cha:file_unix_interface} e in
+\secref{cha:files_std_interface}. Qui basta accennare che si sono usate le
+funzioni standard della libreria del C che prevedono l'output bufferizzato; e
+questa bufferizzazione (trattata in dettaglio in \secref{sec:file_buffering})
+varia a seconda che si tratti di un file su disco (in cui il buffer viene
+scaricato su disco solo quando necessario) o di un terminale (nel qual caso il
+buffer viene scaricato ad ogni carattere di a capo).
+
+Nel primo esempio allora avevamo che ad ogni chiamata a \func{printf} il
+buffer veniva scaricato, e le singole righe erano stampate a video subito dopo
+l'esecuzione della \func{printf}. Ma con la redirezione su file la scrittura
+non avviene più alla fine di ogni riga e l'output resta nel buffer. Dato che
+ogni figlio riceve una copia della memoria del padre, esso riceverà anche
+quanto c'è nel buffer delle funzioni di I/O, comprese le linee scritte dal
+padre fino allora. Così quando il buffer viene scritto su disco all'uscita del
+figlio, troveremo nel file anche tutto quello che il processo padre aveva
+scritto prima della sua creazione. E alla fine del file (dato che in questo
+caso il padre esce per ultimo) troveremo anche l'output completo del padre.
+
+L'esempio ci mostra un'altro aspetto fondamentale dell'interazione con i file,
+valido anche per l'esempio precedente, ma meno evidente: il fatto cioè che non
+solo processi diversi possono scrivere in contemporanea sullo stesso file
+(l'argomento della condivisione dei file è trattato in dettaglio in
+\secref{sec:file_sharing}), ma anche che, a differenza di quanto avviene per
+le variabili, la posizione corrente sul file è condivisa fra il padre e tutti
+i processi figli.
+
+Quello che succede è che quando lo standard output del padre viene rediretto,
+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 \textit{file table} (per la spiegazione di questi termini si
+veda \secref{sec:file_sharing}) e fra cui c'è anche la posizione corrente nel
+file.
+
+In questo modo se un processo scrive sul file aggiornerà la posizione corrente
+sulla \textit{file table}, e tutti gli altri processi, che vedono la stessa
+\textit{file table}, vedranno il nuovo valore. In questo modo si evita, in
+casi come quello appena mostrato in cui diversi processi scrivono sullo stesso
+file, che l'output successivo di un processo vada a sovrapporsi a quello dei
+precedenti: l'output potrà risultare mescolato, ma non ci saranno parti
+perdute per via di una sovrascrittura.
+
+Questo tipo di comportamento è essenziale in tutti quei casi in cui il padre
+crea un figlio e attende la sua conclusione per proseguire, ed entrambi
+scrivono sullo stesso file (un caso tipico è la shell quando lancia un
+programma, il cui output va sullo standard output).
+
+In questo modo, anche se l'output viene rediretto, il padre potrà sempre
+continuare a scrivere in coda a quanto scritto dal figlio in maniera
+automatica; se così non fosse ottenere questo comportamento sarebbe
+estremamente complesso necessitando di una qualche forma di comunicazione fra
+i due processi per far riprendere al padre la scrittura al punto giusto.
+
+In generale comunque non è buona norma far scrivere più processi sullo stesso
+file senza una qualche forma di sincronizzazione in quanto, come visto anche
+con il nostro esempio, le varie scritture risulteranno mescolate fra loro in
+una sequenza impredicibile. Per questo le modalità con cui in genere si usano
+i file dopo una \func{fork} sono sostanzialmente due:
+\begin{enumerate}
+\item Il processo padre aspetta la conclusione del figlio. In questo caso non
+ è necessaria nessuna azione riguardo ai file, in quanto la sincronizzazione
+ della posizione corrente dopo eventuali operazioni di lettura e scrittura
+ effettuate dal figlio è automatica.
+\item L'esecuzione di padre e figlio procede indipendentemente. In questo caso
+ ciascuno dei due processi deve chiudere i file che non gli servono una volta
+ che la \func{fork} è stata eseguita, per evitare ogni forma di interferenza.
+\end{enumerate}
+
+Oltre ai file aperti i processi figli ereditano dal padre una serie di altre
+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} settati
+ (vedi \secref{sec:proc_exec} e \secref{sec:file_fcntl}).
+\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} ed i \textit{supplementary group id} (vedi
+ \secref{sec:proc_access_id}).
+\item gli identificatori per il controllo di sessione: il \textit{process
+ group id} e il \textit{session id} ed il terminale di controllo (vedi
+ \secref{sec:sess_xxx} e \secref{sec:sess_xxx}).
+\item la directory di lavoro e la directory radice (vedi
+ \secref{sec:file_work_dir} e \secref{sec:file_chroot}).
+\item la maschera dei permessi di creazione (vedi \secref{sec:file_umask}).
+\item la maschera dei segnali bloccati (vedi \secref{sec:sig_sigmask}) e le
+ azioni installate (vedi \secref{sec:sig_gen_beha}).
+\item i segmenti di memoria condivisa agganciati al processo (vedi
+\secref{sec:ipc_xxx}).
+\item i limiti sulle risorse (vedi \secref{sec:sys_resource_limit}).
+\item le variabili di ambiente (vedi \secref{sec:proc_environ}).
+\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 (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_gen_beha}), che
+ per il figlio vengono cancellati.
+\end{itemize*}
+
+
+\subsection{La funzione \func{vfork}}
+\label{sec:proc_vfork}
+
+La funzione \func{vfork} è esattamente identica a \func{fork} ed ha la stessa
+semantica e gli stessi errori; la sola differenza è che non viene creata la
+tabella delle pagine né la struttura dei task per il nuovo processo. Il
+processo padre è posto in attesa fintanto che il figlio non ha eseguito una
+\func{execve} o non è uscito con una \func{\_exit}. Il figlio condivide la
+memoria del padre (e modifiche possono avere effetti imprevedibili) e non deve
+ritornare o uscire con \func{exit} ma usare esplicitamente \func{\_exit}.
+
+Questa funzione è un rimasuglio dei vecchi tempi in cui eseguire una
+\func{fork} comportava anche la copia completa del segmento dati del processo
+padre, che costituiva un inutile appesantimento in tutti quei casi in cui la
+\func{fork} veniva fatta solo per poi eseguire una \func{exec}. La funzione
+venne introdotta in BSD per migliorare le prestazioni.
+
+Dato che Linux supporta il \textit{copy on write} la perdita di prestazioni è
+assolutamente trascurabile, e l'uso di questa funzione (che resta un caso
+speciale della funzione \func{clone}), è deprecato; per questo eviteremo di
+trattarla ulteriormente.
+
+
+\subsection{La conclusione di un processo.}
+\label{sec:proc_termination}
+
+In \secref{sec:proc_conclusion} abbiamo già affrontato le modalità con cui
+chiudere un programma, ma dall'interno del programma stesso; avendo a che fare
+con un sistema multitasking resta da affrontare l'argomento dal punto di vista
+di come il sistema gestisce la conclusione dei processi.
+
+Abbiamo visto in \secref{sec:proc_conclusion} le tre modalità con cui un
+programma viene terminato in maniera normale: la chiamata di \func{exit} (che
+esegue le funzioni registrate per l'uscita e chiude gli stream), il ritorno
+dalla funzione \func{main} (equivalente alla chiamata di \func{exit}), e la
+chiamata ad \func{\_exit} (che passa direttamente alle operazioni di
+terminazione del processo da parte del kernel).
+
+Ma abbiamo accennato che oltre alla conclusione normale esistono anche delle
+modalità di conclusione anomala; queste sono in sostanza due: il programma può
+chiamare la funzione \func{abort} per invocare una chiusura anomala, o essere
+terminato da un segnale. In realtà anche la prima modalità si riconduce alla
+seconda, dato che \func{abort} si limita a generare il segnale
+\macro{SIGABRT}.
+
+Qualunque sia la modalità di conclusione di un processo, il kernel esegue
+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*}
+\item tutti i file descriptor sono chiusi.
+\item viene memorizzato lo stato di terminazione del processo.
+\item ad ogni processo figlio viene assegnato un nuovo padre (in genere
+ \cmd{init}).
+\item viene inviato il segnale \macro{SIGCHLD} al processo padre (vedi
+ \secref{sec:sig_sigchld}).
+\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 (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*}
+
+Oltre queste operazioni è però necessario poter disporre di un meccanismo
+ulteriore che consenta di sapere come la terminazione è avvenuta: dato che in
+un sistema unix-like tutto viene gestito attraverso i processi, il meccanismo
+scelto consiste nel riportare lo stato di terminazione (il cosiddetto
+\textit{termination status}) al processo padre.
+
+Nel caso di conclusione normale, abbiamo visto in \secref{sec:proc_conclusion}
+che lo stato di uscita del processo viene 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 che deve generare autonomamente il
+\textit{termination status} per indicare le ragioni della conclusione anomala.
+
+Si noti la distinzione fra \textit{exit status} e \textit{termination status}:
+quello che contraddistingue lo stato di chiusura del processo e viene
+riportato attraverso le funzioni \func{wait} o \func{waitpid} (vedi
+\secref{sec:proc_wait}) è sempre quest'ultimo; in caso di conclusione normale
+il kernel usa il primo (nel codice eseguito da \func{\_exit}) per produrre il
+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 potrebbe essere già
+terminato (si potrebbe avere cioè quello che si chiama un processo
+\textsl{orfano}).
+
+Questa complicazione viene superata facendo in modo che il processo orfano
+venga \textsl{adottato} da \cmd{init}. Come già accennato quando un processo
+termina, il kernel controlla se è il padre di altri processi in esecuzione: in
+caso positivo allora il \acr{ppid} di tutti questi processi viene sostituito
+con il \acr{pid} di \cmd{init} (e cioè con 1); in questo modo ogni processo
+avrà sempre un padre (nel caso possiamo parlare di un padre \textsl{adottivo})
+cui riportare il suo stato di terminazione. Come verifica di questo
+comportamento possiamo eseguire il nostro programma \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
+Spawned 1 child, pid 1973
+Child 1 successfully executing
+Go to next child
+Spawned 2 child, pid 1974
+Child 2 successfully executing
+Go to next child
+Child 3 successfully executing
+Spawned 3 child, pid 1975
+Go to next child
+[piccardi@selidor sources]$ Child 3, parent 1, exiting
+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
+terminano, e come si può notare in questo caso, al contrario di quanto visto
+in precedenza, essi riportano 1 come \acr{ppid}.
+
+Altrettanto rilevante è il caso in cui il figlio termina prima del padre,
+perché non è detto che il padre possa ricevere immediatamente lo stato di
+terminazione, quindi il kernel deve comunque conservare una certa quantità di
+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: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 \texttt{Z} nella colonna che ne indica lo stato. Quando il
+padre effettuerà la lettura dello stato di uscita anche questa informazione,
+non più necessaria, verrà scartata e la terminazione potrà dirsi completamente
+conclusa.
+
+Possiamo utilizzare il nostro programma di prova per analizzare anche questa
+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
+ 419 pts/0 S 0:00 bash
+ 568 pts/0 S 0:00 ./forktest -e10 3
+ 569 pts/0 Z 0:00 [forktest <defunct>]
+ 570 pts/0 Z 0:00 [forktest <defunct>]
+ 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.
+
+La possibilità di avere degli zombie deve essere tenuta sempre presente quando
+si scrive un programma che deve essere mantenuto in esecuzione a lungo e
+creare molti figli. In questo caso si deve sempre avere cura di far leggere
+l'eventuale stato di uscita di tutti i figli (in genere questo si fa
+attraverso un apposito \textit{signal handler}, che chiama la funzione
+\func{wait}, vedi \secref{sec:sig_sigchld} e \secref{sec:proc_wait}). Questa
+operazione è necessaria perché anche se gli \textit{zombie} non consumano
+risorse di memoria o processore, occupano comunque una voce nella tabella dei
+processi, che a lungo andare potrebbe esaurirsi.
+
+Si noti che quando un processo adottato da \cmd{init} termina, esso non
+diviene uno \textit{zombie}; questo perché una delle funzioni di \cmd{init} è
+appunto quella di chiamare la funzione \func{wait} per i processi cui fa da
+padre, completandone la terminazione. Questo è quanto avviene anche quando,
+come nel caso del precedente esempio con \cmd{forktest}, il padre termina con
+dei figli in stato di zombie: alla sua terminazione infatti tutti i suoi figli
+(compresi gli zombie) verranno adottati da \cmd{init}, il quale provvederà a
+completarne la terminazione.
+
+Si tenga presente infine che siccome gli zombie sono processi già usciti, non
+c'è modo di eliminarli con il comando \cmd{kill}; l'unica possibilità di
+cancellarli dalla tabella dei processi è quella di terminare il processo che
+li ha generati, in modo che \cmd{init} possa adottarli e provvedere a
+concluderne la terminazione.
+
+
+\subsection{Le funzioni \func{wait} e \func{waitpid}}
+\label{sec:proc_wait}
+
+Uno degli usi più comuni delle capacità multitasking di un sistema unix-like
+consiste nella creazione di programmi di tipo server, in cui un processo
+principale attende le richieste che vengono poi soddisfatte da una serie di
+processi figli. Si è già sottolineato al paragrafo precedente come in questo
+caso diventi necessario gestire esplicitamente la conclusione dei figli onde
+evitare di riempire di \textit{zombie} la tabella dei processi; le funzioni
+deputate a questo compito sono sostanzialmente due, \func{wait} e
+\func{waitpid}. La prima, il cui prototipo è:
+\begin{functions}
+\headdecl{sys/types.h}
+\headdecl{sys/wait.h}
+\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.
+
+\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.
+ \end{errlist}}
+\end{functions}
+\noindent
+è presente fin dalle prime versioni di Unix; la funzione ritorna non appena un
+processo figlio termina. Se un figlio è già terminato la funzione ritorna
+immediatamente.
+
+Al ritorno lo stato di terminazione 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ù
+ampie, legate anche al controllo di sessione. Dato che è possibile ottenere
+lo stesso comportamento di \func{wait} si consiglia di utilizzare sempre
+questa funzione, il cui prototipo è:
+\begin{functions}
+\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.
+
+\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
+ la funzione è stata interrotta da un segnale.
+ \item[\macro{ECHILD}] il processo specificato da \param{pid} non esiste o
+ non è figlio del processo chiamante.
+ \end{errlist}}
+\end{functions}
+
+Le differenze principali fra le due funzioni sono che \func{wait} si blocca
+sempre fino a che un processo figlio non termina, mentre \func{waitpid} ha la
+possibilità si specificare un'opzione \macro{WNOHANG} che ne previene il
+blocco; inoltre \func{waitpid} può specificare quale processo attendere sulla
+base del valore fornito dall'argomento \param{pid}, secondo lo
+specchietto riportato in \ntab:
+\begin{table}[!htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|c|c|p{8cm}|}
+ \hline
+ \textbf{Valore} & \textbf{Macro} &\textbf{Significato}\\
+ \hline
+ \hline
+ $<-1$& -- & attende per un figlio il cui \textit{process group} è uguale al
+ valore assoluto di \var{pid}. \\
+ $-1$ & \macro{WAIT\_ANY} & attende per un figlio qualsiasi, usata in
+ questa maniera è equivalente a \func{wait}.\\
+ $0$ & \macro{WAIT\_MYPGRP} & attende per un figlio il cui \textit{process
+ group} è uguale a quello del processo chiamante. \\
+ $>0$ & -- &attende per un figlio il cui \acr{pid} è uguale al
+ valore di \var{pid}.\\
+ \hline
+ \end{tabular}
+ \caption{Significato dei valori del parametro \var{pid} della funzione
+ \func{waitpid}.}
+ \label{tab:proc_waidpid_pid}
+\end{table}
+
+Il comportamento di \func{waitpid} può inoltre essere modificato passando
+delle opportune opzioni tramite l'argomento \param{option}. I valori possibili
+sono il già citato \macro{WNOHANG}, che previene il blocco della funzione
+quando il processo figlio non è terminato, e \macro{WUNTRACED} (usata per il
+controllo 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 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
+momento. Per questo motivo, come accennato nella sezione precedente, una delle
+azioni prese dal kernel alla conclusione di un processo è quella di mandare un
+segnale di \macro{SIGCHLD} al padre. L'azione di default (si veda
+\secref{sec:sig_base}) per questo segnale è di essere ignorato, ma la sua
+generazione costituisce il meccanismo di comunicazione asincrona con cui il
+kernel avverte il processo padre che uno dei suoi figli è terminato.
+
+In genere in un programma non si vuole essere forzati ad attendere la
+conclusione di un processo per proseguire, specie se tutto questo serve solo
+per leggerne lo stato di chiusura (ed evitare la presenza di \textit{zombie}),
+per questo la modalità più usata per chiamare queste funzioni è quella di
+utilizzarle all'interno di un \textit{signal handler} (vedremo un esempio di
+come gestire \macro{SIGCHLD} con i segnali in \secref{sec:sig_example}). In
+questo caso infatti, dato che il segnale è generato dalla terminazione di un
+figlio, avremo la 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}\\
+ \hline
+ \hline
+ \macro{WIFEXITED(s)} & Condizione vera (valore non nullo) per un processo
+ figlio che sia terminato normalmente. \\
+ \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 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 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 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
+ \func{waitpid} è bloccato. L'uso è possibile solo avendo specificato
+ 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
+ restituito un valore non nullo. \\
+ \hline
+ \end{tabular}
+ \caption{Descrizione delle varie macro di preprocessore utilizzabili per
+ verificare lo stato di terminazione \var{s} di un processo.}
+ \label{tab:proc_status_macro}
+\end{table}
+
+Entrambe le funzioni di attesa restituiscono lo stato di terminazione del
+processo tramite il puntatore \param{status} (se non interessa memorizzare lo
+stato si può passare un puntatore nullo). Il valore restituito da entrambe le
+funzioni dipende dall'implementazione, e tradizionalmente alcuni bit (in
+genere 8) sono riservati per memorizzare lo stato di uscita, e altri per
+indicare il segnale che ha causato la terminazione (in caso di conclusione
+anomala), uno per indicare se è stato generato un core file, ecc.\footnote{le
+ definizioni esatte si possono trovare in \file{<bits/waitstatus.h>} ma
+ questo file non deve mai essere usato direttamente, esso viene incluso
+ attraverso \file{<sys/wait.h>}.}
+
+Lo standard POSIX.1 definisce una serie di macro di preprocessore da usare per
+analizzare lo stato di uscita. Esse sono definite sempre in
+\file{<sys/wait.h>} ed elencate in \tabref{tab:proc_status_macro} (si tenga
+presente che queste macro prendono come parametro la variabile di tipo
+\ctyp{int} puntata da \var{status}).
+
+Si tenga conto che nel caso di conclusione anomala il valore restituito da
+\macro{WTERMSIG} può essere confrontato con le costanti definite in
+\file{signal.h} ed elencate in \tabref{tab:sig_signal_list}, e stampato usando
+le apposite funzioni trattate in \secref{sec:sig_strsignal}.
+
+
+\subsection{Le funzioni \func{wait3} e \func{wait4}}
+\label{sec:proc_wait4}
+
+Linux, seguendo un'estensione di BSD, supporta altre due funzioni per la
+lettura dello stato di terminazione di un processo \func{wait3} e
+\func{wait4}, analoghe alle precedenti ma che prevedono un ulteriore
+parametro attraverso il quale il kernel può restituire al padre informazioni
+sulle risorse usate dal processo terminato e dai vari figli. I prototipi di
+queste funzioni, che diventano accessibili definendo la costante
+\macro{\_USE\_BSD}, sono:
+\begin{functions}
+ \headdecl{sys/times.h} \headdecl{sys/types.h} \headdecl{sys/wait.h}
+ \headdecl{sys/resource.h}
+
+ \funcdecl{pid\_t wait4(pid\_t pid, int * status, int options, struct rusage
+ * rusage)}
+ È identica a \func{waitpid} sia per comportamento che per i valori dei
+ parametri, ma restituisce in \param{rusage} un sommario delle risorse usate
+ dal processo.
+
+ \funcdecl{pid\_t wait3(int *status, int options, struct rusage *rusage)}
+ Prima versione, equivalente a \code{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} (vedi
+\secref{sec:sys_resource_use}) per ottenere le risorse di sistema usate da un
+processo; la sua definizione è riportata in \figref{fig:sys_rusage_struct}.
+
+
+
+
+\subsection{Le funzioni \func{exec}}
+\label{sec:proc_exec}
+
+Abbiamo già detto che una delle modalità principali con cui si utilizzano i
+processi in Unix è quella di usarli per lanciare nuovi programmi: questo viene
+fatto attraverso una delle funzioni della famiglia \func{exec}. Quando un
+processo chiama una di queste funzioni esso viene completamente sostituito dal
+nuovo programma; il \acr{pid} del processo non cambia, dato che non viene
+creato un nuovo processo, la funzione semplicemente rimpiazza lo stack, lo
+heap, i dati ed il testo del processo corrente con un nuovo programma letto da
+disco.
+
+Ci sono sei diverse versioni di \func{exec} (per questo la si è chiamata
+famiglia di funzioni) che possono essere usate per questo compito, in realtà
+(come mostrato in \figref{fig:proc_exec_relat}), sono tutte 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}.
+
+ \bodydesc{La funzione ritorna solo in caso di errore, restituendo -1; nel
+ qual caso \var{errno} può assumere i valori:
+ \begin{errlist}
+ \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}, l'utente non
+ è root, e o il processo viene tracciato, o il filesystem è montato con
+ l'opzione \cmd{nosuid}.
+ \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'interprete
+ necessari per eseguirlo non esistono.
+ \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.
+ \end{errlist}
+ ed inoltre anche \macro{EFAULT}, \macro{ENOMEM}, \macro{EIO},
+ \macro{ENAMETOOLONG}, \macro{E2BIG}, \macro{ELOOP}, \macro{ENOTDIR},
+ \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
+\code{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, ...)}
+\funcdecl{int execv(const char *path, char *const argv[])}
+\funcdecl{int execle(const char *path, const char *arg, ..., char
+* const envp[])}
+\funcdecl{int execlp(const char *file, const char *arg, ...)}
+\funcdecl{int execvp(const char *file, char *const argv[])}
+
+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.
+
+\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
+riferimento allo specchietto riportato in \ntab. La prima differenza riguarda
+le modalità di passaggio dei parametri che poi andranno a costituire gli
+argomenti a linea di comando (cioè i valori di \var{argv} e \var{argc} visti
+dalla funzione \func{main} del programma chiamato).
+
+Queste modalità sono due e sono riassunte dagli mnemonici \code{v} e \code{l}
+che stanno rispettivamente per \textit{vector} e \textit{list}. Nel primo caso
+gli argomenti sono passati tramite il vettore di puntatori \var{argv[]} a
+stringhe terminate con zero che costituiranno gli argomenti a riga di comando,
+questo vettore \emph{deve} essere terminato da un puntatore nullo.
+
+Nel secondo caso le stringhe degli argomenti sono passate alla funzione come
+lista di puntatori, nella forma:
+\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
+ char *arg0, char *arg1, ..., char *argn, NULL
+\end{lstlisting}
+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
+ \begin{tabular}[c]{|l|c|c|c||c|c|c|}
+ \hline
+ \multicolumn{1}{|c|}{\textbf{Caratteristiche}} &
+ \multicolumn{6}{|c|}{\textbf{Funzioni}} \\
+ \hline
+ &\func{execl\ }&\func{execlp}&\func{execle}
+ &\func{execv\ }& \func{execvp}& \func{execve} \\
+ \hline
+ \hline
+ argomenti a lista &$\bullet$&$\bullet$&$\bullet$&&& \\
+ argomenti a vettore &&&&$\bullet$&$\bullet$&$\bullet$\\
+ \hline
+ filename completo &&$\bullet$&&&$\bullet$& \\
+ ricerca su \var{PATH}&$\bullet$&&$\bullet$&$\bullet$&&$\bullet$ \\
+ \hline
+ ambiente a vettore &&&$\bullet$&&&$\bullet$ \\
+ uso di \var{environ} &$\bullet$&$\bullet$&&$\bullet$&$\bullet$& \\
+ \hline
+ \end{tabular}
+ \caption{Confronto delle caratteristiche delle varie funzioni della
+ famiglia \func{exec}.}
+ \label{tab:proc_exec_scheme}
+\end{table}
+
+La seconda differenza fra le funzioni riguarda le modalità con cui si
+specifica il programma che si vuole eseguire. Con lo mnemonico \code{p} si
+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
+relativo a permessi di accesso insufficienti (cioè l'esecuzione della
+sottostante \func{execve} ritorna un \macro{EACCESS}), la ricerca viene
+proseguita nelle eventuali ulteriori directory indicate in \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 \code{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_access_id}).
+\item i \textit{supplementary group id} (vedi \secref{sec:proc_access_id}).
+\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 (vedi \secref{sec:sig_alarm_abort}).
+\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_sigmask}).
+\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*}
+
+Inoltre 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_gen_beha}).
+
+La gestione dei file aperti dipende dal valore che ha il flag di
+\textit{close-on-exec} (trattato in \secref{sec:file_fcntl}) per ciascun file
+descriptor. 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} (vedi \secref{sec:file_dir_read}) 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 quando
+il file che si va ad eseguire abbia o il \acr{suid} bit o lo \acr{sgid} bit
+settato, in questo caso l'\textit{effective user id} e l'\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 è
+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 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; vedremo quali sono gli identificatori
+usati, come questi possono essere modificati nella creazione e nel lancio di
+nuovi processi, le varie funzioni per la loro manipolazione diretta e tutte le
+problematiche connesse ad una gestione accorta dei privilegi.
+
+
+\subsection{Gli identificatori del controllo di accesso}
+\label{sec:proc_access_id}
+
+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 programma, e pertanto
+anche a ciascun processo è associato un utente e a un gruppo.
+
+Un semplice controllo di una corrispondenza fra identificativi 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}.
+