+\section{La gestione dei processi}
+\label{sec:proc_handling}
+
+In questa sezione tratteremo le funzioni per la gestione dei processi, a
+partire dalle funzioni elementari che permettono di leggerne gli
+identificatori, alle varie funzioni di manipolazione dei processi, che
+riguardano la loro creazione, terminazione, e la messa in esecuzione di altri
+programmi.
+
+
+\subsection{Gli identificatori dei processi}
+\label{sec:proc_pid}
+
+Come accennato nell'introduzione ogni processo viene identificato dal sistema
+da un numero identificativo unico, il \textit{process id} o \acr{pid};
+quest'ultimo è un tipo di dato standard, il \type{pid\_t} che in genere è un
+intero con segno (nel caso di Linux e delle glibc il tipo usato è \type{int}).
+
+Il \acr{pid} viene assegnato in forma progressiva ogni volta che un nuovo
+processo viene creato, fino ad un limite massimo (in genere essendo detto
+numero memorizzato in un intero a 16 bit si arriva a 32767) oltre il quale si
+riparte dal numero più basso disponibile (FIXME: verificare, non sono sicuro).
+Per questo motivo processo il processo di avvio (\cmd{init}) ha sempre il
+\acr{pid} uguale a uno.
+
+Tutti i processi inoltre memorizzano anche il \acr{pid} del genitore da cui
+sono stati creati, questo viene chiamato in genere \acr{ppid} (da
+\textit{parent process id}). Questi due identificativi possono essere
+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
+ corrente.
+
+Entrambe le funzioni non riportano condizioni di errore.
+\end{functions}
+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
+candidato ideale per generare ulteriori indicatori associati al processo di
+cui diventa possibile garantire l'unicità: ad esempio la funzione
+\func{tmpname} (si veda \secref{sec:file_temp_file}) usa il \acr{pid} per
+generare un pathname univoco, che non potrà essere replicato da un'altro
+processo che usi la stessa funzione.
+
+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 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 dettaglii più avanti in
+\secref{sec:proc_perm}.
+
+
+\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)}
+ 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:
+ \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 alla 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, ma la memoria è copiata, non condivisa\footnote{In generale il segmento
+ di testo, che è identico, è condiviso e tenuto in read-only, Linux poi
+ utilizza la tecnica del \textit{copy-on-write}, per cui la memoria degli
+ altri segmenti viene copiata dal kernel per il nuovo processo solo in caso
+ di scrittura, rendendo molto più efficiente il meccanismo} pertanto padre e
+figlio vedono variabili diverse.
+
+La differenza che si ha nei due processi è che nel processo padre il valore di
+ritorno della funzione 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 sola differenza che si
+ha nei due processi è il valore di ritorno restituito dalla funzione, che nel
+padre è il \acr{pid} del figlio mentre nel figlio è zero; in questo modo il
+programma può identificare se viene eseguito dal padre o dal figlio.
+
+La scelta di questi valori non è casuale, un processo infatti può avere più
+figli, ed il valore di ritorno di \func{fork} è l'unico modo che 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}) e si usa il valore nullo, che non può essere 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 (il valore della costante
+\macro{CHILD\_MAX} definito in \file{limits.h}, che fa riferimento ai processo
+con lo stesso \textit{real user id}).
+
+L'uso di \func{fork} avviene secondo due modalità principali; la prima è
+quella in cui all'interno di un programma si creano processi figli per
+affidargli 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 visto per la prima
+modalità d'uso, esistono numerosi scenari in cui si può usare una \func{fork}
+senza bisogno di una \func{exec}. Inoltre anche nel caso della seconda
+modalità di operazioni, 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 molto più
+flessibile la possibilità di modificare gli attributi del nuovo processo.
+
+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 a 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}.
+
+Decifrato il numero di figli da creare, il ciclo principale del programma
+(\texttt{\small 28--40}) esegue in successione la creazione dei processi figli
+controllando il successo della chiamata a \func{fork} (\texttt{\small
+ 29--31}); ciascun figlio (\texttt{\small 29--31}) 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 29--31}) 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 è non si
+può dire quale processo fra il padre ed il figlio venga eseguito per
+primo\footnote{anche se nel kernel 2.4.x era stato introdotto un meccanismo
+ che metteva in esecuzione sempre il xxx per primo (TODO recuperare le
+ informazioni esatte)} 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, e se è necessaria una qualche forma di precedenza
+occorrerà provvedere ad espliciti meccanismi di sincronizzazione, pena il
+rischio di incorrere nelle cosiddette \textit{race conditions}.
+
+Si noti inoltre che, come accennato, 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 33}) sono
+visibili solo al loro interno, 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 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 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, per questo
+motivo, 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 all'uscita del figlio il buffer
+viene scritto su disco, 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, troviamo anche l'output del padre.
+
+Ma l'esempio ci mostra un'altro aspetto fondamentale dell'interazione con i
+file, che era 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 in unix è 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 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
+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 ed attende la sua conclusione per proseguire, ed entrambi
+scrivono sullo stesso file, ad esempio lo standard output (un caso tipico è la
+shell). Se l'output viene rediretto con questo comportamento avremo che il
+padre potrà continuare a scrivere automaticamente in coda a quanto scritto dal
+figlio; se così non fosse ottenere questo comportamento sarebbe estremamente
+complesso necessitando di una qualche forma di comunicazione fra i due
+processi.
+
+In generale comunque non è buona norma far scrivere più processi sullo stesso
+file senza una qualche forma di sincronizzazione in quanto, come visto con il
+nostro esempio, le varie scritture risulteranno mescolate fra loro in una
+sequenza impredicibile. 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
+ degli offset 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 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} 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{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 (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 bloccati e le azioni installate.
+\item i segmenti di memoria condivisa agganciati al processo.
+\item i limiti sulle risorse.
+\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 (\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 ed i segnali pendenti, 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 fatto 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
+concludere un programma, ma dal punto di vista del programma stesso; avendo a
+che fare con un sistema multitasking occorre adesso affrontare l'argomento dal
+punto di vista generale di come il sistema gestisce la conclusione dei
+processi.
+
+Abbiamo già 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 oltre alla conclusione normale abbiamo accennato che 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 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 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 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}.
+\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
+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 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 figlio
+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 \textsl{adottivo}) cui riportare il suo stato
+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
+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:intro_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
+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_xxx} 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
+vengono ereditati (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à è quella
+di terminare il processo che li ha generati, in modo che \cmd{init} possa
+adottarli e provvedere a concludere la terminazione.
+
+
+\subsection{Le funzioni \func{wait} e \func{waitpid}}
+\label{sec:proc_wait}
+
+Abbiamo già accennato come uno degli usi possibili delle capacità multitasking
+di un sistema unix-like consista nella creazione di programmi di tipo server,
+in cui un processo principale attende le richieste che vengono poi soddisfatte
+creando una serie di processi figli. Si è già sottolineato al paragrafo
+precedente come in questo caso diventi necessario gestire esplicitamente la
+conclusione dei vari processi 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. 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.
+
+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}
+
+è 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.
+
+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 suo prototipo è:
+
+\begin{functions}
+\headdecl{sys/types.h}
+\headdecl{sys/wait.h}
+\funcdecl{pid\_t waitpid(pid\_t pid, int * status, int options)}
+
+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 \var{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 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}\\
+ \hline
+ \hline
+ $<-1$& attende per un figlio il cui \textit{process group} è uguale al
+ valore assoluto di \var{pid}. \\
+ $-1$ & attende per un figlio qualsiasi, usata in questa maniera è
+ equivalente a \func{wait}.\\
+ $0$ & 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ò essere modificato passando delle
+opportune opzioni tramite la variabile \var{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 si è visto nella sezione precedente, una
+delle azioni prese dal kernel alla conclusione di un processo è quella di
+mandare un segnale di \macro{SIGCHLD} al padre. Questo segnale viene ignorato
+di default, ma costituisce il meccanismo di comunicazione asincrona con cui il
+kernel avverte un 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} (torneremo sui segnali e
+su come gestire \macro{SIGCHLD} in \secref{sec:sig_sigwait_xxx}) nel qual
+caso, dato che il segnale è generato dalla terminazione 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 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
+dipende dall'implementazione, e tradizionalmente alcuni bit sono riservati per
+memorizzare lo stato di uscita (in genere 8) altri per indicare il segnale che
+ha causato la terminazione (in caso di conclusione anomala), uno per indicare
+se è stato generato un core file, etc.\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 \curtab\ (si tenga presente che
+queste macro prendono come parametro la variabile di tipo \type{int} puntata
+da \var{status}).
+
+Si tenga conto che nel caso di conclusione anomala il valore restituito da
+\macro{WTERMSIG} può essere controllato contro le costanti definite in
+\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, 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)}
+ La funzione è 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}.
+\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:
+\begin{figure}[!htb]
+ \footnotesize
+ \centering
+ \begin{minipage}[c]{15cm}
+ \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
+struct rusage {
+ struct timeval ru_utime; /* user time used */
+ struct timeval ru_stime; /* system time used */
+ long ru_maxrss; /* maximum resident set size */
+ long ru_ixrss; /* integral shared memory size */
+ long ru_idrss; /* integral unshared data size */
+ long ru_isrss; /* integral unshared stack size */
+ long ru_minflt; /* page reclaims */
+ long ru_majflt; /* page faults */
+ long ru_nswap; /* swaps */
+ long ru_inblock; /* block input operations */
+ long ru_oublock; /* block output operations */
+ long ru_msgsnd; /* messages sent */
+ long ru_msgrcv; /* messages received */
+ long ru_nsignals; ; /* signals received */
+ long ru_nvcsw; /* voluntary context switches */
+ long ru_nivcsw; /* involuntary context switches */
+};
+ \end{lstlisting}
+ \end{minipage}
+ \normalsize
+ \caption{La struttura \var{rusage} per la lettura delle informazioni dei
+ delle risorse usate da un processo.}
+ \label{fig:proc_rusage_struct}
+\end{figure}
+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 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 \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, o
+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, che in
+realtà (come mostrato in \figref{fig:proc_exec_relat}), costituiscono un
+front-end a \func{execve}. Il prototipo di quest'ultima è: