Aggiornamento al 2010 delle note di copyright
[gapil.git] / prochand.tex
index 07ebb358579f5375876cce2416e9ea9a80554bfc..7fe061ffcb81b5d369b937932b4b05c5fa44438b 100644 (file)
@@ -1,39 +1,56 @@
+%% prochand.tex
+%%
+%% Copyright (C) 2000-2010 Simone Piccardi.  Permission is granted to
+%% copy, distribute and/or modify this document under the terms of the GNU Free
+%% Documentation License, Version 1.1 or any later version published by the
+%% Free Software Foundation; with the Invariant Sections being "Un preambolo",
+%% with no Front-Cover Texts, and with no Back-Cover Texts.  A copy of the
+%% license is included in the section entitled "GNU Free Documentation
+%% License".
+%%
+
 \chapter{La gestione dei processi}
 \label{cha:process_handling}
 
-Come accennato nell'introduzione in un sistema unix ogni attività del sistema
-viene svolta tramite i processi.  In sostanza i processi costituiscono l'unità
-base per l'allocazione e l'uso delle risorse del sistema.
+Come accennato nell'introduzione in un sistema Unix tutte le operazioni
+vengono svolte tramite opportuni processi.  In sostanza questi ultimi vengono
+a costituire l'unità base per l'allocazione e l'uso delle risorse del sistema.
 
-Nel precedente capitolo abbiamo visto come funziona un singolo processo, in
-questo capitolo affronteremo i dettagli della creazione e della distruzione
-dei processi, della gestione dei loro attributi e privilegi, e di tutte le
-funzioni a questo connesse.
+Nel precedente capitolo abbiamo esaminato il funzionamento di un processo come
+unità a se stante, in questo esamineremo il funzionamento dei processi
+all'interno del sistema. Saranno cioè affrontati i dettagli della creazione e
+della terminazione dei processi, della gestione dei loro attributi e
+privilegi, e di tutte le funzioni a questo connesse. Infine nella sezione
+finale introdurremo alcune problematiche generiche della programmazione in
+ambiente multitasking.
 
 
 \section{Introduzione}
 \label{sec:proc_gen}
 
-Partiremo con una introduzione generale ai concetti che stanno alla base della
-gestione dei processi in unix. Introdurremo in questa sezione l'architettura
-della gestione dei processi e le sue principali caratteristiche, e daremo una
-panoramica sull'uso delle principali funzioni per la gestione dei processi.
+Inizieremo con un'introduzione generale ai concetti che stanno alla base della
+gestione dei processi in un sistema unix-like. Introdurremo in questa sezione
+l'architettura della gestione dei processi e le sue principali
+caratteristiche, dando una panoramica sull'uso delle principali funzioni di
+gestione.
+
 
-\subsection{La gerarchia dei processi}
+\subsection{L'architettura della gestione dei processi}
 \label{sec:proc_hierarchy}
 
 A differenza di quanto avviene in altri sistemi (ad esempio nel VMS la
 generazione di nuovi processi è un'operazione privilegiata) una delle
-caratteristiche di unix (che esamineremo in dettaglio più avanti) è che
+caratteristiche di Unix (che esamineremo in dettaglio più avanti) è che
 qualunque processo può a sua volta generarne altri, detti processi figli
 (\textit{child process}). Ogni processo è identificato presso il sistema da un
-numero unico, il cosiddetto \textit{process identifier} o, più brevemente, 
-\acr{pid}.
+numero univoco, il cosiddetto \textit{process identifier} o, più brevemente,
+\acr{pid}, assegnato in forma progressiva (vedi sez.~\ref{sec:proc_pid})
+quando il processo viene creato.
 
-Una seconda caratteristica di un sistema unix è che la generazione di un
-processo è unoperazione separata rispetto al lancio di un programma. In
+Una seconda caratteristica di un sistema Unix è che la generazione di un
+processo è un'operazione separata rispetto al lancio di un programma. In
 genere la sequenza è sempre quella di creare un nuovo processo, il quale
-eseguirà, in un passo successivo, il programma voluto: questo è ad esempio
+eseguirà, in un passo successivo, il programma desiderato: questo è ad esempio
 quello che fa la shell quando mette in esecuzione il programma che gli
 indichiamo nella linea di comando.
 
@@ -49,7 +66,7 @@ Ovviamente \cmd{init} 
 partire tutti gli altri processi necessari al funzionamento del sistema,
 inoltre \cmd{init} è essenziale per svolgere una serie di compiti
 amministrativi nelle operazioni ordinarie del sistema (torneremo su alcuni di
-essi in \secref{sec:proc_termination}) e non può mai essere terminato. La
+essi in sez.~\ref{sec:proc_termination}) e non può mai essere terminato. La
 struttura del sistema comunque consente di lanciare al posto di \cmd{init}
 qualunque altro programma, e in casi di emergenza (ad esempio se il file di
 \cmd{init} si fosse corrotto) è ad esempio possibile lanciare una shell al suo
@@ -98,40 +115,91 @@ init-+-keventd
 
 Dato che tutti i processi attivi nel sistema sono comunque generati da
 \cmd{init} o da uno dei suoi figli\footnote{in realtà questo non è del tutto
-  vero, in Linux ci sono alcuni processi che pur comparendo come figli di
-  init, o con \acr{pid} successivi, sono in realtà generati direttamente dal
-  kernel, (come \cmd{keventd}, \cmd{kswapd}, etc.)} si possono classificare i
-processi con la relazione padre/figlio in una organizzazione gerarchica ad
-albero, in maniera analoga a come i file sono organizzati in un albero di
-directory (si veda \secref{sec:file_file_struct}); in \curfig\ si è mostrato il
-risultato del comando \cmd{pstree} che permette di mostrare questa struttura,
-alla cui base c'è \cmd{init} che è progenitore di tutti gli altri processi.
+  vero, in Linux ci sono alcuni processi speciali che pur comparendo come
+  figli di \cmd{init}, o con \acr{pid} successivi, sono in realtà generati
+  direttamente dal kernel, (come \cmd{keventd}, \cmd{kswapd}, ecc.).} si
+possono classificare i processi con la relazione padre/figlio in
+un'organizzazione gerarchica ad albero, in maniera analoga a come i file sono
+organizzati in un albero di directory (si veda
+sez.~\ref{sec:file_organization}); in fig.~\ref{fig:proc_tree} si è mostrato il
+risultato del comando \cmd{pstree} che permette di visualizzare questa
+struttura, alla cui base c'è \cmd{init} che è progenitore di tutti gli altri
+processi.
 
+Il kernel mantiene una tabella dei processi attivi, la cosiddetta
+\itindex{process~table} \textit{process table}; per ciascun processo viene
+mantenuta una voce, costituita da una struttura \struct{task\_struct}, nella
+tabella dei processi che contiene tutte le informazioni rilevanti per quel
+processo. Tutte le strutture usate a questo scopo sono dichiarate nell'header
+file \file{linux/sched.h}, ed uno schema semplificato, che riporta la
+struttura delle principali informazioni contenute nella \struct{task\_struct}
+(che in seguito incontreremo a più riprese), è mostrato in
+fig.~\ref{fig:proc_task_struct}.
+
+\begin{figure}[htb]
+  \centering
+  \includegraphics[width=12cm]{img/task_struct}
+  \caption{Schema semplificato dell'architettura delle strutture usate dal
+    kernel nella gestione dei processi.}
+  \label{fig:proc_task_struct}
+\end{figure}
 
-\subsection{Una panoramica sulle funzioni di gestione}
+% TODO la task_struct è cambiata per qualche dettaglio vedi anche
+% http://www.ibm.com/developerworks/linux/library/l-linux-process-management/
+% TODO completare la parte su quando viene chiamato lo scheduler.
+
+Come accennato in sez.~\ref{sec:intro_unix_struct} è lo \itindex{scheduler}
+\textit{scheduler} che decide quale processo mettere in esecuzione; esso viene
+eseguito ad ogni system call ed ad ogni interrupt,\footnote{più in una serie
+  di altre occasioni.} ma può essere anche attivato esplicitamente. Il timer
+di sistema provvede comunque a che esso sia invocato periodicamente; generando
+un interrupt periodico secondo la frequenza specificata dalla costante
+\const{HZ},\footnote{fino al kernel 2.4 il valore di \const{HZ} era 100 su
+  tutte le architetture tranne l'alpha, per cui era 1000, nel 2.6 è stato
+  portato a 1000 su tutte; dal 2.6.13 lo si può impostare in fase di
+  compilazione del kernel, con un default di 250 e valori possibili di 100,
+  250, 1000 e dal 2.6.20 anche 300 (che è divisibile per le frequenze di
+  refresh della televisione); occorre fare attenzione a non confondere questo
+  valore con quello dei \itindex{clock~tick} \textit{clock tick} (vedi
+  sez.~\ref{sec:sys_unix_time}).} definita in \file{asm/param.h}, ed il cui
+valore è espresso in Hertz.\footnote{a partire dal kernel 2.6.21 è stato
+  introdotto (a cura di Ingo Molnar) un meccanismo completamente diverso,
+  detto \textit{tickless}, in cui non c'è più una interruzione periodica con
+  frequenza prefissata, ma ad ogni chiamata del timer viene programmata
+  l'interruzione successiva sulla base di una stima; in questo modo si evita
+  di dover eseguire un migliaio di interruzioni al secondo anche su macchine
+  che non stanno facendo nulla, con un forte risparmio nell'uso dell'energia
+  da parte del processore che può essere messo in stato di sospensione anche
+  per lunghi periodi di tempo.}
+
+Ogni volta che viene eseguito, lo \itindex{scheduler} \textit{scheduler}
+effettua il calcolo delle priorità dei vari processi attivi (torneremo su
+questo in sez.~\ref{sec:proc_priority}) e stabilisce quale di essi debba
+essere posto in esecuzione fino alla successiva invocazione.
+
+
+\subsection{Una panoramica sulle funzioni fondamentali}
 \label{sec:proc_handling_intro}
 
-I processi vengono creati dalla funzione \func{fork}; in molti unix questa è
-una system call, Linux però usa un'altra nomenclatura, e la funzione fork è
-basata a sua volta sulla system call \func{\_\_clone}, che viene usata anche
-per generare i \textit{thread}.  Il processo figlio creato dalla \func{fork} è
-una copia identica del processo processo padre, ma ha nuovo \acr{pid} e viene
-eseguito in maniera indipendente (le differenze fra padre e figlio sono
-affrontate in dettaglio in \secref{sec:proc_fork}).
+Tradizionalmente in un sistema unix-like i processi vengono sempre creati da
+altri processi tramite la funzione \func{fork}; il nuovo processo (che viene
+chiamato \textsl{figlio}) creato dalla \func{fork} è una copia identica del
+processo processo originale (detto \textsl{padre}), ma ha un nuovo \acr{pid} e
+viene eseguito in maniera indipendente (le differenze fra padre e figlio sono
+affrontate in dettaglio in sez.~\ref{sec:proc_fork}).
 
 Se si vuole che il processo padre si fermi fino alla conclusione del processo
 figlio questo deve essere specificato subito dopo la \func{fork} chiamando la
 funzione \func{wait} o la funzione \func{waitpid} (si veda
-\secref{sec:proc_wait}); queste funzioni restituiscono anche una informazione
-abbastanza limitata (lo stato di terminazione) sulle cause della terminazione
-del processo.
+sez.~\ref{sec:proc_wait}); queste funzioni restituiscono anche un'informazione
+abbastanza limitata sulle cause della terminazione del processo figlio.
 
 Quando un processo ha concluso il suo compito o ha incontrato un errore non
 risolvibile esso può essere terminato con la funzione \func{exit} (si veda
-quanto discusso in \secref{sec:proc_conclusion}). La vita del processo però
-termina solo quando la notifica della sua conclusione viene ricevuta dal
-processo padre, a quel punto tutte le risorse allocate nel sistema ad esso
-associate vengono rilasciate.
+quanto discusso in sez.~\ref{sec:proc_conclusion}). La vita del processo però
+termina completamente solo quando la notifica della sua conclusione viene
+ricevuta dal processo padre, a quel punto tutte le risorse allocate nel
+sistema ad esso associate vengono rilasciate.
 
 Avere due processi che eseguono esattamente lo stesso codice non è molto
 utile, normalmente si genera un secondo processo per affidargli l'esecuzione
@@ -142,9 +210,9 @@ coi processi che 
 
 Il programma che un processo sta eseguendo si chiama immagine del processo (o
 \textit{process image}), le funzioni della famiglia \func{exec} permettono di
-caricare un'altro programma da disco sostituendo quest'ultimo all'immagine
-corrente; questo fa si che l'immagine precedente venga completamente
-cancellata. Questo significa che quando il nuovo programma esce anche il
+caricare un altro programma da disco sostituendo quest'ultimo all'immagine
+corrente; questo fa sì che l'immagine precedente venga completamente
+cancellata. Questo significa che quando il nuovo programma termina, anche il
 processo termina, e non si può tornare alla precedente immagine.
 
 Per questo motivo la \func{fork} e la \func{exec} sono funzioni molto
@@ -153,173 +221,163 @@ prima ritorna due volte (nel processo padre e nel figlio) mentre la seconda
 non ritorna mai (in quanto con essa viene eseguito un altro programma).
 
 
-
-\section{La gestione dei processi}
+\section{Le funzioni di base}% della 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
+In questa sezione tratteremo le problematiche della gestione dei processi
+all'interno del sistema, illustrandone tutti i dettagli.  Inizieremo con le
+funzioni elementari che permettono di leggerne gli identificatori, per poi
+passare alla spiegazione delle funzioni base che si usano per la creazione e
+la terminazione dei processi, e per la messa in esecuzione degli 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};
+Come accennato nell'introduzione, ogni processo viene identificato dal sistema
+da un numero identificativo univoco, 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. 
+intero con segno (nel caso di Linux e delle \acr{glibc} il tipo usato è
+\ctyp{int}).
+
+Il \acr{pid} viene assegnato in forma progressiva\footnote{in genere viene
+  assegnato il numero successivo a quello usato per l'ultimo processo creato,
+  a meno che questo numero non sia già utilizzato per un altro \acr{pid},
+  \acr{pgid} o \acr{sid} (vedi sez.~\ref{sec:sess_proc_group}).} ogni volta
+che un nuovo processo viene creato, fino ad un limite che, essendo il
+\acr{pid} un numero positivo memorizzato in un intero a 16 bit, arriva ad un
+massimo di 32768.  Oltre questo valore l'assegnazione riparte dal numero più
+basso disponibile a partire da un minimo di 300,\footnote{questi valori, fino
+  al kernel 2.4.x, sono definiti dalla macro \const{PID\_MAX} in
+  \file{threads.h} e direttamente in \file{fork.c}, con il kernel 2.5.x e la
+  nuova interfaccia per i \itindex{thread} \textit{thread} creata da Ingo
+  Molnar anche il meccanismo di allocazione dei \acr{pid} è stato modificato;
+  il valore massimo è impostabile attraverso il file
+  \procfile{/proc/sys/kernel/pid\_max} e di default vale 32768.} che serve a
+riservare i \acr{pid} più bassi ai processi eseguiti direttamente dal kernel.
+Per questo motivo, come visto in sez.~\ref{sec:proc_hierarchy}, 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:
-
+\textit{parent process ID}).  Questi due identificativi possono essere
+ottenuti usando le due funzioni \funcd{getpid} e \funcd{getppid}, i cui
+prototipi sono:
 \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.
+  \headdecl{sys/types.h} 
+  \headdecl{unistd.h} 
+  \funcdecl{pid\_t getpid(void)}
+  
+  Restituisce il \acr{pid} del processo corrente.  
+  
+  \funcdecl{pid\_t getppid(void)} 
+  
+  Restituisce il \acr{pid} del padre del processo corrente.
 
-Entrambe le funzioni non riportano condizioni di errore. 
+\bodydesc{Entrambe le funzioni non riportano condizioni di errore.}
 \end{functions}
-esempi dell'uso di queste funzioni sono riportati in
-\figref{fig:proc_fork_code}, nel programma di esempio \file{ForkTest.c}.
+\noindent esempi dell'uso di queste funzioni sono riportati in
+fig.~\ref{fig:proc_fork_code}, nel programma \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. 
+Il fatto che il \acr{pid} sia un numero univoco per il sistema lo rende un
+candidato per generare ulteriori indicatori associati al processo di cui
+diventa possibile garantire l'unicità: ad esempio in alcune implementazioni la
+funzione \func{tempnam} (si veda sez.~\ref{sec:file_temp_file}) usa il
+\acr{pid} per generare un \itindex{pathname} \textit{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
+cap.~\ref{cha:session}, dove esamineremo gli altri identificativi associati ad
 un processo e le varie relazioni fra processi utilizzate per definire una
 sessione.
 
-Oltre al \acr{pid} e al \acr{ppid}, e a quelli usati per il controllo di
-sessione, ad ogni processo sono associati altri identificatori, usati per il
-controllo di accesso, che servono per determinare se il processo può o meno
-eseguire le operazioni richieste, a seconda dei privilegi e dell'identità di
-chi lo ha posto in esecuzione; su questi torneremo in dettaglii più avanti in
-\secref{sec:proc_perm}.
+Oltre al \acr{pid} e al \acr{ppid}, (e a quelli che vedremo in
+sez.~\ref{sec:sess_proc_group}, 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 sez.~\ref{sec:proc_perms}.
 
 
-\subsection{La funzione \func{fork}}
+\subsection{La funzione \func{fork} e le funzioni di creazione dei processi}
 \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 è:
-
+La funzione \funcd{fork} è la funzione fondamentale della gestione dei
+processi: come si è detto tradizionalmente l'unico modo di creare un nuovo
+processo era attraverso l'uso di questa funzione,\footnote{in realtà oggi la
+  system call usata più comunemente da Linux per creare nuovi processi è
+  \func{clone} (vedi \ref{sec:process_clone}) , anche perché a partire dalle
+  \acr{glibc} 2.3.3 non viene più usata la system call originale, ma la stessa
+  \func{fork} viene implementata tramite \func{clone}, cosa che consente una
+  migliore interazione coi \textit{thread}.} essa quindi riveste un ruolo
+centrale tutte le volte che si devono scrivere programmi che usano il
+multitasking.\footnote{oggi questa rilevanza, con la diffusione dell'uso dei
+  \textit{thread} che tratteremo al cap.~\ref{cha:threads}, è in parte minore,
+  ma \func{fork} resta comunque la funzione principale per la creazione di
+  processi.} Il prototipo della funzione è:
 \begin{functions}
   \headdecl{sys/types.h} 
   \headdecl{unistd.h} 
   \funcdecl{pid\_t fork(void)} 
-  Restituisce zero al padre e il \acr{pid} al figlio in caso di successo,
-  ritorna -1 al padre (senza creare il figlio) in caso di errore;
-  \texttt{errno} può assumere i valori:
+  Crea un nuovo processo.
+  
+  \bodydesc{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
+  \item[\errcode{EAGAIN}] non ci sono risorse sufficienti per creare un altro
     processo (per allocare la tabella delle pagine e le strutture del task) o
     si è esaurito il numero di processi disponibili.
-  \item \macro{ENOMEM} non è stato possibile allocare la memoria per le
+  \item[\errcode{ENOMEM}] non è stato possibile allocare la memoria per le
     strutture necessarie al kernel per creare il nuovo processo.
-  \end{errlist}
+  \end{errlist}}
 \end{functions}
 
 Dopo il successo dell'esecuzione di una \func{fork} sia il processo padre che
-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.
+il processo figlio continuano ad essere eseguiti normalmente a partire
+dall'istruzione successiva alla \func{fork}; il processo figlio è però una
+copia del padre, e riceve una copia dei \index{segmento!testo} segmenti di
+testo, \itindex{stack} \textit{stack} e \index{segmento!dati} dati (vedi
+sez.~\ref{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
+\index{segmento!testo} segmento di testo, che è identico per i due processi, è
+condiviso e tenuto in read-only per il padre e per i figli. Per gli altri
+segmenti Linux utilizza la tecnica del \itindex{copy~on~write} \textit{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 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.
+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 sez.~\ref{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}
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+  \includecodesample{listati/ForkTest.c}
+  \end{minipage}
+  \normalsize
   \caption{Esempio di codice per la creazione di nuovi processi.}
   \label{fig:proc_fork_code}
 \end{figure}
@@ -327,58 +385,66 @@ int main(int argc, char *argv[])
 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}).
+sul numero totale di processi permessi all'utente (vedi
+sez.~\ref{sec:sys_resource_limit}, ed in particolare
+tab.~\ref{tab:sys_rlimit_values}).
 
 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.
+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 programmi server (il modello
+\textit{client-server} è illustrato in sez.~\ref{sec:net_cliserv}) in cui il
+padre riceve ed accetta le richieste da parte dei programmi 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}.
+crea un figlio la cui unica operazione è quella di fare una \func{exec} (di
+cui parleremo in sez.~\ref{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
+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 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
+dell'output, identificatori) prima della \func{exec}, rendendo così
+relativamente facile intervenire sulle le modalità di esecuzione del nuovo
+programma.
+
+In fig.~\ref{fig:proc_fork_code} è riportato il corpo del codice del programma
+di esempio \cmd{forktest}, che permette di illustrare molte caratteristiche
+dell'uso della funzione \func{fork}. Il programma crea 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}.
+le opzioni a riga di comando, è disponibile nel file \file{ForkTest.c},
+distribuito insieme agli altri sorgenti degli esempi su
+\href{http://gapil.truelite.it/gapil_source.tgz}
+{\textsf{http://gapil.truelite.it/gapil\_source.tgz}}.
 
 Decifrato il numero di figli da creare, il ciclo principale del programma
-(\texttt{\small 28--40}) esegue in successione la creazione dei processi figli
+(\texttt{\small 24--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
+  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 29--31}) stampa un messaggio di creazione, eventualmente
+(\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:
-\begin{verbatim}
-[piccardi@selidor sources]$ ./forktest 3
+Se eseguiamo il comando\footnote{che è preceduto dall'istruzione \code{export
+    LD\_LIBRARY\_PATH=./} per permettere l'uso delle librerie dinamiche.}
+senza specificare attese (come si può notare in (\texttt{\small 17--19}) i
+valori predefiniti specificano di non attendere), otterremo come output sul
+terminale:
+\begin{Verbatim}[fontsize=\footnotesize,xleftmargin=1cm,xrightmargin=1.5cm]
+[piccardi@selidor sources]$ export LD_LIBRARY_PATH=./; ./forktest 3
 Process 1963: forking 3 child
 Spawned 1 child, pid 1964 
 Child 1 successfully executing
@@ -392,46 +458,67 @@ Child 3 successfully executing
 Child 3, parent 1963, exiting
 Spawned 3 child, pid 1966 
 Go to next child 
-\end{verbatim} %$
-
-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.
+\end{Verbatim} 
+%$
+
+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
+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.
+\itindex{scheduler} scheduling usato dal kernel, dalla particolare situazione
+in cui 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
+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 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).
+rischio di incorrere nelle cosiddette \itindex{race~condition} \textit{race
+  condition} (vedi sez.~\ref{sec:proc_race_cond}).
+
+In realtà a partire dal kernel 2.5.2-pre10 il nuovo \itindex{scheduler}
+\textit{scheduler} di Ingo Molnar esegue sempre per primo il
+figlio;\footnote{i risultati precedenti sono stati ottenuti usando un kernel
+  della serie 2.4.}  questa è una ottimizzazione che serve a evitare che il
+padre, effettuando per primo una operazione di scrittura in memoria, attivi il
+meccanismo del \itindex{copy~on~write} \textit{copy on write}. Questa
+operazione infatti potrebbe risultare del tutto inutile qualora il figlio
+fosse stato creato solo per eseguire una \func{exec}, in tal caso infatti si
+invocherebbe un altro programma scartando completamente lo spazio degli
+indirizzi, rendendo superflua la copia della memoria modificata dal padre.
+
+% TODO spiegare l'ulteriore cambiamento in ponte con il 2.6.32, che fa girare
+% prima il padre per questioni di caching nella CPU
+
+Eseguendo sempre per primo il figlio la \func{exec} verrebbe effettuata subito
+avendo così la certezza che il \itindex{copy~on~write} \textit{copy on write}
+viene utilizzato solo quando necessario. Quanto detto in precedenza vale
+allora soltanto per i kernel fino al 2.4; per mantenere la portabilità è però
+opportuno non fare affidamento su questo comportamento, che non si riscontra
+in altri Unix e nelle versioni del kernel precedenti a quella indicata.
+
+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 è:
-\begin{verbatim}
+\begin{Verbatim}[fontsize=\footnotesize,xleftmargin=1cm,xrightmargin=1.5cm]
 [piccardi@selidor sources]$ ./forktest 3 > output
 [piccardi@selidor sources]$ cat output
 Process 1967: forking 3 child
@@ -456,115 +543,140 @@ Spawned 2 child, pid 1969
 Go to next child 
 Spawned 3 child, pid 1970 
 Go to next child 
-\end{verbatim}
+\end{Verbatim}
 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
+in gran dettaglio in cap.~\ref{cha:file_unix_interface} e in
+cap.~\ref{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).
+questa bufferizzazione (trattata in dettaglio in sez.~\ref{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, 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 referenza a figura da fare) 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
+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
+sez.~\ref{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
+come si è fatto nell'esempio, lo stesso avviene anche per tutti i figli; la
+funzione \func{fork} infatti ha la caratteristica di duplicare nei processi
+figli tutti i file descriptor aperti nel processo padre (allo stesso modo in
+cui lo fa la funzione \func{dup}, trattata in sez.~\ref{sec:file_dup}), il che
+comporta che padre e figli condividono le stesse voci della
+\itindex{file~table} \textit{file table} (per la spiegazione di questi termini
+si veda sez.~\ref{sec:file_sharing}) fra cui c'è anche la posizione corrente
+nel file.
+
+In questo modo se un processo scrive sul file aggiornerà la posizione corrente
+sulla \itindex{file~table} \textit{file table}, e tutti gli altri processi,
+che vedono la stessa \itindex{file~table} \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).
+processo vada a sovrapporsi a quello dei precedentil'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.
+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 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}
+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
-  degli offset dopo eventuali operazioni di lettura e scrittura effettuate dal
-  figlio è automatica.
+  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 deve chiudere i file che non gli servono una volta che la
-  \func{fork} è stata eseguita, per evitare ogni forma di interferenza.
-\end{enumerate}
+  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à comuni; in dettaglio avremo che dopo l'esecuzione di una \func{fork}
-padre e figlio avranno in comune:
-\begin{itemize}
-\item i file aperti (e gli eventuali flag di \textit{close-on-exec} se
-  settati).
-\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}).
+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 \itindex{close-on-exec}
+  \textit{close-on-exec} impostati (vedi sez.~\ref{sec:proc_exec} e
+  sez.~\ref{sec:file_fcntl});
+\item gli identificatori per il controllo di accesso: l'\textsl{user-ID
+    reale}, il \textsl{group-ID reale}, l'\textsl{user-ID effettivo}, il
+  \textsl{group-ID effettivo} ed i \textit{group-ID supplementari} (vedi
+  sez.~\ref{sec:proc_access_id});
+\item gli identificatori per il controllo di sessione: il
+  \itindex{process~group} \textit{process group-ID} e il \textit{session id}
+  ed il terminale di controllo (vedi sez.~\ref{sec:sess_proc_group});
 \item la directory di lavoro e la directory radice (vedi
-  \secref{sec:file_work_dir}).
-\item la maschera dei permessi di creazione (vedi \secref{sec:file_umask}).
-\item la maschera dei segnali.
-\item i segmenti di memoria condivisa agganciati al processo. 
-\item i limiti sulle risorse
-\item le variabili di ambiente (vedi \secref{sec:proc_environ}).
-\end{itemize}
-le differenze invece sono:
-\begin{itemize}
-\item il valore di ritorno di \func{fork}.
-\item il \textit{process id}. 
-\item il \textit{parent process id} (quello del figlio viene settato al
-  \acr{pid} del padre).
-\item i valori dei tempi di esecuzione (\var{tms\_utime}, \var{tms\_stime},
-  \var{tms\_cutime}, \var{tms\_uetime}) che nel figlio sono posti a zero.
-\item i \textit{file lock}, che non vengono ereditati dal figlio.
-\item gli allarmi pendenti, che per il figlio vengono cancellati.
-\end{itemize}
-
-
-\subsection{La funzione \func{vfork}}
-\label{sec:proc_vfork}
-
-La funzione \func{vfork} è esattamente identica a \func{fork} ed ha la stessa
+  sez.~\ref{sec:file_work_dir} e sez.~\ref{sec:file_chroot});
+\item la maschera dei permessi di creazione dei file (vedi
+  sez.~\ref{sec:file_perm_management});
+\item la maschera dei segnali bloccati (vedi sez.~\ref{sec:sig_sigmask}) e le
+  azioni installate (vedi sez.~\ref{sec:sig_gen_beha});
+\item i segmenti di memoria condivisa agganciati al processo (vedi
+  sez.~\ref{sec:ipc_sysv_shm});
+\item i limiti sulle risorse (vedi sez.~\ref{sec:sys_resource_limit});
+\item il valori di \textit{nice}, le priorità real-time e le affinità di
+  processore (vedi sez.~\ref{sec:proc_sched_stand},
+  sez.~\ref{sec:proc_real_time} e sez.~\ref{sec:proc_sched_multiprocess});
+\item le variabili di ambiente (vedi sez.~\ref{sec:proc_environ}).
+\end{itemize*}
+Le differenze fra padre e figlio dopo la \func{fork} invece sono:\footnote{a
+  parte le ultime quattro, relative a funzionalità specifiche di Linux, le
+  altre sono esplicitamente menzionate dallo standard POSIX.1-2001.}
+\begin{itemize*}
+\item il valore di ritorno di \func{fork};
+\item il \acr{pid} (\textit{process id}), assegnato ad un nuovo valore univoco;
+\item il \acr{ppid} (\textit{parent process id}), quello del figlio viene
+  impostato al \acr{pid} del padre;
+\item i valori dei tempi di esecuzione (vedi sez.~\ref{sec:sys_cpu_times}) e
+  delle risorse usate (vedi sez.~\ref{sec:sys_resource_use}), che nel figlio
+  sono posti a zero;
+\item i \textit{lock} sui file (vedi sez.~\ref{sec:file_locking}) e sulla
+  memoria (vedi sez.~\ref{sec:proc_mem_lock}), che non vengono ereditati dal
+  figlio;
+\item gli allarmi (vedi sez.~\ref{sec:sig_alarm_abort}) ed i segnali pendenti
+  (vedi sez.~\ref{sec:sig_gen_beha}), che per il figlio vengono cancellati.
+\item le operazioni di I/O asincrono in corso (vedi
+  sez.~\ref{sec:file_asyncronous_io}) che non vengono ereditate dal figlio;
+\item gli aggiustamenti fatti dal padre ai semafori con \func{semop} (vedi
+  sez.~\ref{sec:ipc_sysv_sem}).
+\item le notifiche sui cambiamenti delle directory con \textit{dnotify} (vedi
+  sez.~\ref{sec:sig_notification}), che non vengono ereditate dal figlio;
+\item le mappature di memoria marcate come \const{MADV\_DONTFORK} (vedi
+  sez.~\ref{sec:file_memory_map}) che non vengono ereditate dal figlio;
+\item l'impostazione con \func{prctl} (vedi sez.~\ref{sec:prctl_xxx}) che
+  notifica al figlio la terminazione del padre viene cancellata;
+\item il segnale di terminazione del figlio è sempre \const{SIGCHLD} anche
+  qualora nel padre fosse stato modificato (vedi sez.~\ref{sec:process_clone}). 
+\end{itemize*}
+
+Una seconda funzione storica usata per la creazione di un nuovo processo è
+\func{vfork}, che è 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
@@ -575,72 +687,78 @@ 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
+\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.
+Dato che Linux supporta il \itindex{copy~on~write} \textit{copy on write} la
+perdita di prestazioni è assolutamente trascurabile, e l'uso di questa
+funzione, che resta un caso speciale della system call \func{clone} (che
+tratteremo in dettaglio in sez.~\ref{sec:process_clone}) è deprecato; per
+questo eviteremo di trattarla ulteriormente.
 
 
-\subsection{La conclusione di un processo.}
+\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.
+In sez.~\ref{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 già visto in \secref{sec:proc_conclusion} le tre modalità con cui un
+Abbiamo visto in sez.~\ref{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
+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}.
+terminato da un segnale (torneremo sui segnali in cap.~\ref{cha:signals}).  In
+realtà anche la prima modalità si riconduce alla seconda, dato che
+\func{abort} si limita a generare il segnale \const{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
+\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 \const{SIGCHLD} al processo padre (vedi
+  sez.~\ref{sec:sig_sigchld});
+\item se il processo è un leader di sessione ed il suo terminale di controllo
+  è quello della sessione viene mandato un segnale di \const{SIGHUP} a tutti i
+  processi del gruppo di \textit{foreground} e il terminale di controllo viene
+  disconnesso (vedi sez.~\ref{sec:sess_ctrl_term});
+\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 \const{SIGHUP} e \const{SIGCONT}
+  (vedi ancora sez.~\ref{sec:sess_ctrl_term}).
+\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
+sez.~\ref{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.  
+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
+sez.~\ref{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.
 
@@ -648,19 +766,19 @@ 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})
+terminatosi 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
+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 \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 è:
-\begin{verbatim}
+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 è:
+\begin{Verbatim}[fontsize=\footnotesize,xleftmargin=1cm,xrightmargin=1.5cm]
 [piccardi@selidor sources]$ ./forktest -c2 3
 Process 1972: forking 3 child
 Spawned 1 child, pid 1973 
@@ -675,7 +793,7 @@ Go to next child
 [piccardi@selidor sources]$ Child 3, parent 1, exiting
 Child 2, parent 1, exiting
 Child 1, parent 1, exiting
-\end{verbatim}
+\end{Verbatim}
 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
@@ -689,23 +807,23 @@ 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.
+dal processo (vedi sez.~\ref{sec:sys_unix_time}) e lo stato di terminazione,
+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 \index{zombie} \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 (vedi tab.~\ref{tab:proc_proc_states}). 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:
-\begin{verbatim}
+condizione: lanciamo il comando \cmd{forktest} in \textit{background} (vedi
+sez.~\ref{sec:sess_job_control}), 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:
+\begin{Verbatim}[fontsize=\footnotesize,xleftmargin=1cm,xrightmargin=1.5cm]
 [piccardi@selidor sources]$ ps T
   PID TTY      STAT   TIME COMMAND
   419 pts/0    S      0:00 bash
@@ -714,185 +832,283 @@ otterremo:
   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} %$
-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.
+\end{Verbatim} 
+%$
+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 \index{zombie} \textit{zombie} e l'indicazione che
+sono stati terminati.
+
+La possibilità di avere degli \index{zombie} \textit{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 sez.~\ref{sec:sig_sigchld} e
+sez.~\ref{sec:proc_wait}).  Questa operazione è necessaria perché anche se gli
+\index{zombie} \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 \texttt{wait} e  \texttt{waitpid}}
+diviene uno \index{zombie} \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 \index{zombie} \textit{zombie}:
+alla sua terminazione infatti tutti i suoi figli (compresi gli \index{zombie}
+\textit{zombie}) verranno adottati da \cmd{init}, il quale provvederà a
+completarne la terminazione.
+
+Si tenga presente infine che siccome gli \index{zombie} \textit{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{La funzione \func{waitpid} e le funzioni di ricezione degli stati
+  di uscita}
 \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 è:
-
+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 \index{zombie} \textit{zombie} la tabella dei processi;
+le funzioni deputate a questo compito sono principalmente due, \funcd{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)} 
+\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:
+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}
+  \item[\errcode{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 è:
-
+\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, se più di un figlio è terminato occorre chiamare la funzione
+più volte se si vuole recuperare lo stato di terminazione di tutti quanti.
+
+Al ritorno della funzione lo stato di terminazione del figlio viene salvato
+nella variabile puntata da \param{status} e tutte le risorse del kernel
+relative al processo (vedi sez.~\ref{sec:proc_termination}) vengono rilasciate.
+Nel caso un processo abbia più figli il valore di ritorno (il \acr{pid} del
+figlio) permette di identificare qual è quello che è uscito.
+
+Questa funzione ha il difetto di essere poco flessibile, in quanto ritorna
+all'uscita di un qualunque processo figlio. Nelle occasioni in cui è
+necessario attendere la conclusione di un processo specifico occorrerebbe
+predisporre un meccanismo che tenga conto dei processi già terminati, e
+provvedere 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
+\funcd{waitpid} che effettua lo stesso servizio, ma dispone di una serie di
+funzionalità più ampie, legate anche al controllo di sessione (si veda
+sez.~\ref{sec:sess_job_control}).  Dato che è possibile ottenere lo stesso
+comportamento di \func{wait}\footnote{in effetti il codice
+  \code{wait(\&status)} è del tutto equivalente a \code{waitpid(WAIT\_ANY,
+    \&status, 0)}.} 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)} 
+\funcdecl{pid\_t waitpid(pid\_t pid, int *status, int options)} 
+Attende la conclusione di un processo figlio.
 
-La funzione restituisce il \acr{pid} del processo che è uscito, 0 se è stata
-specificata l'opzione \macro{WNOHANG} e il processo non è uscito e -1 per un
-errore, nel qual caso \var{errno} assumerà i valori:
+\bodydesc{La funzione restituisce il \acr{pid} del processo che è uscito, 0 se
+  è stata specificata l'opzione \const{WNOHANG} e il processo non è uscito e
+  -1 per un errore, nel qual caso \var{errno} assumerà i valori:
   \begin{errlist}
-  \item \macro{EINTR} se non è stata specificata l'opzione \macro{WNOHANG} e
+  \item[\errcode{EINTR}] non è stata specificata l'opzione \const{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}
+  \item[\errcode{ECHILD}] il processo specificato da \param{pid} non esiste o
+    non è figlio del processo chiamante.
+  \item[\errcode{EINVAL}] si è specificato un valore non valido per
+    l'argomento \param{options}.
+  \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:
+La prima differenza fra le due funzioni è che con \func{waitpid} si può
+specificare in maniera flessibile quale processo attendere, sulla base del
+valore fornito dall'argomento \param{pid}, questo può assumere diversi valori,
+secondo lo specchietto riportato in tab.~\ref{tab:proc_waidpid_pid}, dove si
+sono riportate anche le costanti definite per indicare alcuni di essi.
+
 \begin{table}[!htb]
   \centering
-  \begin{tabular}[c]{|c|p{10cm}|}
+  \footnotesize
+  \begin{tabular}[c]{|c|c|p{8cm}|}
     \hline
-    \textbf{Valore} & \textbf{Significato}\\
+    \textbf{Valore} & \textbf{Costante} &\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}.\\
+    $<-1$& --               & Attende per un figlio il cui
+                              \itindex{process~group} \textit{process group}
+                              (vedi sez.~\ref{sec:sess_proc_group}) è uguale
+                              al valore assoluto di \param{pid}. \\ 
+    $-1$&\const{WAIT\_ANY}  & Attende per un figlio qualsiasi, usata in
+                              questa maniera senza specificare nessuna opzione
+                              è equivalente a \func{wait}.\\ 
+    $ 0$&\const{WAIT\_MYPGRP}&Attende per un figlio il cui
+                              \itindex{process~group} \textit{process group}
+                              (vedi sez.~\ref{sec:sess_proc_group}) è
+                              uguale a quello del processo chiamante. \\ 
+    $>0$& --                & Attende per un figlio il cui \acr{pid} è uguale
+                              al valore di \param{pid}.\\
     \hline
   \end{tabular}
-  \caption{Significato dei valori del parametro \var{pid} della funzione
+  \caption{Significato dei valori dell'argomento \param{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à.
+Il comportamento di \func{waitpid} può inoltre essere modificato passando alla
+funzione delle opportune opzioni tramite l'argomento \param{options}; questo
+deve essere specificato come maschera binaria dei flag riportati nella prima
+parte in tab.~\ref{tab:proc_waitpid_options} che possono essere combinati fra
+loro con un OR aritmetico. Nella seconda parte della stessa tabella si sono
+riportati anche alcuni valori non standard specifici di Linux, che consentono
+un controllo più dettagliato per i processi creati con la system call generica
+\func{clone} (vedi sez.~\ref{sec:process_clone}) usati principalmente per la
+gestione della terminazione dei \itindex{thread} \textit{thread} (vedi
+sez.~\ref{sec:thread_xxx}).
+
+\begin{table}[!htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|p{8cm}|}
+    \hline
+    \textbf{Macro} & \textbf{Descrizione}\\
+    \hline
+    \hline
+    \const{WNOHANG}   & La funzione ritorna immediatamente anche se non è
+                        terminato nessun processo figlio. \\
+    \const{WUNTRACED} & Ritorna anche se un processo figlio è stato fermato. \\
+    \const{WCONTINUED}& Ritorna anche quando un processo figlio che era stato
+                        fermato ha ripreso l'esecuzione.\footnotemark \\
+    \hline
+    \const{\_\_WCLONE}& Attende solo per i figli creati con \func{clone},
+                        vale a dire processi che non emettono nessun segnale
+                        o emettono un segnale diverso da \const{SIGCHL} alla
+                        terminazione. \\
+    \const{\_\_WALL}  & Attende per qualunque processo figlio. \\
+    \const{\_\_WNOTHREAD}& Non attende per i figli di altri \textit{thread}
+                        dello stesso gruppo. \\
+    \hline
+  \end{tabular}
+  \caption{Costanti che identificano i bit dell'argomento \param{options}
+    della funzione \func{waitpid}.} 
+  \label{tab:proc_waitpid_options}
+\end{table}
+
+\footnotetext{disponibile solo a partire dal kernel 2.6.10.}
+
+L'uso dell'opzione \const{WNOHANG} consente di prevenire il blocco della
+funzione qualora nessun figlio sia uscito (o non si siano verificate le altre
+condizioni per l'uscita della funzione); in tal caso la funzione ritornerà un
+valore nullo anziché positivo.\footnote{anche in questo caso un valore
+  positivo indicherà il \acr{pid} del processo di cui si è ricevuto lo stato
+  ed un valore negativo un errore.}
+
+Le altre due opzioni \const{WUNTRACED} e \const{WCONTINUED} consentono
+rispettivamente di tracciare non la terminazione di un processo, ma il fatto
+che esso sia stato fermato, o fatto ripartire, e sono utilizzate per la
+gestione del controllo di sessione (vedi sez.~\ref{sec:sess_job_control}).
+
+Nel caso di \const{WUNTRACED} la funzione ritorna, restituendone il \acr{pid},
+quando un processo figlio entra nello stato \textit{stopped}\footnote{in
+  realtà viene notificato soltanto il caso in cui il processo è stato fermato
+  da un segnale di stop (vedi sez.~\ref{sec:sess_ctrl_term}), e non quello in
+  cui lo stato \textit{stopped} è dovuto all'uso di \func{ptrace} (vedi
+  sez.~\ref{sec:xxx_ptrace}).} (vedi tab.~\ref{tab:proc_proc_states}), mentre
+con \const{WCONTINUED} la funzione ritorna quando un processo in stato
+\textit{stopped} riprende l'esecuzione per la ricezione del segnale
+\const{SIGCONT} (l'uso di questi segnali per il controllo di sessione è
+dettagliato in sez.~\ref{sec:sess_ctrl_term}). 
+
+La terminazione di un processo figlio (così come gli altri eventi osservabili
+con \func{waitpid}) è 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
+\const{SIGCHLD} al padre. L'azione predefinita (si veda
+sez.~\ref{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.
+
+Il comportamento delle funzioni è però cambiato nel passaggio dal kernel 2.4
+al kernel 2.6, quest'ultimo infatti si è adeguato alle prescrizioni dello
+standard POSIX.1-2001,\footnote{una revisione del 2001 dello standard POSIX.1
+  che ha aggiunto dei requisiti e delle nuove funzioni, come \func{waitid}.}
+e come da esso richiesto se \const{SIGCHLD} viene ignorato, o se si imposta il
+flag di \const{SA\_NOCLDSTOP} nella ricezione dello stesso (si veda
+sez.~\ref{sec:sig_sigaction}) i processi figli che terminano non diventano
+\textit{zombie} e sia \func{wait} che \func{waitpid} si bloccano fintanto che
+tutti i processi figli non sono terminati, dopo di che falliscono con un
+errore di \errcode{ENOCHLD}.\footnote{questo è anche il motivo per cui le
+  opzioni \const{WUNTRACED} e \const{WCONTINUED} sono utilizzabili soltanto
+  qualora non si sia impostato il flag di \const{SA\_NOCLDSTOP} per il segnale
+  \const{SIGCHLD}.}
+
+Con i kernel della serie 2.4 e tutti i kernel delle serie precedenti entrambe
+le funzioni di attesa ignorano questa prescrizione\footnote{lo standard POSIX.1
+  originale infatti lascia indefinito il comportamento di queste funzioni
+  quando \const{SIGCHLD} viene ignorato.} e si comportano sempre nello stesso
+modo, indipendentemente dal fatto \const{SIGCHLD} sia ignorato o meno:
+attendono la terminazione di un processo figlio e ritornano il relativo
+\acr{pid} e lo stato di terminazione nell'argomento \param{status}.
 
 \begin{table}[!htb]
   \centering
   \footnotesize
-  \begin{tabular}[c]{|c|p{10cm}|}
+  \begin{tabular}[c]{|l|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. \\
+                             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.\\
+                             stato di uscita del processo (passato attraverso
+                             \func{\_exit}, \func{exit} o come valore di
+                             ritorno di \func{main}); può essere valutata solo
+                             se \val{WIFEXITED} ha restituito un valore non
+                             nullo.\\ 
+    \macro{WIFSIGNALED(s)} & Condizione vera se il processo figlio è terminato
+                             in maniera anomala a causa di un segnale che non
+                             è stato catturato (vedi
+                             sez.~\ref{sec:sig_notification}).\\ 
+    \macro{WTERMSIG(s)}    & Restituisce il numero del segnale che ha causato
+                             la terminazione anomala del processo; può essere
+                             valutata solo se \val{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}.\\
+                             file di \itindex{core~dump} \textit{core
+                               dump}; può essere valutata solo se
+                             \val{WIFSIGNALED} ha restituito un valore non
+                             nullo.\footnotemark \\
     \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. \\
+                             \func{waitpid} è bloccato; l'uso è possibile solo
+                             con \func{waitpid} avendo specificato l'opzione
+                             \const{WUNTRACED}.\\
+    \macro{WSTOPSIG(s)}    & Restituisce il numero del segnale che ha bloccato
+                             il processo; può essere valutata solo se
+                             \val{WIFSTOPPED} ha restituito un valore non
+                             nullo. \\ 
+    \macro{WIFCONTINUED(s)}& Vera se il processo che ha causato il ritorno è
+                             stato riavviato da un
+                             \const{SIGCONT}.\footnotemark  \\ 
     \hline
   \end{tabular}
   \caption{Descrizione delle varie macro di preprocessore utilizzabili per 
@@ -900,147 +1116,258 @@ certezza che la chiamata a \func{wait} non si bloccher
   \label{tab:proc_status_macro}
 \end{table}
 
-
-Entrambe le funzioni restituiscono lo stato di terminazione del processo
-tramite il puntatore \var{status} (se non interessa memorizzare lo stato si
-può passare un puntatore nullo). Il valore restituito da entrambe le funzioni
-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}).
+\footnotetext[20]{questa macro non è definita dallo standard POSIX.1-2001, ma è
+  presente come estensione sia in Linux che in altri Unix, deve essere
+  pertanto utilizzata con attenzione (ad esempio è il caso di usarla in un
+  blocco \texttt{\#ifdef WCOREDUMP ... \#endif}.}
+
+\footnotetext{è presente solo a partire dal kernel 2.6.10.}
+
+In generale in un programma non si vuole essere forzati ad attendere la
+conclusione di un processo figlio per proseguire l'esecuzione, specie se tutto
+questo serve solo per leggerne lo stato di chiusura (ed evitare eventualmente
+la presenza di \index{zombie} \textit{zombie}). 
+
+Per questo la modalità più comune di chiamare queste funzioni è quella di
+utilizzarle all'interno di un \textit{signal handler} (vedremo un esempio di
+come gestire \const{SIGCHLD} con i segnali in sez.~\ref{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{waitpid} non si bloccherà.
+
+Come accennato sia \func{wait} che \func{waitpid} 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, ma
+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 \itindex{core~dump} \textit{core dump}, 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 tab.~\ref{tab:proc_status_macro}; si tenga
+presente che queste macro prevedono che gli si passi come parametro la
+variabile di tipo \ctyp{int} puntata dall'argomento \param{status} restituito
+da \func{wait} o \func{waitpid}.
 
 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}.
+\val{WTERMSIG} può essere confrontato con le costanti che identificano i
+segnali definite in \file{signal.h} ed elencate in
+tab.~\ref{tab:sig_signal_list}, e stampato usando le apposite funzioni
+trattate in sez.~\ref{sec:sig_strsignal}.
+
+A partire dal kernel 2.6.9, sempre in conformità allo standard POSIX.1-2001, è
+stata introdotta una nuova funzione di attesa che consente di avere un
+controllo molto più preciso sui possibili cambiamenti di stato dei processi
+figli e più dettagli sullo stato di uscita; la funzione è \funcd{waitid} ed il
+suo prototipo è:
+\begin{functions}
+  \headdecl{sys/types.h} 
+
+  \headdecl{sys/wait.h}
+  
+  \funcdecl{int waitid(idtype\_t idtype, id\_t id, siginfo\_t *infop, int
+    options)}    
+
+  Attende la conclusione di un processo figlio.
 
+  \bodydesc{La funzione restituisce 0 in caso di successo e -1 per un errore,
+    nel qual caso \var{errno} assumerà i valori:
+  \begin{errlist}
+  \item[\errcode{EINTR}] se non è stata specificata l'opzione \const{WNOHANG} e
+    la funzione è stata interrotta da un segnale.
+  \item[\errcode{ECHILD}] il processo specificato da \param{pid} non esiste o
+    non è figlio del processo chiamante.
+  \item[\errcode{EINVAL}] si è specificato un valore non valido per
+    l'argomento \param{options}.
+  \end{errlist}}
+\end{functions}
 
-\subsection{Le funzioni \func{wait3} e \func{wait4}}
-\label{sec:proc_wait4}
+La funzione prevede che si specifichi quali processi si intendono osservare
+usando i due argomenti \param{idtype} ed \param{id}; il primo indica se ci si
+vuole porre in attesa su un singolo processo, un gruppo di processi o un
+processo qualsiasi, e deve essere specificato secondo uno dei valori di
+tab.~\ref{tab:proc_waitid_idtype}; il secondo indica, a seconda del valore del
+primo, quale processo o quale gruppo di processi selezionare.
+
+\begin{table}[!htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|p{8cm}|}
+    \hline
+    \textbf{Macro} & \textbf{Descrizione}\\
+    \hline
+    \hline
+    \const{P\_PID} & Indica la richiesta di attendere per un processo figlio
+                     il cui \acr{pid} corrisponda al valore dell'argomento
+                     \param{id}.\\
+    \const{P\_PGID}& Indica la richiesta di attendere per un processo figlio
+                     appartenente al \textit{process group} (vedi
+                     sez.~\ref{sec:sess_proc_group}) il cui \acr{pgid}
+                     corrisponda al valore dell'argomento \param{id}.\\
+    \const{P\_ALL} & Indica la richiesta di attendere per un processo figlio
+                     generico, il valore dell'argomento \param{id} viene
+                     ignorato.\\
+    \hline
+  \end{tabular}
+  \caption{Costanti per i valori dell'argomento \param{idtype} della funzione
+    \func{waitid}.}
+  \label{tab:proc_waitid_idtype}
+\end{table}
 
-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:
+Come per \func{waitpid} anche il comportamento di \func{waitid} viene
+controllato dall'argomento \param{options}, da specificare come maschera
+binaria dei valori riportati in tab.~\ref{tab:proc_waitid_options}. Benché
+alcuni di questi siano identici come significato ed effetto ai precedenti di
+tab.~\ref{tab:proc_waitpid_options}, ci sono delle differenze significative:
+in questo caso si dovrà specificare esplicitamente l'attesa della terminazione
+di un processo impostando l'opzione \const{WEXITED}, mentre il precedente
+\const{WUNTRACED} è sostituito da \const{WSTOPPED}.  Infine è stata aggiunta
+l'opzione \const{WNOWAIT} che consente una lettura dello stato mantenendo il
+processo in attesa di ricezione, così che una successiva chiamata possa di
+nuovo riceverne lo stato.
 
+\begin{table}[!htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|p{8cm}|}
+    \hline
+    \textbf{Macro} & \textbf{Descrizione}\\
+    \hline
+    \hline
+    \const{WEXITED}   & Ritorna quando un processo figlio è terminato.\\
+    \const{WNOHANG}   & Ritorna immediatamente anche se non c'è niente da
+                        notificare.\\ 
+    \const{WSTOPPED} &  Ritorna quando un processo figlio è stato fermato.\\
+    \const{WCONTINUED}& Ritorna quando un processo figlio che era stato
+                        fermato ha ripreso l'esecuzione.\\
+    \const{WNOWAIT}   & Lascia il processo ancora in attesa di ricezione, così
+                        che una successiva chiamata possa di nuovo riceverne
+                        lo stato.\\
+    \hline
+  \end{tabular}
+  \caption{Costanti che identificano i bit dell'argomento \param{options}
+    della funzione \func{waitid}.} 
+  \label{tab:proc_waitid_options}
+\end{table}
+
+La funzione \func{waitid} restituisce un valore nullo in caso di successo, e
+$-1$ in caso di errore; viene restituito un valore nullo anche se è stata
+specificata l'opzione \const{WNOHANG} e la funzione è ritornata immediatamente
+senza che nessun figlio sia terminato. Pertanto per verificare il motivo del
+ritorno della funzione occorre analizzare le informazioni che essa
+restituisce; queste, al contrario delle precedenti \func{wait} e
+\func{waitpid} che usavano un semplice valore numerico, sono ritornate in una
+struttura di tipo \struct{siginfo\_t} (vedi fig.~\ref{fig:sig_siginfo_t})
+all'indirizzo puntato dall'argomento \param{infop}.
+
+Tratteremo nei dettagli la struttura \struct{siginfo\_t} ed il significato dei
+suoi vari campi in sez.~\ref{sec:sig_sigaction}, per quanto ci interessa qui
+basta dire che al ritorno di \func{waitid} verranno avvalorati i seguenti
+campi:
+\begin{basedescript}{\desclabelwidth{2.0cm}}
+\item[\var{si\_pid}] con il \acr{pid} del figlio.
+\item[\var{si\_uid}] con l'user-ID reale (vedi sez.~\ref{sec:proc_perms}) del
+  figlio.
+\item[\var{si\_signo}] con \const{SIGCHLD}.
+\item[\var{si\_status}] con lo stato di uscita del figlio o con il segnale che
+  lo ha terminato, fermato o riavviato.
+\item[\var{si\_code}] con uno fra \const{CLD\_EXITED}, \const{CLD\_KILLED},
+  \const{CLD\_STOPPED}, \const{CLD\_CONTINUED}, \const{CLD\_TRAPPED} e
+  \const{CLD\_DUMPED} a indicare la ragione del ritorno della funzione, il cui
+  significato è, nell'ordine: uscita normale, terminazione da segnale,
+  processo fermato, processo riavviato, processo terminato in \textit{core
+    dump}.
+\end{basedescript}
+
+Infine Linux, seguendo un'estensione di BSD, supporta altre due funzioni per
+la lettura dello stato di terminazione di un processo, analoghe alle
+precedenti ma che prevedono un ulteriore argomento attraverso il quale il
+kernel può restituire al padre informazioni sulle risorse (vedi
+sez.~\ref{sec:sys_res_limits}) usate dal processo terminato e dai vari figli.
+Le due funzioni sono \funcd{wait3} e \funcd{wait4}, che diventano accessibili
+definendo la macro \macro{\_USE\_BSD}; i loro prototipi 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})
+  \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 degli
+  argomenti, 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 \func{wait4(-1, \&status, opt, rusage)} è
+  Prima versione, equivalente a \code{wait4(-1, \&status, opt, rusage)} è
   ormai deprecata in favore di \func{wait4}.
 \end{functions}
-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 \texttt{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}.
+\noindent 
+la struttura \struct{rusage} è definita in \file{sys/resource.h}, e viene
+utilizzata anche dalla funzione \func{getrusage} (vedi
+sez.~\ref{sec:sys_resource_use}) per ottenere le risorse di sistema usate da un
+processo; la sua definizione è riportata in fig.~\ref{fig:sys_rusage_struct}.
 
-
-\subsection{Le funzioni \texttt{exec}}
+\subsection{La funzione \func{exec} e le funzioni di esecuzione dei programmi}
 \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
+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. 
+creato un nuovo processo, la funzione semplicemente rimpiazza lo
+\itindex{stack} \textit{stack}, lo \itindex{heap} \textit{heap}, i
+\index{segmento!dati} dati ed il \index{segmento!testo} 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 è:
-
+famiglia di funzioni) che possono essere usate per questo compito, in realtà
+(come mostrato in fig.~\ref{fig:proc_exec_relat}), sono tutte un front-end a
+\funcd{execve}. Il prototipo di quest'ultima è:
 \begin{prototype}{unistd.h}
-{int execve(const char * filename, char * const argv [], char * const envp[])}
+{int execve(const char *filename, char *const argv[], char *const envp[])}
+  Esegue il programma contenuto nel file \param{filename}.
   
-  La funzione esegue il file o lo script indicato da \var{filename},
-  passandogli la lista di argomenti indicata da \var{argv} e come ambiente la
-  lista di stringhe indicata da \var{envp}; entrambe le liste devono essere
-  terminate da un puntatore nullo. I vettori degli argomenti e dell'ambiente
-  possono essere acceduti dal nuovo programma quando la sua funzione
-  \func{main} è dichiarata nella forma \func{main(int argc, char *argv[], char
-    *envp[])}.
-
-  La funzione ritorna -1 solo in caso di errore, nel qual caso caso la
-  \var{errno} può assumere i valori:
+  \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} ma l'utente non
-    è root o il filesystem è montato con \cmd{nosuid}, oppure
-  \item \macro{ENOEXEC} il file è in un formato non eseguibile o non
+  \item[\errcode{EACCES}] il file non è eseguibile, oppure il filesystem è
+    montato in \cmd{noexec}, oppure non è un file regolare o un interprete.
+  \item[\errcode{EPERM}] il file ha i bit \itindex{suid~bit} \acr{suid} o
+    \itindex{sgid~bit} \acr{sgid}, l'utente non è root, il processo viene
+    tracciato, o il filesystem è montato con l'opzione \cmd{nosuid}.
+  \item[\errcode{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
+  \item[\errcode{ENOENT}] il file o una delle librerie dinamiche o l'interprete
     necessari per eseguirlo non esistono.
-  \item \macro{ETXTBSY} L'eseguibile è aperto in scrittura da uno o più
+  \item[\errcode{ETXTBSY}] l'eseguibile è aperto in scrittura da uno o più
     processi. 
-  \item \macro{EINVAL} L'eseguibile ELF ha più di un segmento
-    \macro{PF\_INTERP}, cioè chiede di essere eseguito da più di un interprete.
-  \item \macro{ELIBBAD} Un interprete ELF non è in un formato  riconoscibile.
+  \item[\errcode{EINVAL}] l'eseguibile ELF ha più di un segmento
+    \const{PF\_INTERP}, cioè chiede di essere eseguito da più di un
+    interprete.
+  \item[\errcode{ELIBBAD}] un interprete ELF non è in un formato
+    riconoscibile.
+  \item[\errcode{E2BIG}] la lista degli argomenti è troppo grande.
   \end{errlist}
-  ed inoltre anche \macro{EFAULT}, \macro{ENOMEM}, \macro{EIO},
-  \macro{ENAMETOOLONG}, \macro{E2BIG}, \macro{ELOOP}, \macro{ENOTDIR},
-  \macro{ENFILE}, \macro{EMFILE}.
+  ed inoltre anche \errval{EFAULT}, \errval{ENOMEM}, \errval{EIO},
+  \errval{ENAMETOOLONG}, \errval{ELOOP}, \errval{ENOTDIR}, \errval{ENFILE},
+  \errval{EMFILE}.}
 \end{prototype}
 
-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:
+La funzione \func{exec} esegue il file o lo script indicato da
+\param{filename}, passandogli la lista di argomenti indicata da \param{argv}
+e come ambiente la lista di stringhe indicata da \param{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 di
+possibili 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, ...)} 
@@ -1051,21 +1378,22 @@ prototipi sono:
 \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
+argomento. Gli argomenti successivi consentono di specificare gli argomenti a
 linea di comando e l'ambiente ricevuti dal nuovo processo.
 
-Queste funzioni ritornano solo in caso di errore, restituendo -1; nel qual
-caso \var{errno} andrà ad assumere i valori visti in precedenza per
-\func{execve}.
+\bodydesc{Queste funzioni ritornano solo in caso di errore, restituendo -1;
+  nel qual caso \var{errno} assumerà 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). 
+riferimento allo specchietto riportato in tab.~\ref{tab:proc_exec_scheme}. La
+prima differenza riguarda le modalità di passaggio dei valori che poi andranno
+a costituire gli argomenti a linea di comando (cioè i valori di
+\param{argv} e \param{argc} visti dalla funzione \func{main} del programma
+chiamato).
 
-Queste modalità sono due e sono riassunte dagli mnenonici \func{v} e \func{l}
+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,
@@ -1073,9 +1401,7 @@ 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}
+\includecodesnip{listati/char_list.c}
 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.
@@ -1088,15 +1414,15 @@ per indicare il nome del file che contiene il programma che verr
     \multicolumn{1}{|c|}{\textbf{Caratteristiche}} & 
     \multicolumn{6}{|c|}{\textbf{Funzioni}} \\
     \hline
-    &\func{execl\ }&\func{execlp}&\func{execle}
-    &\func{execv\ }& \func{execvp}& \func{execve} \\
+    &\func{execl}\texttt{ }&\func{execlp}&\func{execle}
+    &\func{execv}\texttt{ }& \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$ \\
+    filename completo     &$\bullet$&&$\bullet$&$\bullet$&&$\bullet$\\ 
+    ricerca su \var{PATH} &&$\bullet$&&&$\bullet$& \\
     \hline
     ambiente a vettore   &&&$\bullet$&&&$\bullet$ \\
     uso di \var{environ} &$\bullet$&$\bullet$&&$\bullet$&$\bullet$& \\
@@ -1108,108 +1434,181 @@ per indicare il nome del file che contiene il programma che verr
 \end{table}
 
 La seconda differenza fra le funzioni riguarda le modalità con cui si
-specifica il programma che si vuole eseguire. Con lo mnemonico \func{p} si
+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 di
-permessi negati (cioè l'esecuzione della sottostante \func{execve} ritorna un
-\macro{EACCESS}), la ricerca viene proseguita nelle eventuali ulteriori
-directory indicate nel \var{PATH}, solo se non viene trovato nessun altro file
-viene finalmente restituito \macro{EACCESS}.
+specificare il comando da eseguire; quando l'argomento \param{file} non
+contiene una ``\texttt{/}'' 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 \errcode{EACCES}), la ricerca viene
+proseguita nelle eventuali ulteriori directory indicate in \var{PATH}; solo se
+non viene trovato nessun altro file viene finalmente restituito
+\errcode{EACCES}.
 
 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.
+indicato dall'argomento \param{path}, che viene interpretato come il
+\itindex{pathname} \textit{pathname} del programma.
 
 \begin{figure}[htb]
   \centering
-  \includegraphics[width=13cm]{img/exec_rel.eps}
-  \caption{La interrelazione fra le sei funzioni della famiglia \func{exec}}
+  \includegraphics[width=12cm]{img/exec_rel}
+  \caption{La interrelazione fra le sei funzioni della famiglia \func{exec}.}
   \label{fig:proc_exec_relat}
 \end{figure}
 
 La terza differenza è come viene passata la lista delle variabili di ambiente.
-Con lo mnemonico \func{e} vengono indicate quelle funzioni che necessitano di
-un vettore di parametri \var{envp[]} analogo a quello usato per gli argomenti
-a riga di comando (terminato quindi da un \macro{NULL}), le altre usano il
-valore della variabile \var{environ} (vedi \secref{sec:proc_environ}) del
-processo di partenza per costruire l'ambiente.
+Con lo mnemonico \texttt{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 \val{NULL}), le altre
+usano il valore della variabile \var{environ} (vedi
+sez.~\ref{sec:proc_environ}) del processo di partenza per costruire
+l'ambiente.
 
 Oltre a mantenere lo stesso \acr{pid}, il nuovo programma fatto partire da
-\func{exec} assume anche una serie di altre proprietà del processo chiamante;
-la lista completa è la seguente:
-\begin{itemize}
-\item il \textit{process ID} (\acr{pid}) ed il \textit{parent process ID}
-  (\acr{ppid}).
-\item il \textit{real user ID} ed il \textit{real group ID} (vedi
-  \secref{sec:proc_user_group}).
-\item i \textit{supplementary group ID} (vedi \secref{sec:proc_user_group}).
-\item il \textit{session ID} ed il \textit{process group ID} (vedi
-  \secref{sec:sess_xxx}).
-\item il terminale di controllo (vedi \secref{sec:sess_xxx}).
-\item il tempo restante ad un allarme.
+\func{exec} mantiene la gran parte delle proprietà del processo chiamante; una
+lista delle più significative è la seguente:
+\begin{itemize*}
+\item il \textit{process id} (\acr{pid}) ed il \textit{parent process id}
+  (\acr{ppid});
+\item l'\textsl{user-ID reale}, il \textit{group-ID reale} ed i
+  \textsl{group-ID supplementari} (vedi sez.~\ref{sec:proc_access_id});
+\item il \textit{session ID} (\acr{sid}) ed il \itindex{process~group}
+  \textit{process group ID} (\acr{pgid}), vedi sez.~\ref{sec:sess_proc_group};
+\item il terminale di controllo (vedi sez.~\ref{sec:sess_ctrl_term});
+\item il tempo restante ad un allarme (vedi sez.~\ref{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_xxx}).
-\item i segnali sospesi (\textit{pending}) e la maschera dei segnali (si veda
-  \secref{sec:sig_xxx}).
-\item i limiti sulle risorse (vedi \secref{sec:limits_xxx})..
-\item i valori delle variabili \var{tms\_utime}, \var{tms\_stime},
-  \var{tms\_cutime}, \var{tms\_ustime} (vedi \secref{sec:xxx_xxx})..
-\end{itemize}
-
-Oltre a questo i segnali che sono stati settati per essere ignorati nel
-processo chiamante mantengono lo stesso settaggio pure nuovo programma, tutti
-gli altri segnali vengono settati alla loro azione di default. Un caso
-speciale è il segnale \macro{SIGCHLD} che, quando settato a \macro{SIG\_IGN}
-può anche non essere resettato a \macro{SIG\_DFL} (si veda
-\secref{sec:sig_xxx}).
-
-La gestione dei file aperti dipende dal valore del flag di
-\textit{close-on-exec} per ciascun file descriptor (si veda
-\secref{sec:file_xxx}); i file per cui è settato vengono chiusi, tutti gli
-altri file restano aperti. Questo significa che il comportamento di default è
-che i file restano aperti attraverso una \func{exec}, a meno di una chiamata
-esplicita a \func{fcntl} che setti il suddetto flag.
-
-Per le directory lo standard POSIX.1 richiede che esse vengano chiuse
-attraverso una \func{exec}, in genere questo è fatto dalla funzione
-\func{opendir} che effettua da sola il settaggio del flag di
-\textit{close-on-exec} sulle directory che apre, in maniera trasparente
-all'utente.
-
-Abbiamo detto che il \textit{real user ID} ed il \textit{real group ID}
-restano gli stessi all'esecuzione di \func{exec}; lo stesso vale per
-l'\textit{effective user ID} ed l'\textit{effective group ID}, tranne il caso
-in cui il file che si va ad eseguire ha o il \acr{suid} bit o lo \acr{sgid}
-bit settato, nel qual caso \textit{effective user ID} e \textit{effective
-  group ID} vengono settati rispettivamente all'utente o al gruppo cui il file
-appartiene (per i dettagli vedi \secref{sec:proc_perms}).
+  sez.~\ref{sec:file_work_dir});
+\item la maschera di creazione dei file \itindex{umask} (\textit{umask}, vedi
+  sez.~\ref{sec:file_perm_management}) ed i \textit{lock} sui file (vedi
+  sez.~\ref{sec:file_locking});
+\item i limiti sulle risorse (vedi sez.~\ref{sec:sys_resource_limit});
+\item i valori delle variabili \var{tms\_utime}, \var{tms\_stime};
+  \var{tms\_cutime}, \var{tms\_ustime} (vedi sez.~\ref{sec:sys_cpu_times});
+% TODO ===========Importante=============
+% TODO questo sotto è incerto, verificare
+% TODO ===========Importante=============
+\item la maschera dei segnali (si veda sez.~\ref{sec:sig_sigmask}).
+\end{itemize*}
+
+Una serie di proprietà del processo originale, che non avrebbe senso mantenere
+in un programma che esegue un codice completamente diverso in uno spazio di
+indirizzi totalmente indipendente e ricreato da zero, vengono perse con
+l'esecuzione di \func{exec}; lo standard POSIX.1-2001 prevede che le seguenti
+proprietà non vengano preservate:
+\begin{itemize*}
+\item l'insieme dei segnali pendenti (vedi sez.~\ref{sec:sig_gen_beha}), che
+  viene cancellato;
+\item gli eventuali stack alternativi per i segnali (vedi
+  sez.~\ref{sec:sig_specific_features});
+\item i \textit{directory stream} (vedi sez.~\ref{sec:file_dir_read}), che
+  vengono chiusi;
+\item le mappature dei file in memoria (vedi sez.~\ref{sec:file_memory_map});
+\item i segmenti di memoria condivisa SysV (vedi sez.~\ref{sec:ipc_sysv_shm})
+  e POSIX (vedi sez.~\ref{sec:ipc_posix_shm});
+\item i blocchi sulla memoria (vedi sez.~\ref{sec:proc_mem_lock});
+\item le funzioni registrate all'uscita (vedi sez.~\ref{sec:proc_atexit});
+\item i semafori e le code di messaggi POSIX (vedi
+  sez.~\ref{sec:ipc_posix_sem} e sez.~\ref{sec:ipc_posix_mq});
+\item i timer POSIX (vedi sez.~\ref{sec:sig_timer_adv}).
+\end{itemize*}
+
+I segnali che sono stati impostati per essere ignorati nel processo chiamante
+mantengono la stessa impostazione pure nel nuovo programma, ma tutti gli altri
+segnali, ed in particolare quelli per i quali è stato installato un gestore
+vengono impostati alla loro azione predefinita (vedi
+sez.~\ref{sec:sig_gen_beha}). Un caso speciale è il segnale \const{SIGCHLD}
+che, quando impostato a \const{SIG\_IGN}, potrebbe anche essere reimpostato a
+\const{SIG\_DFL}, anche se questo con Linux non avviene.\footnote{lo standard
+  POSIX.1-2001 prevede che questo comportamento sia deciso dalla singola
+  implementazione, quella di Linux è di non modificare l'impostazione
+  precedente.}
+
+Oltre alle precedenti che sono completamente generali e disponibili anche su
+altri sistemi unix-like, esistono altre proprietà dei processi, attinenti
+caratteristiche specifiche di Linux, che non vengono preservate
+nell'esecuzione della funzione \func{exec}, queste sono:
+\begin{itemize*}
+\item le operazione di I/O asincrono (vedi sez.~\ref{sec:file_asyncronous_io})
+  pendenti vengono cancellate;
+\item le \itindex{capabilities} \textit{capabilities} vengono modificate come
+  illustrato in sez.~\ref{sec:proc_capabilities};
+\item tutti i \itindex{thread} \textit{thread} tranne il chiamante (vedi
+  sez.~\ref{sec:thread_xxx}) sono cancellati e tutti gli oggetti ad essi
+  relativi (vedi sez.~\ref{sec:thread_xxx}) rimossi;
+\item viene impostato il flag \const{PR\_SET\_DUMPABLE} di \func{prctl} (vedi
+  sez.~\ref{sec:prctl_xxx}) a meno che il programma da eseguire non sia
+  \itindex{suid~bit} \acr{suid} o \itindex{sgid~bit} \acr{sgid} (vedi
+  sez.~\ref{sec:proc_access_id});
+\item il flag \const{PR\_SET\_KEEPCAPS} di \func{prctl} (vedi
+  sez.~\ref{sec:prctl_xxx}) viene cancellato;
+\item il nome del processo viene impostato al nome del file contenente il
+  programma messo in esecuzione;
+\item il segnale di terminazione viene reimpostato a \const{SIGCHLD};
+\item l'ambiente viene reinizializzato impostando le variabili attinenti alla
+  localizzazione al valore di default POSIX. 
+\end{itemize*}
+
+La gestione dei file aperti nel passaggio al nuovo programma lanciato con
+\func{exec} dipende dal valore che ha il flag di \itindex{close-on-exec}
+\textit{close-on-exec} (vedi anche sez.~\ref{sec:file_fcntl}) per ciascun file
+descriptor. I file per cui è impostato vengono chiusi, tutti gli altri file
+restano aperti. Questo significa che il comportamento predefinito è che i file
+restano aperti attraverso una \func{exec}, a meno di una chiamata esplicita a
+\func{fcntl} che imposti 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
+sez.~\ref{sec:file_dir_read}) che effettua da sola l'impostazione del flag di
+\itindex{close-on-exec} \textit{close-on-exec} sulle directory che apre, in
+maniera trasparente all'utente.
+
+Il comportamento della funzione in relazione agli identificatori relativi al
+controllo di accesso verrà trattato in dettaglio in sez.~\ref{sec:proc_perms},
+qui è sufficiente anticipare (si faccia riferimento a
+sez.~\ref{sec:proc_access_id} per la definizione di questi identificatori)
+come l'\textsl{user-ID reale} ed il \textsl{group-ID reale} restano sempre gli
+stessi, mentre l'\textsl{user-ID salvato} ed il \textsl{group-ID salvato}
+vengono impostati rispettivamente all'\textsl{user-ID effettivo} ed il
+\textsl{group-ID effettivo}, questi ultimi normalmente non vengono modificati,
+a meno che il file di cui viene chiesta l'esecuzione non abbia o il
+\itindex{suid~bit} \acr{suid} bit o lo \itindex{sgid~bit} \acr{sgid} bit
+impostato, in questo caso l'\textsl{user-ID effettivo} ed il \textsl{group-ID
+  effettivo} vengono impostati rispettivamente all'utente o al gruppo cui il
+file appartiene.
 
 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}.
+condivise, viene lanciato il \textit{linker} dinamico \cmd{/lib/ld.so} prima
+del programma per caricare le librerie necessarie ed effettuare il link
+dell'eseguibile.\footnote{il formato è ormai in completo disuso, per cui è
+  molto probabile che non il relativo supporto non sia disponibile.} Se il
+programma è in formato ELF per caricare le librerie dinamiche viene usato
+l'interprete indicato nel segmento \const{PT\_INTERP} previsto dal formato
+stesso, in genere questo è \sysfile{/lib/ld-linux.so.1} per programmi
+collegati con le \acr{libc5}, e \sysfile{/lib/ld-linux.so.2} per programmi
+collegati con le \acr{glibc}.
+
+Infine nel caso il file sia uno script esso deve iniziare con una linea nella
+forma \cmd{\#!/path/to/interpreter [argomenti]} dove l'interprete indicato
+deve essere un programma valido (binario, non un altro script) che verrà
+chiamato come se si fosse eseguito il comando \cmd{interpreter [argomenti]
+  filename}.\footnote{si tenga presente che con Linux quanto viene scritto
+  come \texttt{argomenti} viene passato all'interprete come un unico argomento
+  con una unica stringa di lunghezza massima di 127 caratteri e se questa
+  dimensione viene ecceduta la stringa viene troncata; altri Unix hanno
+  dimensioni massime diverse, e diversi comportamenti, ad esempio FreeBSD
+  esegue la scansione della riga e la divide nei vari argomenti e se è troppo
+  lunga restituisce un errore di \const{ENAMETOOLONG}, una comparazione dei
+  vari comportamenti si trova su
+  \href{http://www.in-ulm.de/~mascheck/various/shebang/}
+  {\textsf{http://www.in-ulm.de/\tild mascheck/various/shebang/}}.}
 
 Con la famiglia delle \func{exec} si chiude il novero delle funzioni su cui è
-basato il controllo dei processi in unix: con \func{fork} si crea un nuovo
-processo, con \func{exec} si avvia un nuovo programma, con \func{exit} e
-\func{wait} si effettua e si gestisce la conclusione dei programmi. Tutte le
-altre funzioni sono ausiliarie e servono la lettura e il settaggio dei vari
-parametri connessi ai processi.
+basata la gestione dei processi in Unix: con \func{fork} si crea un nuovo
+processo, con \func{exec} si lancia un nuovo programma, con \func{exit} e
+\func{wait} si effettua e verifica la conclusione dei processi. Tutte le
+altre funzioni sono ausiliarie e servono per la lettura e l'impostazione dei
+vari parametri connessi ai processi.
 
 
 
@@ -1217,151 +1616,1878 @@ parametri connessi ai processi.
 \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
+accesso dal punto di vista dei processi; vedremo quali sono gli identificatori
 usati, come questi possono essere modificati nella creazione e nel lancio di
-nuovi processi, e le varie funzioni per la loro manipolazione diretta e tutte
-le problematiche connesse alla gestione accorta dei privilegi.
+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 sez.~\ref{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 \itindex{capabilities}
+  \textit{capabilities} illustrate in sez.~\ref{sec:proc_capabilities}, le ACL
+  per i file (vedi sez.~\ref{sec:file_ACL}) o il
+  \itindex{Mandatory~Access~Control~(MAC)} \textit{Mandatory Access Control}
+  di \index{SELinux} SELinux; inoltre basandosi sul lavoro effettuato con
+  SELinux, a partire dal kernel 2.5.x, è iniziato lo sviluppo di una
+  infrastruttura di sicurezza, i \itindex{Linux~Security~Modules}
+  \textit{Linux Security Modules}, o LSM, in grado di fornire diversi agganci
+  a livello del kernel per modularizzare tutti i possibili controlli di
+  accesso.} 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.
 
+Abbiamo già accennato come il sistema associ ad ogni utente e gruppo due
+identificatori univoci, lo user-ID ed il group-ID; 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 sez.~\ref{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.
 
-\subsection{Utente e gruppo di un processo}
-\label{sec:proc_user_group}
+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 dovrà essere associato un utente e 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} (cioè \textsl{reali} ed
+\textsl{effettivi}). Nel caso di Linux si aggiungono poi altri due gruppi, il
+\textit{saved} (\textsl{salvati}) ed il \textit{filesystem} (\textsl{di
+  filesystem}), secondo la situazione illustrata in
+tab.~\ref{tab:proc_uid_gid}.
 
-Come accennato in \secref{sec:intro_multiuser} il modello base\footnote{in
-  realtà esistono estensioni di questo modello, che lo rendono più flessibile
-  e controllabile, come le \textit{capabilities}, le ACL per i file o il
-  modello a ``... NdT riprendere i dati'' 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.
+\begin{table}[htb]
+  \footnotesize
+  \centering
+  \begin{tabular}[c]{|c|c|l|p{7.3cm}|}
+    \hline
+    \textbf{Suffisso} & \textbf{Gruppo} & \textbf{Denominazione} 
+                                        & \textbf{Significato} \\ 
+    \hline
+    \hline
+    \acr{uid}   & \textit{real} & \textsl{user-ID reale} 
+                & Indica l'utente che ha lanciato il programma.\\ 
+    \acr{gid}   & '' &\textsl{group-ID reale} 
+                & Indica il gruppo principale dell'utente che ha lanciato 
+                  il programma.\\ 
+    \hline
+    \acr{euid}  & \textit{effective} &\textsl{user-ID effettivo} 
+                & Indica l'utente usato nel controllo di accesso.\\ 
+    \acr{egid}  & '' & \textsl{group-ID effettivo} 
+                & Indica il gruppo usato nel controllo di accesso.\\ 
+    --          & -- & \textsl{group-ID supplementari} 
+                & Indicano gli ulteriori gruppi cui l'utente appartiene.\\ 
+    \hline
+    --          & \textit{saved} & \textsl{user-ID salvato} 
+                & È una copia dell'\acr{euid} iniziale.\\ 
+    --          & '' & \textsl{group-ID salvato} 
+                & È una copia dell'\acr{egid} iniziale.\\ 
+    \hline
+    \acr{fsuid} & \textit{filesystem} &\textsl{user-ID di filesystem} 
+                & Indica l'utente effettivo per l'accesso al filesystem. \\ 
+    \acr{fsgid} & '' & \textsl{group-ID di filesystem} 
+                & Indica il gruppo effettivo per l'accesso al filesystem.\\ 
+    \hline
+  \end{tabular}
+  \caption{Identificatori di utente e gruppo associati a ciascun processo con
+    indicazione dei suffissi usati dalle varie funzioni di manipolazione.}
+  \label{tab:proc_uid_gid}
+\end{table}
 
-%Benché il sistema sia piuttosto semplice (è basato su un solo livello di
-% separazione) il sistema permette una
-%notevole flessibilità, 
+Al primo gruppo appartengono l'\textsl{user-ID reale} ed il \textsl{group-ID
+  reale}: questi vengono impostati al login ai valori corrispondenti
+all'utente con cui si accede al sistema (e relativo gruppo principale).
+Servono per l'identificazione dell'utente e normalmente non vengono mai
+cambiati. In realtà vedremo (in sez.~\ref{sec:proc_setuid}) che è possibile
+modificarli, ma solo ad un processo che abbia i privilegi di amministratore;
+questa possibilità è usata proprio dal programma \cmd{login} che, una volta
+completata la procedura di autenticazione, lancia una shell per la quale
+imposta questi identificatori ai valori corrispondenti all'utente che entra
+nel sistema.
+
+Al secondo gruppo appartengono lo \textsl{user-ID effettivo} ed il
+\textsl{group-ID effettivo} (a cui si aggiungono gli eventuali \textsl{group-ID
+  supplementari} dei gruppi dei quali l'utente fa parte).  Questi sono invece
+gli identificatori usati nelle verifiche dei permessi del processo e per il
+controllo di accesso ai file (argomento affrontato in dettaglio in
+sez.~\ref{sec:file_perm_overview}).
+
+Questi identificatori normalmente sono identici ai corrispondenti del gruppo
+\textit{real} tranne nel caso in cui, come accennato in
+sez.~\ref{sec:proc_exec}, il programma che si è posto in esecuzione abbia i
+bit \itindex{suid~bit} \acr{suid} o \itindex{sgid~bit} \acr{sgid} impostati
+(il significato di questi bit è affrontato in dettaglio in
+sez.~\ref{sec:file_special_perm}). In questo caso essi saranno impostati
+all'utente e al gruppo proprietari del file. Questo consente, per programmi in
+cui ci sia necessità, di dare a qualunque utente normale privilegi o permessi
+di un altro (o dell'amministratore).
+
+Come nel caso del \acr{pid} e del \acr{ppid}, anche tutti questi
+identificatori possono essere letti attraverso le rispettive funzioni:
+\funcd{getuid}, \funcd{geteuid}, \funcd{getgid} e \funcd{getegid}, i loro
+prototipi sono:
+\begin{functions}
+  \headdecl{unistd.h}
+  \headdecl{sys/types.h}  
+  \funcdecl{uid\_t getuid(void)} Restituisce l'\textsl{user-ID reale} del
+  processo corrente.
 
-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. 
+  \funcdecl{uid\_t geteuid(void)} Restituisce l'\textsl{user-ID effettivo} del
+  processo corrente.
 
-In \secref{sec:file_access_control} vedremo ad esempio come anche 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. 
+  \funcdecl{gid\_t getgid(void)} Restituisce il \textsl{group-ID reale} del
+  processo corrente.
+  
+  \funcdecl{gid\_t getegid(void)} Restituisce il \textsl{group-ID effettivo}
+  del processo corrente.
+  
+  \bodydesc{Queste funzioni non riportano condizioni di errore.}
+\end{functions}
 
-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 ha lanciato un certo processo, e pertanto anche a
-ciascuno di essi è associato un utente e a un gruppo. Un semplice controllo di
-una corrispondenza fra identificativi però non garantisce 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.
+In generale l'uso di privilegi superiori deve essere limitato il più
+possibile, per evitare abusi e problemi di sicurezza, per questo occorre anche
+un meccanismo che consenta ad un programma di rilasciare gli eventuali
+maggiori privilegi necessari, una volta che si siano effettuate le operazioni
+per i quali erano richiesti, e a poterli eventualmente recuperare in caso
+servano di nuovo.
+
+Questo in Linux viene fatto usando altri due gruppi di identificatori, il
+\textit{saved} ed il \textit{filesystem}. Il primo gruppo è lo stesso usato in
+SVr4, e previsto dallo standard POSIX quando è definita la costante
+\macro{\_POSIX\_SAVED\_IDS},\footnote{in caso si abbia a cuore la portabilità
+  del programma su altri Unix è buona norma controllare sempre la
+  disponibilità di queste funzioni controllando se questa costante è
+  definita.} il secondo gruppo è specifico di Linux e viene usato per
+migliorare la sicurezza con NFS.
+
+L'\textsl{user-ID salvato} ed il \textsl{group-ID salvato} sono copie
+dell'\textsl{user-ID effettivo} e del \textsl{group-ID effettivo} del processo
+padre, e vengono impostati dalla funzione \func{exec} all'avvio del processo,
+come copie dell'\textsl{user-ID effettivo} e del \textsl{group-ID effettivo}
+dopo che questi sono stati impostati tenendo conto di eventuali
+\itindex{suid~bit} \acr{suid} o \itindex{sgid~bit} \acr{sgid}.  Essi quindi
+consentono di tenere traccia di quale fossero utente e gruppo effettivi
+all'inizio dell'esecuzione di un nuovo programma.
+
+L'\textsl{user-ID di filesystem} e il \textsl{group-ID di filesystem} sono
+un'estensione introdotta in Linux per rendere più sicuro l'uso di NFS
+(torneremo sull'argomento in sez.~\ref{sec:proc_setuid}). Essi sono una
+replica dei corrispondenti identificatori del gruppo \textit{effective}, ai
+quali si sostituiscono per tutte le operazioni di verifica dei permessi
+relativi ai file (trattate in sez.~\ref{sec:file_perm_overview}).  Ogni
+cambiamento effettuato sugli identificatori effettivi viene automaticamente
+riportato su di essi, per cui in condizioni normali si può tranquillamente
+ignorarne l'esistenza, in quanto saranno del tutto equivalenti ai precedenti.
+
+
+\subsection{Le funzioni di gestione degli identificatori dei processi}
+\label{sec:proc_setuid}
 
-Per questo motivo in generale tutti i processi hanno almeno due gruppi di
-identificatori, chiamati rispettivamente \textsl{reale} e \textsl{effettivo}.
-Al primo gruppo appartengono il \textit{real user ID} e il \textit{real group
-  ID}, che vengono settati al login ai valori corrispondenti all'utente con
-cui si accede al sistema (e relativo gruppo di default), questi normalmente
-non vengono mai cambiati.
+Le due funzioni più comuni che vengono usate per cambiare identità (cioè
+utente e gruppo di appartenenza) ad un processo sono rispettivamente
+\funcd{setuid} e \funcd{setgid}; come accennato in
+sez.~\ref{sec:proc_access_id} in Linux esse seguono la semantica POSIX che
+prevede l'esistenza dell'\textit{user-ID salvato} e del \textit{group-ID
+  salvato}; i loro prototipi sono:
+\begin{functions}
+\headdecl{unistd.h}
+\headdecl{sys/types.h}
 
-Al secondo gruppo appartengono l'\textit{effective user ID} e
-l'\textit{effective group ID} che sono gli identificatori usati nella
-verifiche dei permessi, (ad esempio, come vedremo in
-\secref{sec:file_perm_overview} vengono usati nel controllo di accesso ai
-file). 
+\funcdecl{int setuid(uid\_t uid)} Imposta l'\textsl{user-ID} del processo
+corrente.
 
-Questi normalmente sono identici ai corrispondenti del gruppo reale tranne nel
-caso in cui (come abbiamo accennato in \secref{sec:proc_exec}) il programma
-che si è posto in esecuzione abbia i bit \acr{suid} o \acr{sgid} settati (su
-questo torneremo in maggior dettagli in \secref{sec:file_suid_sgid}) nel qual
-caso essi saranno settati all'utente e al gruppo proprietari del file.
+\funcdecl{int setgid(gid\_t gid)} Imposta il \textsl{group-ID} del processo
+corrente.
 
+\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
+  di fallimento: l'unico errore possibile è \errval{EPERM}.}
+\end{functions}
 
+Il funzionamento di queste due funzioni è analogo, per cui considereremo solo
+la prima; la seconda si comporta esattamente allo stesso modo facendo
+riferimento al \textsl{group-ID} invece che all'\textsl{user-ID}.  Gli
+eventuali \textsl{group-ID supplementari} non vengono modificati.
+
+L'effetto della chiamata è diverso a seconda dei privilegi del processo; se
+l'\textsl{user-ID effettivo} è zero (cioè è quello dell'amministratore di
+sistema) allora tutti gli identificatori (\textit{real}, \textit{effective} e
+\textit{saved}) vengono impostati al valore specificato da \param{uid},
+altrimenti viene impostato solo l'\textsl{user-ID effettivo}, e soltanto se il
+valore specificato corrisponde o all'\textsl{user-ID reale} o
+all'\textsl{user-ID salvato}. Negli altri casi viene segnalato un errore (con
+\errcode{EPERM}).
+
+Come accennato l'uso principale di queste funzioni è quello di poter
+consentire ad un programma con i bit \itindex{suid~bit} \acr{suid} o
+\itindex{sgid~bit} \acr{sgid} impostati (vedi sez.~\ref{sec:file_special_perm})
+di riportare l'\textsl{user-ID effettivo} a quello dell'utente che ha lanciato
+il programma, effettuare il lavoro che non necessita di privilegi aggiuntivi,
+ed eventualmente tornare indietro.
+
+Come esempio per chiarire l'uso di queste funzioni prendiamo quello con cui
+viene gestito l'accesso al file \sysfile{/var/log/utmp}.  In questo file viene
+registrato chi sta usando il sistema al momento corrente; chiaramente non può
+essere lasciato aperto in scrittura a qualunque utente, che potrebbe
+falsificare la registrazione. Per questo motivo questo file (e l'analogo
+\sysfile{/var/log/wtmp} su cui vengono registrati login e logout) appartengono
+ad un gruppo dedicato (\acr{utmp}) ed i programmi che devono accedervi (ad
+esempio tutti i programmi di terminale in X, o il programma \cmd{screen} che
+crea terminali multipli su una console) appartengono a questo gruppo ed hanno
+il bit \acr{sgid} impostato.
+
+Quando uno di questi programmi (ad esempio \cmd{xterm}) viene lanciato, la
+situazione degli identificatori è la seguente:
+\begin{eqnarray*}
+  \label{eq:1}
+  \textsl{group-ID reale}      &=& \textrm{\acr{gid} (del chiamante)} \\
+  \textsl{group-ID effettivo}  &=& \textrm{\acr{utmp}} \\
+  \textsl{group-ID salvato}    &=& \textrm{\acr{utmp}}
+\end{eqnarray*}
+in questo modo, dato che il \textsl{group-ID effettivo} è quello giusto, il
+programma può accedere a \sysfile{/var/log/utmp} in scrittura ed aggiornarlo.
+A questo punto il programma può eseguire una \code{setgid(getgid())} per
+impostare il \textsl{group-ID effettivo} a quello dell'utente (e dato che il
+\textsl{group-ID reale} corrisponde la funzione avrà successo), in questo modo
+non sarà possibile lanciare dal terminale programmi che modificano detto file,
+in tal caso infatti la situazione degli identificatori sarebbe:
+\begin{eqnarray*}
+  \label{eq:2}
+  \textsl{group-ID reale}      &=& \textrm{\acr{gid} (invariato)}  \\
+  \textsl{group-ID effettivo}  &=& \textrm{\acr{gid}} \\
+  \textsl{group-ID salvato}    &=& \textrm{\acr{utmp} (invariato)}
+\end{eqnarray*}
+e ogni processo lanciato dal terminale avrebbe comunque \acr{gid} come
+\textsl{group-ID effettivo}. All'uscita dal terminale, per poter di nuovo
+aggiornare lo stato di \sysfile{/var/log/utmp} il programma eseguirà una
+\code{setgid(utmp)} (dove \var{utmp} è il valore numerico associato al gruppo
+\acr{utmp}, ottenuto ad esempio con una precedente \func{getegid}), dato che
+in questo caso il valore richiesto corrisponde al \textsl{group-ID salvato} la
+funzione avrà successo e riporterà la situazione a:
+\begin{eqnarray*}
+  \label{eq:3}
+  \textsl{group-ID reale}      &=& \textrm{\acr{gid} (invariato)}  \\
+  \textsl{group-ID effettivo}  &=& \textrm{\acr{utmp}} \\
+  \textsl{group-ID salvato}    &=& \textrm{\acr{utmp} (invariato)}
+\end{eqnarray*}
+consentendo l'accesso a \sysfile{/var/log/utmp}.
+
+Occorre però tenere conto che tutto questo non è possibile con un processo con
+i privilegi di amministratore, in tal caso infatti l'esecuzione di una
+\func{setuid} comporta il cambiamento di tutti gli identificatori associati al
+processo, rendendo impossibile riguadagnare i privilegi di amministratore.
+Questo comportamento è corretto per l'uso che ne fa \cmd{login} una volta che
+crea una nuova shell per l'utente; ma quando si vuole cambiare soltanto
+l'\textsl{user-ID effettivo} del processo per cedere i privilegi occorre
+ricorrere ad altre funzioni.
+
+Le due funzioni \funcd{setreuid} e \funcd{setregid} derivano da BSD che, non
+supportando\footnote{almeno fino alla versione 4.3+BSD.} gli identificatori
+del gruppo \textit{saved}, le usa per poter scambiare fra di loro
+\textit{effective} e \textit{real}. I rispettivi prototipi sono:
+\begin{functions}
+\headdecl{unistd.h}
+\headdecl{sys/types.h}
 
+\funcdecl{int setreuid(uid\_t ruid, uid\_t euid)} Imposta l'\textsl{user-ID
+  reale} e l'\textsl{user-ID effettivo} del processo corrente ai valori
+specificati da \param{ruid} e \param{euid}.
+  
+\funcdecl{int setregid(gid\_t rgid, gid\_t egid)} Imposta il \textsl{group-ID
+  reale} ed il \textsl{group-ID effettivo} del processo corrente ai valori
+specificati da \param{rgid} e \param{egid}.
 
-Oltre a questi Linux, seguendo 
+\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
+  di fallimento: l'unico errore possibile è \errval{EPERM}.}
+\end{functions}
 
+La due funzioni sono analoghe ed il loro comportamento è identico; quanto
+detto per la prima riguardo l'user-ID, si applica immediatamente alla seconda
+per il group-ID. I processi non privilegiati possono impostare solo i valori
+del loro user-ID effettivo o reale; valori diversi comportano il fallimento
+della chiamata; l'amministratore invece può specificare un valore qualunque.
+Specificando un argomento di valore -1 l'identificatore corrispondente verrà
+lasciato inalterato.
+
+Con queste funzioni si possono scambiare fra loro gli user-ID reale e
+effettivo, e pertanto è possibile implementare un comportamento simile a
+quello visto in precedenza per \func{setgid}, cedendo i privilegi con un primo
+scambio, e recuperandoli, eseguito il lavoro non privilegiato, con un secondo
+scambio.
+
+In questo caso però occorre porre molta attenzione quando si creano nuovi
+processi nella fase intermedia in cui si sono scambiati gli identificatori, in
+questo caso infatti essi avranno un user-ID reale privilegiato, che dovrà
+essere esplicitamente eliminato prima di porre in esecuzione un nuovo
+programma (occorrerà cioè eseguire un'altra chiamata dopo la \func{fork} e
+prima della \func{exec} per uniformare l'user-ID reale a quello effettivo) in
+caso contrario il nuovo programma potrebbe a sua volta effettuare uno scambio
+e riottenere privilegi non previsti.
+
+Lo stesso problema di propagazione dei privilegi ad eventuali processi figli
+si pone per l'user-ID salvato: questa funzione deriva da un'implementazione che
+non ne prevede la presenza, e quindi non è possibile usarla per correggere la
+situazione come nel caso precedente. Per questo motivo in Linux tutte le volte
+che si imposta un qualunque valore diverso da quello dall'user-ID reale
+corrente, l'user-ID salvato viene automaticamente uniformato al valore
+dell'user-ID effettivo.
+
+Altre due funzioni, \funcd{seteuid} e \funcd{setegid}, sono un'estensione
+dello standard POSIX.1, ma sono comunque supportate dalla maggior parte degli
+Unix; esse vengono usate per cambiare gli identificatori del gruppo
+\textit{effective} ed i loro prototipi sono:
+\begin{functions}
+\headdecl{unistd.h}
+\headdecl{sys/types.h}
+
+\funcdecl{int seteuid(uid\_t uid)} Imposta l'user-ID effettivo del processo
+corrente a \param{uid}.
+
+\funcdecl{int setegid(gid\_t gid)} Imposta il group-ID effettivo del processo
+corrente a \param{gid}.
+
+\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
+  di fallimento: l'unico errore è \errval{EPERM}.}
+\end{functions}
 
-Linux inoltre, per poter rilasciare eventuali privilegi addizionali avuti con
-l'esecuzione di un programma 
+Come per le precedenti le due funzioni sono identiche, per cui tratteremo solo
+la prima. Gli utenti normali possono impostare l'user-ID effettivo solo al
+valore dell'user-ID reale o dell'user-ID salvato, l'amministratore può
+specificare qualunque valore. Queste funzioni sono usate per permettere
+all'amministratore di impostare solo l'user-ID effettivo, dato che l'uso
+normale di \func{setuid} comporta l'impostazione di tutti gli identificatori.
+
+Le due funzioni \funcd{setresuid} e \funcd{setresgid} sono invece
+un'estensione introdotta in Linux,\footnote{per essere precisi a partire dal
+  kernel 2.1.44.}  e permettono un completo controllo su tutti e tre i gruppi
+di identificatori (\textit{real}, \textit{effective} e \textit{saved}), i loro
+prototipi sono:
+\begin{functions}
+\headdecl{unistd.h}
+\headdecl{sys/types.h}
 
+\funcdecl{int setresuid(uid\_t ruid, uid\_t euid, uid\_t suid)} Imposta
+l'user-ID reale, l'user-ID effettivo e l'user-ID salvato del processo corrente
+ai valori specificati rispettivamente da \param{ruid}, \param{euid} e
+\param{suid}.
+  
+\funcdecl{int setresgid(gid\_t rgid, gid\_t egid, gid\_t sgid)} Imposta il
+group-ID reale, il group-ID effettivo ed il group-ID salvato del processo
+corrente ai valori specificati rispettivamente da \param{rgid}, \param{egid} e
+\param{sgid}.
+
+\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
+  di fallimento: l'unico errore è \errval{EPERM}.}
+\end{functions}
+
+Le due funzioni sono identiche, quanto detto per la prima riguardo gli user-ID
+si applica alla seconda per i group-ID. I processi non privilegiati possono
+cambiare uno qualunque degli user-ID solo ad un valore corrispondente o
+all'user-ID reale, o a quello effettivo o a quello salvato, l'amministratore
+può specificare i valori che vuole; un valore di -1 per un qualunque argomento
+lascia inalterato l'identificatore corrispondente.
+
+Per queste funzioni esistono anche due controparti che permettono di leggere
+in blocco i vari identificatori: \funcd{getresuid} e \funcd{getresgid}; i loro
+prototipi sono: 
+\begin{functions}
+\headdecl{unistd.h}
+\headdecl{sys/types.h}
+
+\funcdecl{int getresuid(uid\_t *ruid, uid\_t *euid, uid\_t *suid)} Legge
+l'user-ID reale, l'user-ID effettivo e l'user-ID salvato del processo corrente.
+  
+\funcdecl{int getresgid(gid\_t *rgid, gid\_t *egid, gid\_t *sgid)} Legge il
+group-ID reale, il group-ID effettivo e il group-ID salvato del processo
+corrente.
+
+\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso di
+  fallimento: l'unico errore possibile è \errval{EFAULT} se gli indirizzi delle
+  variabili di ritorno non sono validi.}
+\end{functions}
+
+Anche queste funzioni sono un'estensione specifica di Linux, e non richiedono
+nessun privilegio. I valori sono restituiti negli argomenti, che vanno
+specificati come puntatori (è un altro esempio di
+\itindex{value~result~argument} \textit{value result argument}). Si noti che
+queste funzioni sono le uniche in grado di leggere gli identificatori del
+gruppo \textit{saved}.
+
+
+Infine le funzioni \func{setfsuid} e \func{setfsgid} servono per impostare gli
+identificatori del gruppo \textit{filesystem} che sono usati da Linux per il
+controllo dell'accesso ai file.  Come già accennato in
+sez.~\ref{sec:proc_access_id} Linux definisce questo ulteriore gruppo di
+identificatori, che in circostanze normali sono assolutamente equivalenti a
+quelli del gruppo \textit{effective}, dato che ogni cambiamento di questi
+ultimi viene immediatamente riportato su di essi.
+
+C'è un solo caso in cui si ha necessità di introdurre una differenza fra gli
+identificatori dei gruppi \textit{effective} e \textit{filesystem}, ed è per
+ovviare ad un problema di sicurezza che si presenta quando si deve
+implementare un server NFS. 
+
+Il server NFS infatti deve poter cambiare l'identificatore con cui accede ai
+file per assumere l'identità del singolo utente remoto, ma se questo viene
+fatto cambiando l'user-ID effettivo o l'user-ID reale il server si espone alla
+ricezione di eventuali segnali ostili da parte dell'utente di cui ha
+temporaneamente assunto l'identità.  Cambiando solo l'user-ID di filesystem si
+ottengono i privilegi necessari per accedere ai file, mantenendo quelli
+originari per quanto riguarda tutti gli altri controlli di accesso, così che
+l'utente non possa inviare segnali al server NFS.
+
+Le due funzioni usate per cambiare questi identificatori sono \funcd{setfsuid}
+e \funcd{setfsgid}, ovviamente sono specifiche di Linux e non devono essere
+usate se si intendono scrivere programmi portabili; i loro prototipi sono:
+\begin{functions}
+\headdecl{sys/fsuid.h}
+
+\funcdecl{int setfsuid(uid\_t fsuid)} Imposta l'user-ID di filesystem del
+processo corrente a \param{fsuid}.
+
+\funcdecl{int setfsgid(gid\_t fsgid)} Imposta il group-ID di filesystem del
+processo corrente a \param{fsgid}.
+
+\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
+  di fallimento: l'unico errore possibile è \errval{EPERM}.}
+\end{functions}
+\noindent queste funzioni hanno successo solo se il processo chiamante ha i
+privilegi di amministratore o, per gli altri utenti, se il valore specificato
+coincide con uno dei di quelli del gruppo \textit{real}, \textit{effective} o
+\textit{saved}.
+
+
+\subsection{Le funzioni per la gestione dei gruppi associati a un processo}
+\label{sec:proc_setgroups}
+
+Le ultime funzioni che esamineremo sono quelle che permettono di operare sui
+gruppi supplementari cui un utente può appartenere. Ogni processo può avere
+almeno \const{NGROUPS\_MAX} gruppi supplementari\footnote{il numero massimo di
+  gruppi secondari può essere ottenuto con \func{sysconf} (vedi
+  sez.~\ref{sec:sys_sysconf}), leggendo il parametro
+  \texttt{\_SC\_NGROUPS\_MAX}.} in aggiunta al gruppo primario; questi vengono
+ereditati dal processo padre e possono essere cambiati con queste funzioni.
+
+La funzione che permette di leggere i gruppi supplementari associati ad un
+processo è \funcd{getgroups}; questa funzione è definita nello standard
+POSIX.1, ed il suo prototipo è:
+\begin{functions}
+  \headdecl{sys/types.h}
+  \headdecl{unistd.h}
+  
+  \funcdecl{int getgroups(int size, gid\_t list[])} 
+  
+  Legge gli identificatori dei gruppi supplementari.
+  
+  \bodydesc{La funzione restituisce il numero di gruppi letti in caso di
+    successo e -1 in caso di fallimento, nel qual caso \var{errno} assumerà
+    i valori: 
+    \begin{errlist}
+    \item[\errcode{EFAULT}] \param{list} non ha un indirizzo valido.
+    \item[\errcode{EINVAL}] il valore di \param{size} è diverso da zero ma
+      minore del numero di gruppi supplementari del processo.
+    \end{errlist}}
+\end{functions}
+
+La funzione legge gli identificatori dei gruppi supplementari del processo sul
+vettore \param{list} di dimensione \param{size}. Non è specificato se la
+funzione inserisca o meno nella lista il group-ID effettivo del processo. Se si
+specifica un valore di \param{size} uguale a 0 \param{list} non viene
+modificato, ma si ottiene il numero di gruppi supplementari.
+
+Una seconda funzione, \funcd{getgrouplist}, può invece essere usata per
+ottenere tutti i gruppi a cui appartiene un certo utente; il suo prototipo è:
+\begin{functions}
+  \headdecl{sys/types.h} 
+  \headdecl{grp.h}
+  
+  \funcdecl{int getgrouplist(const char *user, gid\_t group, gid\_t *groups,
+    int *ngroups)} Legge i gruppi supplementari.
+  
+  \bodydesc{La funzione legge fino ad un massimo di \param{ngroups} valori,
+    restituisce 0 in caso di successo e -1 in caso di fallimento.}
+\end{functions}
+
+La funzione legge i gruppi supplementari dell'utente specificato da
+\param{user}, eseguendo una scansione del database dei gruppi (si veda
+sez.~\ref{sec:sys_user_group}). Ritorna poi in \param{groups} la lista di
+quelli a cui l'utente appartiene. Si noti che \param{ngroups} è passato come
+puntatore perché, qualora il valore specificato sia troppo piccolo, la
+funzione ritorna -1, passando indietro il numero dei gruppi trovati.
+
+Per impostare i gruppi supplementari di un processo ci sono due funzioni, che
+possono essere usate solo se si hanno i privilegi di amministratore. La prima
+delle due è \funcd{setgroups}, ed il suo prototipo è:
+\begin{functions}
+  \headdecl{sys/types.h}
+  \headdecl{grp.h}
+  
+  \funcdecl{int setgroups(size\_t size, gid\_t *list)} 
+  
+  Imposta i gruppi supplementari del processo.
+
+  \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+    fallimento, nel qual caso \var{errno} assumerà i valori:
+    \begin{errlist}
+    \item[\errcode{EFAULT}] \param{list} non ha un indirizzo valido.
+    \item[\errcode{EPERM}] il processo non ha i privilegi di amministratore.
+    \item[\errcode{EINVAL}] il valore di \param{size} è maggiore del valore
+    massimo consentito.
+    \end{errlist}}
+\end{functions}
+
+La funzione imposta i gruppi supplementari del processo corrente ai valori
+specificati nel vettore passato con l'argomento \param{list}, di dimensioni
+date dall'argomento \param{size}. Il numero massimo di gruppi supplementari è
+un parametro di sistema, che può essere ricavato con le modalità spiegate in
+sez.~\ref{sec:sys_characteristics}.
+
+Se invece si vogliono impostare i gruppi supplementari del processo a quelli di
+un utente specifico, si può usare \funcd{initgroups} il cui prototipo è:
+\begin{functions}
+  \headdecl{sys/types.h}
+  \headdecl{grp.h}
+
+  \funcdecl{int initgroups(const char *user, gid\_t group)} 
+  
+  Inizializza la lista dei gruppi supplementari.
+  
+  \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+    fallimento, nel qual caso \var{errno} assumerà gli stessi valori di
+    \func{setgroups} più \errval{ENOMEM} quando non c'è memoria sufficiente
+    per allocare lo spazio per informazioni dei gruppi.}
+\end{functions}
+
+La funzione esegue la scansione del database dei gruppi (usualmente
+\conffile{/etc/group}) cercando i gruppi di cui è membro l'utente \param{user}
+con cui costruisce una lista di gruppi supplementari, a cui aggiunge anche
+\param{group}, infine imposta questa lista per il processo corrente usando
+\func{setgroups}.  Si tenga presente che sia \func{setgroups} che
+\func{initgroups} non sono definite nello standard POSIX.1 e che pertanto non
+è possibile utilizzarle quando si definisce \macro{\_POSIX\_SOURCE} o si
+compila con il flag \cmd{-ansi}, è pertanto meglio evitarle se si vuole
+scrivere codice portabile.
+
+\section{La gestione della priorità dei processi}
+\label{sec:proc_priority}
+
+In questa sezione tratteremo più approfonditamente i meccanismi con il quale
+lo \itindex{scheduler} \textit{scheduler} assegna la CPU ai vari processi
+attivi.  In particolare prenderemo in esame i vari meccanismi con cui viene
+gestita l'assegnazione del tempo di CPU, ed illustreremo le varie funzioni di
+gestione. Tratteremo infine anche le altre priorità dei processi (come quelle
+per l'accesso a disco) divenute disponibili con i kernel più recenti.
+
+
+\subsection{I meccanismi di \textit{scheduling}}
+\label{sec:proc_sched}
+
+\itindbeg{scheduler}
+
+La scelta di un meccanismo che sia in grado di distribuire in maniera efficace
+il tempo di CPU per l'esecuzione dei processi è sempre una questione delicata,
+ed oggetto di numerose ricerche; in generale essa dipende in maniera
+essenziale anche dal tipo di utilizzo che deve essere fatto del sistema, per
+cui non esiste un meccanismo che sia valido per tutti gli usi.
+
+La caratteristica specifica di un sistema multitasking come Linux è quella del
+cosiddetto \itindex{preemptive~multitasking} \textit{preemptive
+  multitasking}: questo significa che al contrario di altri sistemi (che usano
+invece il cosiddetto \itindex{cooperative~multitasking} \textit{cooperative
+  multitasking}) non sono i singoli processi, ma il kernel stesso a decidere
+quando la CPU deve essere passata ad un altro processo. Come accennato in
+sez.~\ref{sec:proc_hierarchy} questa scelta viene eseguita da una sezione
+apposita del kernel, lo \textit{scheduler}, il cui scopo è quello di
+distribuire al meglio il tempo di CPU fra i vari processi.
+
+La cosa è resa ancora più complicata dal fatto che con le architetture
+multi-processore si deve anche scegliere quale sia la CPU più opportuna da
+utilizzare.\footnote{nei processori moderni la presenza di ampie cache può
+  rendere poco efficiente trasferire l'esecuzione di un processo da una CPU ad
+  un'altra, per cui effettuare la migliore scelta fra le diverse CPU non è
+  banale.}  Tutto questo comunque appartiene alle sottigliezze
+dell'implementazione del kernel; dal punto di vista dei programmi che girano
+in user space, anche quando si hanno più processori (e dei processi che sono
+eseguiti davvero in contemporanea), le politiche di scheduling riguardano
+semplicemente l'allocazione della risorsa \textsl{tempo di esecuzione}, la cui
+assegnazione sarà governata dai meccanismi di scelta delle priorità che
+restano gli stessi indipendentemente dal numero di processori.
+
+Si tenga conto poi che i processi non devono solo eseguire del codice: ad
+esempio molto spesso saranno impegnati in operazioni di I/O, o potranno
+venire bloccati da un comando dal terminale, o sospesi per un certo periodo di
+tempo.  In tutti questi casi la CPU diventa disponibile ed è compito dello
+kernel provvedere a mettere in esecuzione un altro processo.
+
+Tutte queste possibilità sono caratterizzate da un diverso \textsl{stato} del
+processo, in Linux un processo può trovarsi in uno degli stati riportati in
+tab.~\ref{tab:proc_proc_states}; ma soltanto i processi che sono nello stato
+\textbf{Runnable} concorrono per l'esecuzione. Questo vuol dire che, qualunque
+sia la sua priorità, un processo non potrà mai essere messo in esecuzione
+fintanto che esso si trova in uno qualunque degli altri stati.
 
 \begin{table}[htb]
   \footnotesize
   \centering
-  \begin{tabular}[c]{|c|l|p{8cm}|}
+  \begin{tabular}[c]{|p{2.4cm}|c|p{9cm}|}
     \hline
-    \textbf{Sigla} & \textbf{Significato} & \textbf{Utilizzo} \\ 
+    \textbf{Stato} & \texttt{STAT} & \textbf{Descrizione} \\
     \hline
     \hline
-    \acr{ruid} & \textit{real user id} & indica l'utente reale che ha lanciato
-    il programma\\ 
-    \acr{rgid} & \textit{real group id} & indica il gruppo reale dell'utente 
-    che ha lanciato il programma \\ 
-    \acr{euid} & \textit{effective user id} & indica l'utente effettivo usato
-    dal programma \\ 
-    \acr{egid} & \textit{effective group id} & indica il gruppo effettivo usato
-    dal programma \\ 
-               & \textit{supplementary group id} & indica i gruppi cui
-    l'utente appartiene  \\ 
-    \acr{suid} & \textit{saved user id} & indica l'utente  \\ 
-    \acr{sgid} & \textit{saved group id} & indica il gruppo  \\ 
-    \acr{fsuid} & \textit{filesystem user id} & indica l'utente effettivo per
-    il filesystem \\ 
-    \acr{fsgid} & \textit{filesystem group id} & indica il gruppo effettivo
-    per il filesystem  \\ 
+    \textbf{Runnable}& \texttt{R} & Il processo è in esecuzione o è pronto ad
+                                    essere eseguito (cioè è in attesa che gli
+                                    venga assegnata la CPU).\\
+    \textbf{Sleep}   & \texttt{S} & Il processo  è in attesa di un
+                                    risposta dal sistema, ma può essere 
+                                    interrotto da un segnale.\\
+    \textbf{Uninterrutible Sleep}& \texttt{D} & Il  processo è in
+                                    attesa di un risposta dal sistema (in 
+                                    genere per I/O), e non può essere
+                                    interrotto in nessuna circostanza.\\
+    \textbf{Stopped} & \texttt{T} & Il processo è stato fermato con un
+                                    \const{SIGSTOP}, o è tracciato.\\
+    \textbf{Zombie}\index{zombie} & \texttt{Z} & Il processo è terminato ma il
+                                    suo stato di terminazione non è ancora
+                                    stato letto dal padre.\\
+    \textbf{Killable}& \texttt{D} & Un nuovo stato introdotto con il kernel
+                                    2.6.25, sostanzialmente identico
+                                    all'\textbf{Uninterrutible Sleep} con la
+                                    sola differenza che il processo può
+                                    terminato con \const{SIGKILL} (usato per
+                                    lo più per NFS).\\ 
     \hline
   \end{tabular}
-  \caption{Identificatori di utente e gruppo associati a ciascun processo.}
-  \label{tab:proc_uid_gid}
+  \caption{Elenco dei possibili stati di un processo in Linux, nella colonna
+    \texttt{STAT} si è riportata la corrispondente lettera usata dal comando 
+    \cmd{ps} nell'omonimo campo.}
+  \label{tab:proc_proc_states}
 \end{table}
 
-Il \textit{real user id} e il \textit{real group id} indicano l'utente che ha
-lanciato il processo, e vengono settati al login al valore standard di
-\acr{uid} e \acr{gid} dell'utente letti direttamente da \file{/etc/passwd}.
-
-Esso servono ad identificare l'utente che ha lanciato il processo e non
-vengono mai cambiati nella creazione di nuovi processi restando sempre gli
-stessi per tutti i processi avviati in una sessione. In realtà vedremo che è
-possibile possibile modificarli (in \secref{sec:proc_setuid}), ma solo ad un
-processo che abbia i privilegi di amministratore; questa possibilità è usata
-ad esempio da \cmd{login} che una volta completata la procedura di
-autenticazione lancia una shell per la quale setta questi identificatori ai
-valori corrispondenti all'utente che entra nel sistema.
-
-L'\textit{effective user id}, l'\textit{effective group id} e gli eventuali
-\textit{supplementary group id} sono invece gli identificatori usati per il
-controllo di accesso ai file (secondo quanto descritto in dettaglio in
-\secref{sec:file_perm_overview}). Normalmente essi sono uguali al \textit{real
-  user id} e al \textit{real group id}, a meno che il file posto in esecuzione
-non abbia o il bit \acr{suid} o il bit \acr{sgid} settato, in questo caso alla
-la funzione \func{exec} (vedi \secref{}) li setta rispettivamente ai valori
-dell'\acr{uid} e del \acr{gid} cui appartiene il file.
-
-Il \textit{saved user id} e il \textit{saved group id} sono copie
-dell'\textit{effective user id} e dell'\textit{effective group id} del
-processo padre, e vengono settati dalla funzione \func{exec} all'avvio del
-processo, prima che \textit{effective user id} e \textit{effective group id}
-vengano modificati per tener conto di eventuali \acr{suid} o \acr{sgid}, essi
-quindi consentono di tenere traccia di quale fossero l'utente originale.
-
-
-\subsection{Le funzioni \texttt{setuid} e \texttt{setgid}}
-\label{sec:proc_setuid}
+Si deve quindi tenere presente che l'utilizzo della CPU è soltanto una delle
+risorse che sono necessarie per l'esecuzione di un programma, e a seconda
+dello scopo del programma non è detto neanche che sia la più importante (molti
+programmi dipendono in maniera molto più critica dall'I/O). Per questo motivo
+non è affatto detto che dare ad un programma la massima priorità di esecuzione
+abbia risultati significativi in termini di prestazioni.
+
+Il meccanismo tradizionale di scheduling di Unix (che tratteremo in
+sez.~\ref{sec:proc_sched_stand}) è sempre stato basato su delle
+\textsl{priorità dinamiche}, in modo da assicurare che tutti i processi, anche
+i meno importanti, possano ricevere un po' di tempo di CPU. In sostanza quando
+un processo ottiene la CPU la sua priorità viene diminuita. In questo modo
+alla fine, anche un processo con priorità iniziale molto bassa, finisce per
+avere una priorità sufficiente per essere eseguito.
+
+Lo standard POSIX.1b però ha introdotto il concetto di \textsl{priorità
+  assoluta}, (chiamata anche \textsl{priorità statica}, in contrapposizione
+alla normale priorità dinamica), per tenere conto dei sistemi
+real-time,\footnote{per sistema real-time si intende un sistema in grado di
+  eseguire operazioni in un tempo ben determinato; in genere si tende a
+  distinguere fra l'\textit{hard real-time} in cui è necessario che i tempi di
+  esecuzione di un programma siano determinabili con certezza assoluta (come
+  nel caso di meccanismi di controllo di macchine, dove uno sforamento dei
+  tempi avrebbe conseguenze disastrose), e \textit{soft-real-time} in cui un
+  occasionale sforamento è ritenuto accettabile.} in cui è vitale che i
+processi che devono essere eseguiti in un determinato momento non debbano
+aspettare la conclusione di altri che non hanno questa necessità.
+
+Il concetto di priorità assoluta dice che quando due processi si contendono
+l'esecuzione, vince sempre quello con la priorità assoluta più alta.
+Ovviamente questo avviene solo per i processi che sono pronti per essere
+eseguiti (cioè nello stato \textit{runnable}).  La priorità assoluta viene in
+genere indicata con un numero intero, ed un valore più alto comporta una
+priorità maggiore. Su questa politica di scheduling torneremo in
+sez.~\ref{sec:proc_real_time}.
+
+In generale quello che succede in tutti gli Unix moderni è che ai processi
+normali viene sempre data una priorità assoluta pari a zero, e la decisione di
+assegnazione della CPU è fatta solo con il meccanismo tradizionale della
+priorità dinamica. In Linux tuttavia è possibile assegnare anche una priorità
+assoluta, nel qual caso un processo avrà la precedenza su tutti gli altri di
+priorità inferiore, che saranno eseguiti solo quando quest'ultimo non avrà
+bisogno della CPU.
+
+
+\subsection{Il meccanismo di \textit{scheduling} standard}
+\label{sec:proc_sched_stand}
+
+A meno che non si abbiano esigenze specifiche,\footnote{per alcune delle quali
+  sono state introdotte delle varianti specifiche.} l'unico meccanismo di
+scheduling con il quale si avrà a che fare è quello tradizionale, che prevede
+solo priorità dinamiche. È di questo che, di norma, ci si dovrà preoccupare
+nella programmazione.  Come accennato in Linux i processi ordinari hanno tutti
+una priorità assoluta nulla; quello che determina quale, fra tutti i processi
+in attesa di esecuzione, sarà eseguito per primo, è la cosiddetta
+\textsl{priorità dinamica},\footnote{quella che viene mostrata nella colonna
+  \texttt{PR} del comando \texttt{top}.} che è chiamata così proprio perché
+varia nel corso dell'esecuzione di un processo.
+
+Il meccanismo usato da Linux è in realtà piuttosto complesso,\footnote{e
+  dipende strettamente dalla versione di kernel; in particolare a partire
+  dalla serie 2.6.x lo scheduler è stato riscritto completamente, con molte
+  modifiche susseguitesi per migliorarne le prestazioni, per un certo periodo
+  ed è stata anche introdotta la possibilità di usare diversi algoritmi,
+  selezionabili sia in fase di compilazione, che, nelle versioni più recenti,
+  all'avvio (addirittura è stato ideato un sistema modulare che permette di
+  cambiare lo scheduler a sistema attivo).} ma a grandi linee si può dire che
+ad ogni processo è assegnata una \textit{time-slice}, cioè un intervallo di
+tempo (letteralmente una fetta) per il quale, a meno di eventi esterni, esso
+viene eseguito senza essere interrotto.  Inoltre la priorità dinamica viene
+calcolata dallo scheduler a partire da un valore iniziale che viene
+\textsl{diminuito} tutte le volte che un processo è in stato \textbf{Runnable}
+ma non viene posto in esecuzione.\footnote{in realtà il calcolo della priorità
+  dinamica e la conseguente scelta di quale processo mettere in esecuzione
+  avviene con un algoritmo molto più complicato, che tiene conto anche della
+  \textsl{interattività} del processo, utilizzando diversi fattori, questa è
+  una brutale semplificazione per rendere l'idea del funzionamento, per una
+  trattazione più dettagliata, anche se non aggiornatissima, dei meccanismi di
+  funzionamento dello scheduler si legga il quarto capitolo di
+  \cite{LinKernDev}.} Lo scheduler infatti mette sempre in esecuzione, fra
+tutti i processi in stato \textbf{Runnable}, quello che ha il valore di
+priorità dinamica più basso.\footnote{con le priorità dinamiche il significato
+  del valore numerico ad esse associato è infatti invertito, un valore più
+  basso significa una priorità maggiore.} Il fatto che questo valore venga
+diminuito quando un processo non viene posto in esecuzione pur essendo pronto,
+significa che la priorità dei processi che non ottengono l'uso del processore
+viene progressivamente incrementata, così che anche questi alla fine hanno la
+possibilità di essere eseguiti.
+
+Sia la dimensione della \textit{time-slice} che il valore di partenza della
+priorità dinamica sono determinate dalla cosiddetta \textit{nice} (o
+\textit{niceness}) del processo.\footnote{questa è una delle tante proprietà
+  che ciascun processo si porta dietro, essa viene ereditata dai processi
+  figli e mantenuta attraverso una \func{exec}; fino alla serie 2.4 essa era
+  mantenuta nell'omonimo campo \texttt{nice} della \texttt{task\_struct}, con
+  la riscrittura dello scheduler eseguita nel 2.6 viene mantenuta nel campo
+  \texttt{static\_prio} come per le priorità statiche.} L'origine del nome di
+questo parametro sta nel fatto che generalmente questo viene usato per
+\textsl{diminuire} la priorità di un processo, come misura di cortesia nei
+confronti degli altri.  I processi infatti vengono creati dal sistema con un
+valore di \var{nice} nullo e nessuno è privilegiato rispetto agli altri;
+specificando un valore positivo si avrà una \textit{time-slice} più breve ed
+un valore di priorità dinamica iniziale più alto, mentre un valore negativo
+darà una \textit{time-slice} più lunga ed un valore di priorità dinamica
+iniziale più basso.
+
+Esistono diverse funzioni che consentono di modificare la \textit{niceness} di
+un processo; la più semplice è funzione \funcd{nice}, che opera sul processo
+corrente, il suo prototipo è:
+\begin{prototype}{unistd.h}
+{int nice(int inc)}
+  Aumenta il valore di \var{nice} per il processo corrente.
+  
+  \bodydesc{La funzione ritorna zero o il nuovo valore di \var{nice} in caso
+    di successo e -1 in caso di errore, nel qual caso \var{errno} può assumere
+    i valori:
+  \begin{errlist}
+  \item[\errcode{EPERM}] non si ha il permesso di specificare un valore
+    di \param{inc} negativo. 
+  \end{errlist}}
+\end{prototype}
+
+L'argomento \param{inc} indica l'incremento da effettuare rispetto al valore
+di \var{nice} corrente: quest'ultimo può assumere valori compresi fra
+\const{PRIO\_MIN} e \const{PRIO\_MAX}; nel caso di Linux sono fra $-20$ e
+$19$,\footnote{in realtà l'intervallo varia a seconda delle versioni di
+  kernel, ed è questo a partire dal kernel 1.3.43, anche se oggi si può avere
+  anche l'intervallo fra $-20$ e $20$.} ma per \param{inc} si può specificare
+un valore qualunque, positivo o negativo, ed il sistema provvederà a troncare
+il risultato nell'intervallo consentito. Valori positivi comportano maggiore
+\textit{cortesia} e cioè una diminuzione della priorità, valori negativi
+comportano invece un aumento della priorità. Con i kernel precedenti il
+2.6.12 solo l'amministratore\footnote{o un processo con la
+  \itindex{capabilities} \textit{capability} \const{CAP\_SYS\_NICE}, vedi
+  sez.~\ref{sec:proc_capabilities}.} può specificare valori negativi
+di \param{inc} che permettono di aumentare la priorità di un processo, a
+partire da questa versione è consentito anche agli utenti normali alzare
+(entro certi limiti, che vedremo più avanti) la priorità dei propri processi.
+
+Gli standard SUSv2 e POSIX.1 prevedono che la funzione ritorni il nuovo valore
+di \var{nice} del processo; tuttavia la system call di Linux non segue questa
+convenzione e restituisce sempre 0 in caso di successo e $-1$ in caso di
+errore; questo perché $-1$ è un valore di \var{nice} legittimo e questo
+comporta una confusione con una eventuale condizione di errore. La system call
+originaria inoltre non consente, se non dotati di adeguati privilegi, di
+diminuire un valore di \var{nice} precedentemente innalzato.
+Fino alle \acr{glibc} 2.2.4 la funzione di libreria riportava direttamente il
+risultato dalla system call, violando lo standard, per cui per ottenere il
+nuovo valore occorreva una successiva chiamata alla funzione
+\func{getpriority}. A partire dalla \acr{glibc} 2.2.4 \func{nice} è stata
+reimplementata e non viene più chiamata la omonima system call, con questa
+versione viene restituito come valore di ritorno il valore di \var{nice}, come
+richiesto dallo standard.\footnote{questo viene fatto chiamando al suo interno
+  \func{setpriority}, che tratteremo a breve.}  In questo caso l'unico modo
+per rilevare in maniera affidabile una condizione di errore è quello di
+azzerare \var{errno} prima della chiamata della funzione e verificarne il
+valore quando \func{nice} restituisce $-1$.
+
+Per leggere il valore di \textit{nice} di un processo occorre usare la
+funzione \funcd{getpriority}, derivata da BSD; il suo prototipo è:
+\begin{prototype}{sys/resource.h}
+{int getpriority(int which, int who)}
+  
+Restituisce il valore di \var{nice} per l'insieme dei processi specificati.
+
+  \bodydesc{La funzione ritorna la priorità in caso di successo e -1 in caso di
+    errore, nel qual caso \var{errno} può assumere i valori:
+  \begin{errlist}
+  \item[\errcode{ESRCH}] non c'è nessun processo che corrisponda ai valori di
+  \param{which} e \param{who}.
+  \item[\errcode{EINVAL}] il valore di \param{which} non è valido.
+  \end{errlist}}
+\end{prototype}
+\noindent nelle vecchie versioni può essere necessario includere anche
+\file{<sys/time.h>}, questo non è più necessario con versioni recenti delle
+librerie, ma è comunque utile per portabilità.
+
+La funzione permette, a seconda del valore di \param{which}, di leggere la
+priorità di un processo, di un gruppo di processi (vedi
+sez.~\ref{sec:sess_proc_group}) o di un utente, specificando un corrispondente
+valore per \param{who} secondo la legenda di tab.~\ref{tab:proc_getpriority};
+un valore nullo di quest'ultimo indica il processo, il gruppo di processi o
+l'utente correnti.
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|c|c|l|}
+    \hline
+    \param{which} & \param{who} & \textbf{Significato} \\
+    \hline
+    \hline
+    \const{PRIO\_PROCESS} & \type{pid\_t} & processo  \\
+    \const{PRIO\_PRGR}    & \type{pid\_t} & \itindex{process~group}
+                                            \textit{process group}  \\ 
+    \const{PRIO\_USER}    & \type{uid\_t} & utente \\
+    \hline
+  \end{tabular}
+  \caption{Legenda del valore dell'argomento \param{which} e del tipo
+    dell'argomento \param{who} delle funzioni \func{getpriority} e
+    \func{setpriority} per le tre possibili scelte.}
+  \label{tab:proc_getpriority}
+\end{table}
+
+La funzione restituisce la priorità più alta (cioè il valore più basso) fra
+quelle dei processi specificati; di nuovo, dato che $-1$ è un valore
+possibile, per poter rilevare una condizione di errore è necessario cancellare
+sempre \var{errno} prima della chiamata alla funzione per verificare che essa
+resti uguale a zero.
+
+Analoga a \func{getpriority} è la funzione \funcd{setpriority} che permette di
+impostare la priorità di uno o più processi; il suo prototipo è:
+\begin{prototype}{sys/resource.h}
+{int setpriority(int which, int who, int prio)}  
+  Imposta la priorità per l'insieme dei processi specificati.
+
+  \bodydesc{La funzione ritorna la priorità in caso di successo e -1 in caso di
+    errore, nel qual caso \var{errno} può assumere i valori:
+  \begin{errlist}
+  \item[\errcode{ESRCH}] non c'è nessun processo che corrisponda ai valori di
+  \param{which} e \param{who}.
+  \item[\errcode{EINVAL}] il valore di \param{which} non è valido.
+  \item[\errcode{EACCES}] si è richiesto un aumento di priorità senza avere
+    sufficienti privilegi.
+  \item[\errcode{EPERM}] un processo senza i privilegi di amministratore ha
+    cercato di modificare la priorità di un processo di un altro utente.
+  \end{errlist}}
+\end{prototype}
+
+La funzione imposta la priorità al valore specificato da \param{prio} per
+tutti i processi indicati dagli argomenti \param{which} e \param{who}. In
+questo caso come valore di \param{prio} deve essere specificato il valore di
+\textit{nice} da assegnare, e non un incremento (positivo o negativo) come nel
+caso di \func{nice}. La funzione restituisce il valore di \textit{nice}
+assegnato in caso di successo e $-1$ in caso di errore, e come per \func{nice}
+anche in questo caso per rilevare un errore occorre sempre porre a zero
+\var{errno} prima della chiamata della funzione, essendo $-1$ un valore di
+\textit{nice} valido. 
+
+Si tenga presente che solo l'amministratore\footnote{o più precisamente un
+  processo con la \itindex{capabilities} \textit{capability}
+  \const{CAP\_SYS\_NICE}, vedi sez.~\ref{sec:proc_capabilities}.} ha la
+possibilità di modificare arbitrariamente le priorità di qualunque
+processo. Un utente normale infatti può modificare solo la priorità dei suoi
+processi ed in genere soltanto diminuirla.  Fino alla versione di kernel
+2.6.12 Linux ha seguito le specifiche dello standard SUSv3, e come per tutti i
+sistemi derivati da SysV veniva richiesto che l'user-ID reale o quello
+effettivo del processo chiamante corrispondessero all'user-ID reale (e solo a
+quello) del processo di cui si intendeva cambiare la priorità. A partire dalla
+versione 2.6.12 è stata adottata la semantica in uso presso i sistemi derivati
+da BSD (SunOS, Ultrix, *BSD), in cui la corrispondenza può essere anche con
+l'user-ID effettivo.
+
+Sempre a partire dal kernel 2.6.12 è divenuto possibile anche per gli utenti
+ordinari poter aumentare la priorità dei propri processi specificando un
+valore di \param{prio} negativo. Questa operazione non è possibile però in
+maniera indiscriminata, ed in particolare può essere effettuata solo
+nell'intervallo consentito dal valore del limite \const{RLIMIT\_NICE}
+(torneremo su questo in sez.~\ref{sec:sys_resource_limit}).
+
+
+\subsection{Il meccanismo di \textit{scheduling real-time}}
+\label{sec:proc_real_time}
+
+Come spiegato in sez.~\ref{sec:proc_sched} lo standard POSIX.1b ha introdotto
+le priorità assolute per permettere la gestione di processi real-time. In
+realtà nel caso di Linux non si tratta di un vero hard real-time, in quanto in
+presenza di eventuali interrupt il kernel interrompe l'esecuzione di un
+processo qualsiasi sia la sua priorità,\footnote{questo a meno che non si
+  siano installate le patch di RTLinux, RTAI o Adeos, con i quali è possibile
+  ottenere un sistema effettivamente hard real-time. In tal caso infatti gli
+  interrupt vengono intercettati dall'interfaccia real-time (o nel caso di
+  Adeos gestiti dalle code del nano-kernel), in modo da poterli controllare
+  direttamente qualora ci sia la necessità di avere un processo con priorità
+  più elevata di un \textit{interrupt handler}.} mentre con l'incorrere in un
+\itindex{page~fault} \textit{page fault} si possono avere ritardi non
+previsti.  Se l'ultimo problema può essere aggirato attraverso l'uso delle
+funzioni di controllo della memoria virtuale (vedi
+sez.~\ref{sec:proc_mem_lock}), il primo non è superabile e può comportare
+ritardi non prevedibili riguardo ai tempi di esecuzione di qualunque processo.
+
+Nonostante questo, ed in particolare con una serie di miglioramenti che sono
+stati introdotti nello sviluppo del kernel,\footnote{in particolare a partire
+  dalla versione 2.6.18 sono stati inserite nel kernel una serie di modifiche
+  che consentono di avvicinarsi sempre di più ad un vero e proprio sistema
+  \textit{real-time} estendendo il concetto di \textit{preemption} alle
+  operazioni dello stesso kernel; esistono vari livelli a cui questo può
+  essere fatto, ottenibili attivando in fase di compilazione una fra le
+  opzioni \texttt{CONFIG\_PREEMPT\_NONE}, \texttt{CONFIG\_PREEMPT\_VOLUNTARY}
+  e \texttt{CONFIG\_PREEMPT\_DESKTOP}.} si può arrivare ad una ottima
+approssimazione di sistema real-time usando le priorità assolute; occorre
+farlo però con molta attenzione: se si dà ad un processo una priorità assoluta
+e questo finisce in un loop infinito, nessun altro processo potrà essere
+eseguito, ed esso sarà mantenuto in esecuzione permanentemente assorbendo
+tutta la CPU e senza nessuna possibilità di riottenere l'accesso al
+sistema. Per questo motivo è sempre opportuno, quando si lavora con processi
+che usano priorità assolute, tenere attiva una shell cui si sia assegnata la
+massima priorità assoluta, in modo da poter essere comunque in grado di
+rientrare nel sistema.
+
+Quando c'è un processo con priorità assoluta lo scheduler lo metterà in
+esecuzione prima di ogni processo normale. In caso di più processi sarà
+eseguito per primo quello con priorità assoluta più alta. Quando ci sono più
+processi con la stessa priorità assoluta questi vengono tenuti in una coda e
+tocca al kernel decidere quale deve essere eseguito.  Il meccanismo con cui
+vengono gestiti questi processi dipende dalla politica di scheduling che si è
+scelta; lo standard ne prevede due:
+\begin{basedescript}{\desclabelwidth{1.2cm}\desclabelstyle{\nextlinelabel}}
+\item[\textsf{FIFO}] \textit{First In First Out}. Il processo viene eseguito
+  fintanto che non cede volontariamente la CPU (con \func{sched\_yield}), si
+  blocca, finisce o viene interrotto da un processo a priorità più alta. Se il
+  processo viene interrotto da uno a priorità più alta esso resterà in cima
+  alla lista e sarà il primo ad essere eseguito quando i processi a priorità
+  più alta diverranno inattivi. Se invece lo si blocca volontariamente sarà
+  posto in coda alla lista (ed altri processi con la stessa priorità potranno
+  essere eseguiti).
+\item[\textsf{RR}] \textit{Round Robin}. Il comportamento è del tutto analogo
+  a quello precedente, con la sola differenza che ciascun processo viene
+  eseguito al massimo per un certo periodo di tempo (la cosiddetta
+  \textit{time-slice}) dopo di che viene automaticamente posto in fondo alla
+  coda dei processi con la stessa priorità. In questo modo si ha comunque una
+  esecuzione a turno di tutti i processi, da cui il nome della politica. Solo
+  i processi con la stessa priorità ed in stato \textbf{Runnable} entrano nel
+  \textsl{girotondo}.
+\end{basedescript}
+
+Lo standard POSIX.1-2001 prevede una funzione che consenta sia di modificare
+le politiche di scheduling, passando da real-time a ordinarie o viceversa, che
+di specificare, in caso di politiche real-time, la eventuale priorità statica;
+la funzione è \funcd{sched\_setscheduler} ed il suo prototipo è:
+\begin{prototype}{sched.h}
+{int sched\_setscheduler(pid\_t pid, int policy, const struct sched\_param *p)}
+  Imposta priorità e politica di scheduling.
+  
+  \bodydesc{La funzione ritorna la priorità in caso di successo e $-$1 in caso
+    di errore, nel qual caso \var{errno} può assumere i valori:
+    \begin{errlist}
+    \item[\errcode{ESRCH}] il processo \param{pid} non esiste.
+    \item[\errcode{EINVAL}] il valore di \param{policy} non esiste o il
+      relativo valore di \param{p} non è valido.
+    \item[\errcode{EPERM}] il processo non ha i privilegi per attivare la
+      politica richiesta.
+  \end{errlist}}
+\end{prototype}
+
+La funzione esegue l'impostazione per il processo specificato dall'argomento
+\param{pid}; un valore nullo di questo argomento esegue l'impostazione per il
+processo corrente.  La politica di scheduling è specificata
+dall'argomento \param{policy} i cui possibili valori sono riportati in
+tab.~\ref{tab:proc_sched_policy}; la parte alta della tabella indica le
+politiche real-time, quella bassa le politiche ordinarie. Un valore negativo
+per \param{policy} mantiene la politica di scheduling corrente.
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|l|}
+    \hline
+    \textbf{Policy}  & \textbf{Significato} \\
+    \hline
+    \hline
+    \const{SCHED\_FIFO} & Scheduling real-time con politica \textit{FIFO}. \\
+    \const{SCHED\_RR}   & Scheduling real-time con politica \textit{Round
+      Robin}. \\
+    \hline
+    \const{SCHED\_OTHER}& Scheduling ordinario.\\
+    \const{SCHED\_BATCH}& Scheduling ordinario con l'assunzione ulteriore di
+                          lavoro \textit{CPU intensive}.\footnotemark\\
+    \const{SCHED\_IDLE} & Scheduling di priorità estremamente
+                          bassa.\footnotemark\\
+    \hline
+  \end{tabular}
+  \caption{Valori dell'argomento \param{policy} per la funzione
+    \func{sched\_setscheduler}.}
+  \label{tab:proc_sched_policy}
+\end{table}
+
+\footnotetext[41]{introdotto con il kernel 2.6.16.}
+\footnotetext{introdotto con il kernel 2.6.23.}
+
+Con le versioni più recenti del kernel sono state introdotte anche delle
+varianti sulla politica di scheduling tradizionale per alcuni carichi di
+lavoro specifici, queste due nuove politiche sono specifiche di Linux e non
+devono essere usate se si vogliono scrivere programmi portabili.
+
+La politica \const{SCHED\_BATCH} è una variante della politica ordinaria con
+la sola differenza che i processi ad essa soggetti non ottengono, nel calcolo
+delle priorità dinamiche fatto dallo scheduler, il cosiddetto bonus di
+interattività che mira a favorire i processi che si svegliano dallo stato di
+\textbf{Sleep}.\footnote{cosa che accade con grande frequenza per i processi
+  interattivi, dato che essi sono per la maggior parte del tempo in attesa di
+  dati in ingresso da parte dell'utente.} La si usa pertanto, come indica il
+nome, per processi che usano molta CPU (come programmi di calcolo) che in
+questo modo sono leggermente sfavoriti rispetto ai processi interattivi che
+devono rispondere a dei dati in ingresso, pur non perdendo il loro valore di
+\textit{nice}.
+
+La politica \const{SCHED\_IDLE} invece è una politica dedicata ai processi che
+si desidera siano eseguiti con la più bassa priorità possibile, ancora più
+bassa di un processo con il minimo valore di \textit{nice}. In sostanza la si
+può utilizzare per processi che devono essere eseguiti se non c'è niente altro
+da fare. Va comunque sottolineato che anche un processo \const{SCHED\_IDLE}
+avrà comunque una sua possibilità di utilizzo della CPU, sia pure in
+percentuale molto bassa.
+
+Qualora si sia richiesta una politica real-time il valore della priorità
+statica viene impostato attraverso la struttura \struct{sched\_param},
+riportata in fig.~\ref{fig:sig_sched_param}, il cui solo campo attualmente
+definito è \var{sched\_priority}. Il campo deve contenere il valore della
+priorità statica da assegnare al processo; lo standard prevede che questo
+debba essere assegnato all'interno di un intervallo fra un massimo ed un
+minimo che nel caso di Linux sono rispettivamente 1 e 99.  
+
+\begin{figure}[!bht]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \includestruct{listati/sched_param.c}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \structd{sched\_param}.} 
+  \label{fig:sig_sched_param}
+\end{figure}
+
+I processi con politica di scheduling ordinaria devono sempre specificare un
+valore nullo di \var{sched\_priority} altrimenti si avrà un errore
+\errcode{EINVAL}, questo valore infatti non ha niente a che vedere con la
+priorità dinamica determinata dal valore di \textit{nice}, che deve essere
+impostato con le funzioni viste in precedenza.
+
+Lo standard POSIX.1b prevede comunque che i due valori della massima e minima
+priorità statica possano essere ottenuti, per ciascuna delle politiche di
+scheduling \textit{real-time}, tramite le due funzioni
+\funcd{sched\_get\_priority\_max} e \funcd{sched\_get\_priority\_min}, i cui
+prototipi sono:
+\begin{functions}
+  \headdecl{sched.h}
+  
+  \funcdecl{int sched\_get\_priority\_max(int policy)} Legge il valore
+  massimo della priorità statica per la politica di scheduling \param{policy}.
+
+  
+  \funcdecl{int sched\_get\_priority\_min(int policy)} Legge il valore minimo
+  della priorità statica per la politica di scheduling \param{policy}.
+  
+  \bodydesc{La funzioni ritornano il valore della priorità in caso di successo
+    e $-1$ in caso di errore, nel qual caso \var{errno} può assumere i valori:
+    \begin{errlist}
+    \item[\errcode{EINVAL}] il valore di \param{policy} non è valido.
+  \end{errlist}}
+\end{functions}
+
+Si tenga presente che quando si imposta una politica di scheduling real-time
+per un processo o se ne cambia la priorità statica questo viene messo in cima
+alla lista dei processi con la stessa priorità; questo comporta che verrà
+eseguito subito, interrompendo eventuali altri processi con la stessa priorità
+in quel momento in esecuzione.
+
+Il kernel mantiene i processi con la stessa priorità assoluta in una lista, ed
+esegue sempre il primo della lista, mentre un nuovo processo che torna in
+stato \textbf{Runnable} viene sempre inserito in coda alla lista. Se la
+politica scelta è \const{SCHED\_FIFO} quando il processo viene eseguito viene
+automaticamente rimesso in coda alla lista, e la sua esecuzione continua
+fintanto che non viene bloccato da una richiesta di I/O, o non rilascia
+volontariamente la CPU (in tal caso, tornando nello stato \textbf{Runnable}
+sarà reinserito in coda alla lista); l'esecuzione viene ripresa subito solo
+nel caso che esso sia stato interrotto da un processo a priorità più alta.
+
+Solo un processo con i privilegi di amministratore\footnote{più precisamente
+  con la \itindex{capabilities} capacità \const{CAP\_SYS\_NICE}, vedi
+  sez.~\ref{sec:proc_capabilities}.} può impostare senza restrizioni priorità
+assolute diverse da zero o politiche \const{SCHED\_FIFO} e
+\const{SCHED\_RR}. Un utente normale può modificare solo le priorità di
+processi che gli appartengono; è cioè richiesto che l'user-ID effettivo del
+processo chiamante corrisponda all'user-ID reale o effettivo del processo
+indicato con \param{pid}.
+
+Fino al kernel 2.6.12 gli utenti normali non potevano impostare politiche
+real-time o modificare la eventuale priorità statica di un loro processo. A
+partire da questa versione è divenuto possibile anche per gli utenti normali
+usare politiche real-time fintanto che la priorità assoluta che si vuole
+impostare è inferiore al limite \const{RLIMIT\_RTPRIO} (vedi
+sez.~\ref{sec:sys_resource_limit}) ad essi assegnato. Unica eccezione a questa
+possibilità sono i processi \const{SCHED\_IDLE}, che non possono cambiare
+politica di scheduling indipendentemente dal valore di
+\const{RLIMIT\_RTPRIO}. Inoltre, in caso di processo già sottoposto ad una
+politica real-time, un utente può sempre, indipendentemente dal valore di
+\const{RLIMIT\_RTPRIO}, diminuirne la priorità o portarlo ad una politica
+ordinaria.
+
+Se si intende operare solo sulla priorità statica di un processo si possono
+usare le due funzioni \funcd{sched\_setparam} e \funcd{sched\_getparam} che
+consentono rispettivamente di impostarne e leggerne il valore, i loro
+prototipi sono:
+\begin{functions}
+  \headdecl{sched.h}
+
+  \funcdecl{int sched\_setparam(pid\_t pid, const struct sched\_param *param)}
+  Imposta la priorità statica del processo \param{pid}.
+
+  \funcdecl{int sched\_getparam(pid\_t pid, struct sched\_param *param)}
+  Legge la priorità statica del processo \param{pid}.
+
+  \bodydesc{Entrambe le funzioni ritornano 0 in caso di successo e $-1$ in
+    caso di errore, nel qual caso \var{errno} può assumere i valori:
+    \begin{errlist}
+    \item[\errcode{ESRCH}] il processo \param{pid} non esiste.
+    \item[\errcode{EINVAL}] il valore di \param{param} non ha senso per la
+      politica usata dal processo.
+    \item[\errcode{EPERM}] non si hanno privilegi sufficienti per eseguire
+      l'operazione.
+  \end{errlist}}
+\end{functions}
+
+L'uso di \func{sched\_setparam}, compresi i controlli di accesso che vi si
+applicano, è del tutto equivalente a quello di \func{sched\_setscheduler} con
+argomento \param{policy} uguale a -1. Come per \func{sched\_setscheduler}
+specificando 0 come valore dell'argomento \param{pid} si opera sul processo
+corrente. Benché la funzione sia utilizzabile anche con processi sottoposti a
+politica ordinaria essa ha senso soltanto per quelli real-time, dato che per i
+primi la priorità statica può essere soltanto nulla.  La disponibilità di
+entrambe le funzioni può essere verificata controllando la macro
+\macro{\_POSIX\_PRIORITY\_SCHEDULING} che è definita nell'header
+\file{sched.h}.
+
+Se invece si vuole sapere quale è politica di scheduling di un processo si può
+usare la funzione \funcd{sched\_getscheduler}, il cui prototipo è:
+\begin{prototype}{sched.h}
+{int sched\_getscheduler(pid\_t pid)}
+  Legge la politica di scheduling per il processo \param{pid}.
+  
+  \bodydesc{La funzione ritorna la politica di scheduling in caso di successo
+    e $-1$ in caso di errore, nel qual caso \var{errno} può assumere i valori:
+    \begin{errlist}
+    \item[\errcode{ESRCH}] il processo \param{pid} non esiste.
+    \item[\errcode{EPERM}] non si hanno privilegi sufficienti per eseguire
+      l'operazione.
+  \end{errlist}}  
+\end{prototype}
+
+La funzione restituisce il valore, secondo quanto elencato in
+tab.~\ref{tab:proc_sched_policy}, della politica di scheduling per il processo
+specificato; se l'argomento \param{pid} è nullo viene restituito il valore
+relativo al processo chiamante.
+
+L'ultima funzione che permette di leggere le informazioni relative ai processi
+real-time è \funcd{sched\_rr\_get\_interval}, che permette di ottenere la
+lunghezza della \textit{time-slice} usata dalla politica \textit{round robin};
+il suo prototipo è:
+\begin{prototype}{sched.h}
+  {int sched\_rr\_get\_interval(pid\_t pid, struct timespec *tp)} Legge in
+  \param{tp} la durata della \textit{time-slice} per il processo \param{pid}.
+  
+  \bodydesc{La funzione ritorna 0 in caso di successo e -1 in caso di errore,
+    nel qual caso \var{errno} può assumere i valori:
+    \begin{errlist}
+    \item[\errcode{ESRCH}] il processo \param{pid} non esiste.
+    \item[\errcode{ENOSYS}] la system call non è stata implementata.
+  \end{errlist}}
+\end{prototype}
+
+La funzione restituisce il valore dell'intervallo di tempo usato per la
+politica \textit{round robin} in una struttura \struct{timespec}, (la cui
+definizione si può trovare in fig.~\ref{fig:sys_timeval_struct}). In realtà
+dato che in Linux questo intervallo di tempo è prefissato e non modificabile,
+questa funzione ritorna sempre un valore di 150 millisecondi, e non importa
+specificare il PID di un processo reale.
+
+Come accennato ogni processo può rilasciare volontariamente la CPU in modo da
+consentire agli altri processi di essere eseguiti; la funzione che consente di
+fare tutto ciò è \funcd{sched\_yield}, il cui prototipo è:
+\begin{prototype}{sched.h}
+  {int sched\_yield(void)} 
+  
+  Rilascia volontariamente l'esecuzione.
+  
+  \bodydesc{La funzione ritorna 0 in caso di successo e -1 in caso di errore,
+    nel qual caso \var{errno} viene impostata opportunamente.}
+\end{prototype}
+
+Questa funzione ha un utilizzo effettivo soltanto quando si usa lo scheduling
+real-time, e serve a far sì che il processo corrente rilasci la CPU, in modo
+da essere rimesso in coda alla lista dei processi con la stessa priorità per
+permettere ad un altro di essere eseguito; se però il processo è l'unico ad
+essere presente sulla coda l'esecuzione non sarà interrotta. In genere usano
+questa funzione i processi con politica \const{SCHED\_FIFO}, per permettere
+l'esecuzione degli altri processi con pari priorità quando la sezione più
+urgente è finita.
+
+La funzione può essere utilizzata anche con processi che usano lo scheduling
+ordinario, ma in questo caso il comportamento non è ben definito, e dipende
+dall'implementazione. Fino al kernel 2.6.23 questo comportava che i processi
+venissero messi in fondo alla coda di quelli attivi, con la possibilità di
+essere rimessi in esecuzione entro breve tempo, con l'introduzione del
+\textit{Completely Fair Scheduler} questo comportamento è cambiato ed un
+processo che chiama la funzione viene inserito nella lista dei processi
+inattivo, con un tempo molto maggiore.\footnote{è comunque possibile
+  ripristinare un comportamento analogo al precedente scrivendo il valore 1
+  nel file \texttt{/proc/sys/kernel/sched\_compat\_yield}.}
+
+
+
+\subsection{Il controllo dello \textit{scheduler} per i sistemi
+  multiprocessore}
+\label{sec:proc_sched_multiprocess}
+
+Infine con il supporto dei sistemi multiprocessore sono state introdotte delle
+funzioni che permettono di controllare in maniera più dettagliata la scelta di
+quale processore utilizzare per eseguire un certo programma. Uno dei problemi
+che si pongono nei sistemi multiprocessore è infatti quello del cosiddetto
+\index{effetto~ping-pong} \textsl{effetto ping-pong}. Può accadere cioè che lo
+scheduler, quando riavvia un processo precedentemente interrotto scegliendo il
+primo processore disponibile, lo faccia eseguire da un processore diverso
+rispetto a quello su cui era stato eseguito in precedenza. Se il processo
+passa da un processore all'altro in questo modo (cosa che avveniva abbastanza
+di frequente con i kernel della seria 2.4.x) si ha l'\textsl{effetto
+  ping-pong}.
+
+Questo tipo di comportamento può generare dei seri problemi di prestazioni;
+infatti tutti i processori moderni utilizzano una memoria interna (la
+\textit{cache}) contenente i dati più usati, che permette di evitare di
+eseguire un accesso (molto più lento) alla memoria principale sulla scheda
+madre.  Chiaramente un processo sarà favorito se i suoi dati sono nella cache
+del processore, ma è ovvio che questo può essere vero solo per un processore
+alla volta, perché in presenza di più copie degli stessi dati su più
+processori, non si potrebbe determinare quale di questi ha la versione dei
+dati aggiornata rispetto alla memoria principale.
+
+Questo comporta che quando un processore inserisce un dato nella sua cache,
+tutti gli altri processori che hanno lo stesso dato devono invalidarlo, e
+questa operazione è molto costosa in termini di prestazioni. Il problema
+diventa serio quando si verifica l'\textsl{effetto ping-pong}, in tal caso
+infatti un processo \textsl{rimbalza} continuamente da un processore all'altro
+e si ha una continua invalidazione della cache, che non diventa mai
+disponibile.
+
+\itindbeg{CPU~affinity}
+
+Per ovviare a questo tipo di problemi è nato il concetto di \textsl{affinità
+  di processore} (o \textit{CPU affinity}); la possibilità cioè di far sì che
+un processo possa essere assegnato per l'esecuzione sempre allo stesso
+processore. Lo scheduler dei kernel della serie 2.4.x aveva una scarsa
+\textit{CPU affinity}, e \index{effetto~ping-pong} l'effetto ping-pong era
+comune; con il nuovo scheduler dei kernel della 2.6.x questo problema è stato
+risolto ed esso cerca di mantenere il più possibile ciascun processo sullo
+stesso processore.
+
+In certi casi però resta l'esigenza di poter essere sicuri che un processo sia
+sempre eseguito dallo stesso processore,\footnote{quella che viene detta
+  \textit{hard CPU affinity}, in contrasto con quella fornita dallo scheduler,
+  detta \textit{soft CPU affinity}, che di norma indica solo una preferenza,
+  non un requisito assoluto.} e per poter risolvere questo tipo di
+problematiche nei nuovi kernel\footnote{le due system call per la gestione
+  della \textit{CPU affinity} sono state introdotte nel kernel 2.5.8, e le
+  funzioni di libreria nelle \textsl{glibc} 2.3.} è stata introdotta
+l'opportuna infrastruttura ed una nuova system call che permette di impostare
+su quali processori far eseguire un determinato processo attraverso una
+\textsl{maschera di affinità}. La corrispondente funzione di libreria è
+\funcd{sched\_setaffinity} ed il suo prototipo è:
+\begin{prototype}{sched.h}
+  {int sched\_setaffinity (pid\_t pid, unsigned int cpusetsize, const
+    cpu\_set\_t *cpuset)} 
+  Imposta la maschera di affinità del processo \param{pid}.
+  
+  \bodydesc{La funzione ritorna 0 in caso di successo e -1 in caso di errore,
+    nel qual caso \var{errno} può assumere i valori:
+    \begin{errlist}
+    \item[\errcode{ESRCH}] il processo \param{pid} non esiste.
+    \item[\errcode{EINVAL}] il valore di \param{cpuset} contiene riferimenti a
+      processori non esistenti nel sistema.
+    \item[\errcode{EPERM}] il processo non ha i privilegi sufficienti per
+      eseguire l'operazione.
+  \end{errlist} 
+  ed inoltre anche \errval{EFAULT}.}
+\end{prototype}
+
+
+Questa funzione e la corrispondente \func{sched\_setaffinity} hanno una storia
+abbastanza complessa, la system call prevede l'uso di due ulteriori argomenti
+di tipo \texttt{unsigned int len} e \texttt{unsigned long *mask}, che
+corrispondono al fatto che la implementazione effettiva usa una semplice
+maschera binaria. Quando le funzioni vennero incluse nelle \acr{glibc}
+assunsero invece il prototipo appena mostrato. A complicare la cosa si
+aggiunge il fatto che nella versione 2.3.3 delle \acr{glibc} l'argomento
+\param{cpusetsize} è stato eliminato, per poi essere ripristinato nella
+versione 2.3.4.\footnote{pertanto se la vostra pagina di manuale non è
+  aggiornata, o usate quella particolare versione delle \acr{glibc}, potrete
+  trovare indicazioni diverse, il prototipo illustrato è quello riportato
+  nella versione corrente (maggio 2008) delle pagine di manuale e
+  corrispondente alla definizione presente in \file{sched.h}.}
+
+La funzione imposta, con l'uso del valore contenuto all'indirizzo
+\param{cpuset}, l'insieme dei processori sui quali deve essere eseguito il
+processo identificato tramite il valore passato in \param{pid}. Come in
+precedenza il valore nullo di \param{pid} indica il processo corrente.  Per
+poter utilizzare questa funzione sono richiesti i privilegi di amministratore
+(è necessaria la capacità \const{CAP\_SYS\_NICE}) altrimenti essa fallirà con
+un errore di \errcode{EPERM}. Una volta impostata una maschera di affinità,
+questa viene ereditata attraverso una \func{fork}, in questo modo diventa
+possibile legare automaticamente un gruppo di processi ad un singolo
+processore.
+
+Nell'uso comune, almeno con i kernel della serie 2.6.x, l'uso di questa
+funzione non è necessario, in quanto è lo scheduler stesso che provvede a
+mantenere al meglio l'affinità di processore. Esistono però esigenze
+particolari, ad esempio quando un processo (o un gruppo di processi) è
+utilizzato per un compito importante (ad esempio per applicazioni real-time o
+la cui risposta è critica) e si vuole la massima velocità, con questa
+interfaccia diventa possibile selezionare gruppi di processori utilizzabili in
+maniera esclusiva.  Lo stesso dicasi quando l'accesso a certe risorse (memoria
+o periferiche) può avere un costo diverso a seconda del processore, come
+avviene nelle architetture NUMA (\textit{Non-Uniform Memory Access}).
+
+Infine se un gruppo di processi accede alle stesse risorse condivise (ad
+esempio una applicazione con più \itindex{thread} \textit{thread}) può avere
+senso usare lo stesso processore in modo da sfruttare meglio l'uso della sua
+cache; questo ovviamente riduce i benefici di un sistema multiprocessore
+nell'esecuzione contemporanea dei \itindex{thread} \textit{thread}, ma in
+certi casi (quando i \itindex{thread} \textit{thread} sono inerentemente
+serializzati nell'accesso ad una risorsa) possono esserci sufficienti vantaggi
+nell'evitare la perdita della cache da rendere conveniente l'uso dell'affinità
+di processore.
+
+Per facilitare l'uso dell'argomento \param{cpuset} le \acr{glibc} hanno
+introdotto un apposito dato di tipo, \ctyp{cpu\_set\_t},\footnote{questa è una
+  estensione specifica delle \acr{glibc}, da attivare definendo la macro
+  \macro{\_GNU\_SOURCE}, non esiste infatti una standardizzazione per
+  questo tipo di interfaccia e POSIX al momento non prevede nulla al
+  riguardo.} che permette di identificare un insieme di processori. Il dato è
+una maschera binaria: in generale è un intero a 32 bit in cui ogni bit
+corrisponde ad un processore, ma dato che per architetture particolari il
+numero di bit di un intero può non essere sufficiente, è stata creata questa
+che è una interfaccia generica che permette di usare a basso livello un tipo
+di dato qualunque rendendosi indipendenti dal numero di bit e dalla loro
+disposizione.
+
+Questa interfaccia, oltre alla definizione del tipo di dato apposito, prevede
+anche una serie di macro di preprocessore per la manipolazione dello stesso,
+che consentono di svuotare un insieme, aggiungere o togliere un processore da
+esso o verificare se vi è già presente:
+\begin{functions}
+  \headdecl{sched.h}
+  \funcdecl{void \macro{CPU\_ZERO}(cpu\_set\_t *set)}
+  Inizializza l'insieme (vuoto).
+
+  \funcdecl{void \macro{CPU\_SET}(int cpu, cpu\_set\_t *set)}
+  Inserisce il processore \param{cpu} nell'insieme.
+
+  \funcdecl{void \macro{CPU\_CLR}(int cpu, cpu\_set\_t *set)}
+  Rimuove il processore \param{cpu} nell'insieme.
+  
+  \funcdecl{int \macro{CPU\_ISSET}(int cpu, cpu\_set\_t *set)}
+  Controlla se il processore \param{cpu} è nell'insieme.
+\end{functions}
+
+Oltre a queste macro, simili alle analoghe usate per gli insiemi di file
+descriptor (vedi sez.~\ref{sec:file_select}) è definita la costante
+\const{CPU\_SETSIZE} che indica il numero massimo di processori che possono
+far parte dell'insieme, e che costituisce un limite massimo al valore
+dell'argomento \param{cpu}.
+
+In generale la maschera di affinità è preimpostata in modo che un processo
+possa essere eseguito su qualunque processore, se può comunque leggere il
+valore per un processo specifico usando la funzione
+\funcd{sched\_getaffinity}, il suo prototipo è:
+\begin{prototype}{sched.h}
+  {int sched\_getaffinity (pid\_t pid, unsigned int cpusetsize, 
+    const cpu\_set\_t *cpuset)} 
+  Legge la maschera di affinità del processo \param{pid}.
+  
+  \bodydesc{La funzione ritorna 0 in caso di successo e -1 in caso di errore,
+    nel qual caso \var{errno} può assumere i valori:
+    \begin{errlist}
+    \item[\errcode{ESRCH}] il processo \param{pid} non esiste.
+    \item[\errcode{EFAULT}] il valore di \param{cpuset} non è un indirizzo
+      valido. 
+  \end{errlist} }
+\end{prototype}
+
+La funzione restituirà all'indirizzo specificato da \param{cpuset} il valore
+della maschera di affinità del processo, così da poterla riutilizzare per una
+successiva reimpostazione. In questo caso non sono necessari privilegi
+particolari.  
+
+È chiaro che queste funzioni per la gestione dell'affinità hanno significato
+soltanto su un sistema multiprocessore, esse possono comunque essere
+utilizzate anche in un sistema con un processore singolo, nel qual caso però
+non avranno alcun risultato effettivo.
+
+\itindend{scheduler}
+\itindend{CPU~affinity}
+
+
+\subsection{Le priorità per le operazioni di I/O}
+\label{sec:io_priority}
+
+A lungo l'unica priorità usata per i processi è stata quella relativa
+all'assegnazione dell'uso del processore. Ma il processore non è l'unica
+risorsa che i processi devono contendersi, un'altra, altrettanto importante
+per le prestazioni, è quella dell'accesso a disco. Per questo motivo sono
+stati introdotti diversi \textit{I/O scheduler} in grado di distribuire in
+maniera opportuna questa risorsa ai vari processi. Fino al kernel 2.6.17 era
+possibile soltanto differenziare le politiche generali di gestione, scegliendo
+di usare un diverso \textit{I/O scheduler}; a partire da questa versione, con
+l'introduzione dello scheduler CFQ (\textit{Completely Fair Queuing}) è
+divenuto possibile, qualora si usi questo scheduler, impostare anche delle
+diverse priorità di accesso per i singoli processi.\footnote{al momento
+  (kernel 2.6.31), le priorità di I/O sono disponibili soltanto per questo
+  scheduler.}
+
+La scelta dello scheduler di I/O si può fare in maniera generica a livello di
+avvio del kernel assegnando il nome dello stesso al parametro
+\texttt{elevator}, mentre se ne può indicare uno per l'accesso al singolo
+disco scrivendo nel file \texttt{/sys/block/\textit{dev}/queue/scheduler}
+(dove \texttt{\textit{dev}} è il nome del dispositivo associato al disco); gli
+scheduler disponibili sono mostrati dal contenuto dello stesso file che
+riporta fra parentesi quadre quello attivo, il default in tutti i kernel
+recenti è proprio il \texttt{cfq},\footnote{nome con cui si indica appunto lo
+  scheduler \textit{Completely Fair Queuing}.} che supporta le priorità. Per i
+dettagli sulle caratteristiche specifiche degli altri scheduler, la cui
+discussione attiene a problematiche di ambito sistemistico, si consulti la
+documentazione nella directory \texttt{Documentation/block/} dei sorgenti del
+kernel.
+
+Una volta che si sia impostato lo scheduler CFQ ci sono due specifiche system
+call, specifiche di Linux, che consentono di leggere ed impostare le priorità
+di I/O.\footnote{se usate in corrispondenza ad uno scheduler diverso il loro
+  utilizzo non avrà alcun effetto.} Dato che non esiste una interfaccia
+diretta nelle \acr{glibc} per queste due funzioni occorrerà invocarle tramite
+la funzione \func{syscall} (come illustrato in
+sez.~\ref{sec:intro_syscall}). Le due funzioni sono \funcd{ioprio\_get} ed
+\funcd{ioprio\_set}; i rispettivi prototipi sono:
+\begin{functions}
+  \headdecl{linux/ioprio.h}
+  \funcdecl{int ioprio\_get(int which, int who)} 
+  \funcdecl{int ioprio\_set(int which, int who, int ioprio)} 
+
+  Rileva o imposta la priorità di I/O di un processo.
+  
+  \bodydesc{Le funzioni ritornano rispettivamente un intero positivo
+    (indicante la priorità) o 0 in caso di successo e $-1$ in caso di errore,
+    nel qual caso \var{errno} può assumere i valori:
+    \begin{errlist}
+    \item[\errcode{ESRCH}] non esiste il processo indicato.
+    \item[\errcode{EINVAL}] i valori di \param{which} e \param{who} non sono
+      validi. 
+    \item[\errcode{EPERM}] non si hanno i privilegi per eseguire
+      l'impostazione (solo per \func{ioprio\_set}). 
+  \end{errlist} }
+\end{functions}
+
+Le funzioni leggono o impostano la priorità di I/O sulla base dell'indicazione
+dei due argomenti \param{which} e \param{who} che hanno lo stesso significato
+già visto per gli omonimi argomenti di \func{getpriority} e
+\func{setpriority}. Anche in questo caso si deve specificare il valore
+di \param{which} tramite le opportune costanti riportate in
+tab.~\ref{tab:ioprio_args} che consentono di indicare un singolo processo, i
+processi di un \textit{process group} (tratteremo questo argomento in
+sez.~\ref{sec:sess_proc_group}) o tutti o processi di un utente.
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|c|c|l|}
+    \hline
+    \param{which} & \param{who} & \textbf{Significato} \\
+    \hline
+    \hline
+    \const{IPRIO\_WHO\_PROCESS} & \type{pid\_t} & processo\\
+    \const{IPRIO\_WHO\_PRGR}    & \type{pid\_t} & \itindex{process~group}
+                                                  \textit{process group}\\ 
+    \const{IPRIO\_WHO\_USER}    & \type{uid\_t} & utente\\
+    \hline
+  \end{tabular}
+  \caption{Legenda del valore dell'argomento \param{which} e del tipo
+    dell'argomento \param{who} delle funzioni \func{ioprio\_get} e
+    \func{ioprio\_set} per le tre possibili scelte.}
+  \label{tab:ioprio_args}
+\end{table}
+
+In caso di successo \func{ioprio\_get} restituisce un intero positivo che
+esprime il valore della priorità di I/O, questo valore è una maschera binaria
+composta da due parti, una che esprime la \textsl{classe} di scheduling di I/O
+del processo, l'altra che esprime, quando la classe di scheduling lo prevede,
+la priorità del processo all'interno della classe stessa. Questo stesso
+formato viene utilizzato per indicare il valore della priorità da impostare
+con l'argomento \param{ioprio} di \func{ioprio\_set}.
+
+Per la gestione dei valori che esprimono le priorità di I/O sono state
+definite delle opportune macro di preprocessore, riportate in
+tab.~\ref{tab:IOsched_class_macro}. I valori delle priorità si ottengono o si
+impostano usando queste macro.  Le prime due si usano con il valore restituito
+da \func{ioprio\_get} e per ottenere rispettivamente la classe di
+scheduling\footnote{restituita dalla macro con i valori di
+  tab.~\ref{tab:IOsched_class}.} e l'eventuale valore della priorità. La terza
+macro viene invece usata per creare un valore di priorità da usare come
+argomento di \func{ioprio\_set} per eseguire una impostazione.
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|p{8cm}|}
+    \hline
+    \textbf{Macro} & \textbf{Significato}\\
+    \hline
+    \hline
+    \macro{IOPRIO\_PRIO\_CLASS}\texttt{(\textit{value})}
+                                & dato il valore di una priorità come
+                                  restituito da \func{ioprio\_get} estrae il
+                                  valore della classe.\\
+    \macro{IOPRIO\_PRIO\_DATA}\texttt{(\textit{value})}
+                                & dato il valore di una priorità come
+                                  restituito da \func{ioprio\_get} estrae il
+                                  valore della priorità.\\
+    \macro{IOPRIO\_PRIO\_VALUE}\texttt{(\textit{class},\textit{prio})}
+                                & dato un valore di priorità ed una classe
+                                  ottiene il valore numerico da passare a
+                                  \func{ioprio\_set}.\\
+    \hline
+  \end{tabular}
+  \caption{Le macro per la gestione dei valori numerici .}
+  \label{tab:IOsched_class_macro}
+\end{table}
+
+Le classi di scheduling previste dallo scheduler CFQ sono tre, e ricalcano tre
+diverse modalità di distribuzione delle risorse analoghe a quelle già adottate
+anche nel funzionamento dello scheduler del processore. Ciascuna di esse è
+identificata tramite una opportuna costante, secondo quanto riportato in
+tab.~\ref{tab:IOsched_class}.
+
+La classe di priorità più bassa è \const{IOPRIO\_CLASS\_IDLE}; i processi in
+questa classe riescono ad accedere a disco soltanto quando nessun altro
+processo richiede l'accesso. Occorre pertanto usarla con molta attenzione,
+perché un processo in questa classe può venire completamente bloccato quando
+ci sono altri processi in una qualunque delle altre due classi che stanno
+accedendo al disco. Quando si usa questa classe non ha senso indicare un
+valore di priorità, dato che in questo caso non esiste nessuna gerarchia e la
+priorità è identica, la minima possibile, per tutti i processi.
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|l|}
+    \hline
+    \textbf{Classe}  & \textbf{Significato} \\
+    \hline
+    \hline
+    \const{IOPRIO\_CLASS\_RT}  & Scheduling di I/O \textit{real time}.\\
+    \const{IOPRIO\_CLASS\_BE}  & Scheduling di I/O ordinario.\\ 
+    \const{IOPRIO\_CLASS\_IDLE}& Scheduling di I/O di priorità minima.\\
+    \hline
+  \end{tabular}
+  \caption{Costanti che identificano le classi di scheduling di I/O.}
+  \label{tab:IOsched_class}
+\end{table}
+
+La seconda classe di priorità di I/O è \const{IOPRIO\_CLASS\_BE} (il nome sta
+per \textit{best-effort}) che è quella usata ordinariamente da tutti
+processi. In questo caso esistono priorità diverse che consentono di
+assegnazione di una maggiore banda passante nell'accesso a disco ad un
+processo rispetto agli altri, con meccanismo simile a quello dei valori di
+\textit{nice} in cui si evita che un processo a priorità più alta possa
+bloccare indefinitamente quelli a priorità più bassa. In questo caso però le
+diverse priorità sono soltanto otto, indicate da un valore numerico fra 0 e 7
+e come per \textit{nice} anche in questo caso un valore più basso indica una
+priorità maggiore. 
+
+
+Infine la classe di priorità di I/O \textit{real-time}
+\const{IOPRIO\_CLASS\_RT} ricalca le omonime priorità di processore: un
+processo in questa classe ha sempre la precedenza nell'accesso a disco
+rispetto a tutti i processi delle altre classi e di un processo nella stessa
+classe ma con priorità inferiore, ed è pertanto in grado di bloccare
+completamente tutti gli altri. Anche in questo caso ci sono 8 priorità diverse
+con un valore numerico fra 0 e 7, con una priorità più elevata per valori più
+bassi.
+
+In generale nel funzionamento ordinario la priorità di I/O di un processo
+viene impostata in maniera automatica nella classe \const{IOPRIO\_CLASS\_BE}
+con un valore ottenuto a partire dal corrispondente valore di \textit{nice}
+tramite la formula: $\mathtt{\mathit{prio}}=(\mathtt{\mathit{nice}}+20)/5$. Un
+utente ordinario può modificare con \func{ioprio\_set} soltanto le priorità
+dei processi che gli appartengono,\footnote{per la modifica delle priorità di
+  altri processi occorrono privilegi amministrativi, ed in particolare la
+  capacità \const{CAP\_SYS\_NICE} (vedi sez.~\ref{sec:proc_capabilities}).}
+cioè quelli il cui user-ID reale corrisponde all'user-ID reale o effettivo del
+chiamante. Data la possibilità di ottenere un blocco totale dello stesso, solo
+l'amministratore\footnote{o un processo con la capacità
+  \const{CAP\_SYS\_ADMIN} (vedi sez.~\ref{sec:proc_capabilities}).} può
+impostare un processo ad una priorità di I/O nella classe
+\const{IOPRIO\_CLASS\_RT} o \const{IOPRIO\_CLASS\_IDLE}.
+
+%TODO verificare http://lwn.net/Articles/355987/
+
+%TODO trattare le funzionalità per il NUMA
+% vedi man numa e le pagine di manuale relative
+% vedere anche dove metterle...
+
+\section{Problematiche di programmazione multitasking}
+\label{sec:proc_multi_prog}
+
+Benché i processi siano strutturati in modo da apparire il più possibile come
+indipendenti l'uno dall'altro, nella programmazione in un sistema multitasking
+occorre tenere conto di una serie di problematiche che normalmente non
+esistono quando si ha a che fare con un sistema in cui viene eseguito un solo
+programma alla volta.
+
+Pur essendo questo argomento di carattere generale, ci è parso opportuno
+introdurre sinteticamente queste problematiche, che ritroveremo a più riprese
+in capitoli successivi, in questa sezione conclusiva del capitolo in cui
+abbiamo affrontato la gestione dei processi.
+
+
+\subsection{Le operazioni atomiche}
+\label{sec:proc_atom_oper}
+
+La nozione di \textsl{operazione atomica} deriva dal significato greco della
+parola atomo, cioè indivisibile; si dice infatti che un'operazione è atomica
+quando si ha la certezza che, qualora essa venga effettuata, tutti i passaggi
+che devono essere compiuti per realizzarla verranno eseguiti senza possibilità
+di interruzione in una fase intermedia.
+
+In un ambiente multitasking il concetto è essenziale, dato che un processo può
+essere interrotto in qualunque momento dal kernel che mette in esecuzione un
+altro processo o dalla ricezione di un segnale; occorre pertanto essere
+accorti nei confronti delle possibili \itindex{race~condition} \textit{race
+  condition} (vedi sez.~\ref{sec:proc_race_cond}) derivanti da operazioni
+interrotte in una fase in cui non erano ancora state completate.
+
+Nel caso dell'interazione fra processi la situazione è molto più semplice, ed
+occorre preoccuparsi della atomicità delle operazioni solo quando si ha a che
+fare con meccanismi di intercomunicazione (che esamineremo in dettaglio in
+cap.~\ref{cha:IPC}) o nelle operazioni con i file (vedremo alcuni esempi in
+sez.~\ref{sec:file_atomic}). In questi casi in genere l'uso delle appropriate
+funzioni di libreria per compiere le operazioni necessarie è garanzia
+sufficiente di atomicità in quanto le system call con cui esse sono realizzate
+non possono essere interrotte (o subire interferenze pericolose) da altri
+processi.
+
+Nel caso dei segnali invece la situazione è molto più delicata, in quanto lo
+stesso processo, e pure alcune system call, possono essere interrotti in
+qualunque momento, e le operazioni di un eventuale \textit{signal handler}
+sono compiute nello stesso spazio di indirizzi del processo. Per questo, anche
+il solo accesso o l'assegnazione di una variabile possono non essere più
+operazioni atomiche (torneremo su questi aspetti in
+sez.~\ref{sec:sig_adv_control}).
 
+In questo caso il sistema provvede un tipo di dato, il \type{sig\_atomic\_t},
+il cui accesso è assicurato essere atomico.  In pratica comunque si può
+assumere che, in ogni piattaforma su cui è implementato Linux, il tipo
+\ctyp{int}, gli altri interi di dimensione inferiore ed i puntatori sono
+atomici. Non è affatto detto che lo stesso valga per interi di dimensioni
+maggiori (in cui l'accesso può comportare più istruzioni in assembler) o per
+le strutture. In tutti questi casi è anche opportuno marcare come
+\direct{volatile} le variabili che possono essere interessate ad accesso
+condiviso, onde evitare problemi con le ottimizzazioni del codice.
 
-\subsection{Le funzioni \texttt{seteuid} e \texttt{setegid}}
-\label{sec:proc_seteuid}
 
 
-\subsection{Le \textit{race condition}}
+\subsection{Le \textit{race condition} ed i \textit{deadlock}}
 \label{sec:proc_race_cond}
 
-Si definisce una \textit{race condition} il caso in cui diversi processi
-stanno cercando di fare qualcosa con una risorsa comune ed il risultato finale
-viene a dipendere dall'ordine di esecuzione dei medesimi. Ovviamente dato che
-l'ordine di esecuzione di un processo, senza appositi meccanismi di
-sincronizzazione, non è assolutamente prevedibile, queste situazioni sono
-fonti di errori molto subdoli, che possono verificarsi solo in condizioni
-particolari e quindi difficilmente riproducibili.
+\itindbeg{race~condition}
+
+Si definiscono \textit{race condition} tutte quelle situazioni in cui processi
+diversi operano su una risorsa comune, ed in cui il risultato viene a
+dipendere dall'ordine in cui essi effettuano le loro operazioni. Il caso
+tipico è quello di un'operazione che viene eseguita da un processo in più
+passi, e può essere compromessa dall'intervento di un altro processo che
+accede alla stessa risorsa quando ancora non tutti i passi sono stati
+completati.
+
+Dato che in un sistema multitasking ogni processo può essere interrotto in
+qualunque momento per farne subentrare un altro in esecuzione, niente può
+assicurare un preciso ordine di esecuzione fra processi diversi o che una
+sezione di un programma possa essere eseguita senza interruzioni da parte di
+altri. Queste situazioni comportano pertanto errori estremamente subdoli e
+difficili da tracciare, in quanto nella maggior parte dei casi tutto
+funzionerà regolarmente, e solo occasionalmente si avranno degli errori. 
+
+Per questo occorre essere ben consapevoli di queste problematiche, e del fatto
+che l'unico modo per evitarle è quello di riconoscerle come tali e prendere
+gli adeguati provvedimenti per far sì che non si verifichino. Casi tipici di
+\textit{race condition} si hanno quando diversi processi accedono allo stesso
+file, o nell'accesso a meccanismi di intercomunicazione come la memoria
+condivisa. In questi casi, se non si dispone della possibilità di eseguire
+atomicamente le operazioni necessarie, occorre che quelle parti di codice in
+cui si compiono le operazioni sulle risorse condivise (le cosiddette
+\index{sezione~critica} \textsl{sezioni critiche}) del programma, siano
+opportunamente protette da meccanismi di sincronizzazione (torneremo su queste
+problematiche di questo tipo in cap.~\ref{cha:IPC}).
+
+\itindbeg{deadlock}
+Un caso particolare di \textit{race condition} sono poi i cosiddetti
+\textit{deadlock}, particolarmente gravi in quanto comportano spesso il blocco
+completo di un servizio, e non il fallimento di una singola operazione. Per
+definizione un \textit{deadlock} è una situazione in cui due o più processi
+non sono più in grado di proseguire perché ciascuno aspetta il risultato di
+una operazione che dovrebbe essere eseguita dall'altro.
+
+
+L'esempio tipico di una situazione che può condurre ad un
+\textit{deadlock} è quello in cui un flag di
+``\textsl{occupazione}'' viene rilasciato da un evento asincrono (come un
+segnale o un altro processo) fra il momento in cui lo si è controllato
+(trovandolo occupato) e la successiva operazione di attesa per lo sblocco. In
+questo caso, dato che l'evento di sblocco del flag è avvenuto senza che ce ne
+accorgessimo proprio fra il controllo e la messa in attesa, quest'ultima
+diventerà perpetua (da cui il nome di \textit{deadlock}).
+
+In tutti questi casi è di fondamentale importanza il concetto di atomicità
+visto in sez.~\ref{sec:proc_atom_oper}; questi problemi infatti possono essere
+risolti soltanto assicurandosi, quando essa sia richiesta, che sia possibile
+eseguire in maniera atomica le operazioni necessarie.
+\itindend{race~condition}
+\itindend{deadlock}
+
+
+\subsection{Le funzioni rientranti}
+\label{sec:proc_reentrant}
+
+\index{funzioni!rientranti|(}
+
+Si dice \textsl{rientrante} una funzione che può essere interrotta in
+qualunque punto della sua esecuzione ed essere chiamata una seconda volta da
+un altro \itindex{thread} \textit{thread} di esecuzione senza che questo
+comporti nessun problema nell'esecuzione della stessa. La problematica è
+comune nella programmazione \itindex{thread} \textit{multi-thread}, ma si
+hanno gli stessi problemi quando si vogliono chiamare delle funzioni
+all'interno dei gestori dei segnali.
+
+Fintanto che una funzione opera soltanto con le variabili locali è rientrante;
+queste infatti vengono allocate nello \itindex{stack} \textit{stack}, ed
+un'altra invocazione non fa altro che allocarne un'altra copia. Una funzione
+può non essere rientrante quando opera su memoria che non è nello
+\itindex{stack} \textit{stack}.  Ad esempio una funzione non è mai rientrante
+se usa una variabile globale o statica.
+
+Nel caso invece la funzione operi su un oggetto allocato dinamicamente, la
+cosa viene a dipendere da come avvengono le operazioni: se l'oggetto è creato
+ogni volta e ritornato indietro la funzione può essere rientrante, se invece
+esso viene individuato dalla funzione stessa due chiamate alla stessa funzione
+potranno interferire quando entrambe faranno riferimento allo stesso oggetto.
+Allo stesso modo una funzione può non essere rientrante se usa e modifica un
+oggetto che le viene fornito dal chiamante: due chiamate possono interferire
+se viene passato lo stesso oggetto; in tutti questi casi occorre molta cura da
+parte del programmatore.
+
+In genere le funzioni di libreria non sono rientranti, molte di esse ad
+esempio utilizzano variabili statiche, le \acr{glibc} però mettono a
+disposizione due macro di compilatore,\footnote{si ricordi quanto illustrato
+  in sez.~\ref{sec:intro_gcc_glibc_std}.} \macro{\_REENTRANT} e
+\macro{\_THREAD\_SAFE}, la cui definizione attiva le versioni rientranti di
+varie funzioni di libreria, che sono identificate aggiungendo il suffisso
+\code{\_r} al nome della versione normale.
+
+\index{funzioni!rientranti|)}
+
+
+% LocalWords:  multitasking like VMS child process identifier pid sez shell fig
+% LocalWords:  parent kernel init pstree keventd kswapd table struct linux call
+% LocalWords:  nell'header scheduler system interrupt timer HZ asm Hertz clock
+% LocalWords:  l'alpha tick fork wait waitpid exit exec image glibc int pgid ps
+% LocalWords:  sid thread Ingo Molnar ppid getpid getppid sys unistd LD threads
+% LocalWords:  void ForkTest tempnam pathname sibling cap errno EAGAIN ENOMEM
+% LocalWords:  stack read only copy write tab client spawn forktest sleep PATH
+% LocalWords:  source LIBRARY scheduling race condition printf descriptor dup
+% LocalWords:  close group session tms lock vfork execve BSD stream main abort
+% LocalWords:  SIGABRT SIGCHLD SIGHUP foreground SIGCONT termination signal ANY
+% LocalWords:  handler kill EINTR POSIX options WNOHANG ECHILD option WUNTRACED
+% LocalWords:  dump bits rusage getrusage heap const filename argv envp EACCES
+% LocalWords:  filesystem noexec EPERM suid sgid root nosuid ENOEXEC ENOENT ELF
+% LocalWords:  ETXTBSY EINVAL ELIBBAD BIG EFAULT EIO ENAMETOOLONG ELOOP ENOTDIR
+% LocalWords:  ENFILE EMFILE argc execl path execv execle execlp execvp vector
+% LocalWords:  list environ NULL umask pending utime cutime ustime fcntl linker
+% LocalWords:  opendir libc interpreter FreeBSD capabilities Mandatory Access
+% LocalWords:  Control MAC SELinux Security Modules LSM superuser uid gid saved
+% LocalWords:  effective euid egid dell' fsuid fsgid getuid geteuid getgid SVr
+% LocalWords:  getegid IDS NFS setuid setgid all' logout utmp screen xterm TODO
+% LocalWords:  setreuid setregid FIXME ruid rgid seteuid setegid setresuid size
+% LocalWords:  setresgid getresuid getresgid value result argument setfsuid DAC
+% LocalWords:  setfsgid NGROUPS sysconf getgroups getgrouplist groups ngroups
+% LocalWords:  setgroups initgroups patch LIDS CHOWN OVERRIDE Discrectionary PF
+% LocalWords:  SEARCH chattr sticky NOATIME socket domain immutable append mmap
+% LocalWords:  broadcast multicast multicasting memory locking mlock mlockall
+% LocalWords:  shmctl ioperm iopl chroot ptrace accounting swap reboot hangup
+% LocalWords:  vhangup mknod lease permitted inherited inheritable bounding AND
+% LocalWords:  capability capget capset header ESRCH undef version obj clear PT
+% LocalWords:  pag ssize length proc capgetp preemptive cache runnable Stopped
+% LocalWords:  Uninterrutible SIGSTOP soft slice nice niceness counter which SC
+% LocalWords:  getpriority who setpriority RTLinux RTAI Adeos fault FIFO First
+% LocalWords:  yield Robin setscheduler policy param OTHER priority setparam to
+% LocalWords:  min getparam getscheduler interval robin ENOSYS fifo ping long
+% LocalWords:  affinity setaffinity unsigned mask cpu NUMA CLR ISSET SETSIZE RR
+% LocalWords:  getaffinity assembler deadlock REENTRANT SAFE tgz MYPGRP l'OR rr
+% LocalWords:  WIFEXITED WEXITSTATUS WIFSIGNALED WTERMSIG WCOREDUMP WIFSTOPPED
+% LocalWords:  WSTOPSIG opt char INTERP arg SIG IGN DFL mascheck grp FOWNER RAW
+% LocalWords:  FSETID SETPCAP BIND SERVICE ADMIN PACKET IPC OWNER MODULE RAWIO
+% LocalWords:  PACCT RESOURCE TTY CONFIG SETFCAP hdrp datap libcap lcap text tp
+% LocalWords:  get ncap caps CapInh CapPrm fffffeff CapEff getcap STAT dall'I
+% LocalWords:  inc PRIO SUSv PRGR prio SysV SunOS Ultrix sched timespec len sig
+% LocalWords:  cpusetsize cpuset atomic tickless redirezione WCONTINUED stopped
+% LocalWords:  waitid NOCLDSTOP ENOCHLD WIFCONTINUED ifdef endif idtype siginfo
+% LocalWords:  infop ALL WEXITED WSTOPPED WNOWAIT signo CLD EXITED KILLED page
+% LocalWords:  CONTINUED sources forking Spawned successfully executing exiting
+% LocalWords:  next cat for COMMAND pts bash defunct TRAPPED DUMPED Killable PR
+% LocalWords:  SIGKILL static RLIMIT preemption PREEMPT VOLUNTARY IDLE RTPRIO
+% LocalWords:  Completely Fair compat Uniform CFQ Queuing elevator dev cfq RT
+% LocalWords:  Documentation block syscall ioprio IPRIO CLASS class best effort
+% LocalWords:  refresh semop dnotify MADV DONTFORK prctl WCLONE SIGCHL WALL
+% LocalWords:  WNOTHREAD DUMPABLE KEEPCAPS
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "gapil"
+%%% End: