Correzioni varie, prima parte.
[gapil.git] / prochand.tex
index adf67a3052c38bf7512bbc7ce417055a3b98de5d..173c0bed7e7d585913bacce51ee78a8742d1f6ff 100644 (file)
@@ -1,17 +1,17 @@
 \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 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 distruzione dei processi, della gestione dei loro attributi e privilegi,
-e di tutte le funzioni a questo connesse. Infine nella sezione finale
-affronteremo alcune problematiche generiche della programmazione in ambiente
-multitasking.
+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.
 
 
 
@@ -25,7 +25,7 @@ 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
@@ -109,12 +109,46 @@ Dato che tutti i processi attivi nel sistema sono comunque generati da
   kernel, (come \cmd{keventd}, \cmd{kswapd}, etc.)} si possono classificare i
 processi con la relazione padre/figlio in una organizzazione gerarchica ad
 albero, in maniera analoga a come i file sono organizzati in un albero di
-directory (si veda \secref{sec:file_file_struct}); in \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.
+directory (si veda \secref{sec:file_organization}); 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.
+
+
+Il kernel mantiene una tabella dei processi attivi, la cosiddetta
+\textit{process table}; per ciascun processo viene mantenuta una voce nella
+tabella dei processi costituita da una struttura \type{task\_struct}, 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 \type{task\_struct} (che in seguito incontreremo a più
+riprese), è mostrato in \nfig.
+
+\begin{figure}[htb]
+  \centering
+  \includegraphics[width=13cm]{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}
+Come accennato in \secref{sec:intro_unix_struct} è lo \textit{scheduler} che
+decide quale processo mettere in esecuzione; esso viene eseguito ad ogni
+system call ed ad ogni interrupt, (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 \macro{HZ}, definita in \file{asm/param.h} Il
+valore usuale è 100 (è espresso in Hertz), si ha cioè un interrupt dal timer
+ogni centesimo di secondo.
+
+Ogni volta che viene eseguito, lo \textit{scheduler} effettua il calcolo delle
+priorità dei vari processi attivi (torneremo su questo in
+\secref{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 è
@@ -129,8 +163,7 @@ 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 figlio.
+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
@@ -160,15 +193,15 @@ 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 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 fondamentali che si usano per la
-creazione e la terminazione dei processi, e per la messa in esecuzione degli
-altri programmi.
+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}
@@ -182,9 +215,9 @@ intero con segno (nel caso di Linux e delle \acr{glibc} il tipo usato 
 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. 
+riparte dal numero più basso disponibile\footnote{FIXME: verificare, non sono
+  sicuro}.  Per questo motivo processo il processo di avvio (\cmd{init}) ha
+sempre il \acr{pid} uguale a uno.
 
 Tutti i processi inoltre memorizzano anche il \acr{pid} del genitore da cui
 sono stati creati, questo viene chiamato in genere \acr{ppid} (da
@@ -202,12 +235,12 @@ ottenuti da programma usando le funzioni:
 \noindent esempi dell'uso di queste funzioni sono riportati in
 \figref{fig:proc_fork_code}, nel programma di esempio \file{ForkTest.c}.
 
-Il fatto che il \acr{pid} sia un numero univoco per il sistema lo rende il
-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{tmpname} (si veda \secref{sec:file_temp_file}) usa il \acr{pid}
+per generare un pathname univoco, che non potrà essere replicato da un'altro
+processo che usi la stessa funzione.
 
 Tutti i processi figli dello stesso processo padre sono detti
 \textit{sibling}, questa è una delle relazioni usate nel \textsl{controllo di
@@ -262,7 +295,7 @@ padre, ma la memoria 
   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 della creazione di
-  un nuovo processo}, pertanto padre e figlio vedono variabili diverse.
+  un nuovo processo.}, pertanto padre e figlio vedono variabili diverse.
 
 La differenza che si ha nei due processi è che nel processo padre il valore di
 ritorno della funzione \func{fork} è il \acr{pid} del processo figlio, mentre
@@ -335,11 +368,11 @@ qualcos'altro non sta andando per il verso giusto) o si 
 sul numero totale di processi permessi all'utente (vedi \secref{sec:sys_xxx}).
 
 L'uso di \func{fork} avviene secondo due modalità principali; la prima è
-quella in cui all'interno di un programma si creano processi figli 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 server di rete in cui il padre riceve
+ed accetta le richieste da parte dei client, per ciascuna delle quali pone in
+esecuzione un figlio che è incaricato di fornire il servizio.
 
 La seconda modalità è quella in cui il processo vuole eseguire un altro
 programma; questo è ad esempio il caso della shell. In questo caso il processo
@@ -368,12 +401,12 @@ descrizione delle opzioni); il codice completo, compresa la parte che gestisce
 le opzioni a riga di comando, è disponibile nel file \file{ForkTest.c}.
 
 Decifrato il numero di figli da creare, il ciclo principale del programma
-(\texttt{\small 28--40}) esegue in successione la creazione dei processi figli
+(\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.
@@ -403,15 +436,16 @@ Go to next child
 
 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.
+primo\footnote{a partire dal kernel 2.5.2-pre10 è stato introdotto il nuovo
+  scheduler di Ingo Molnar che esegue sempre per primo il figlio; per
+  mantenere la portabilità è opportuno non fare comunque affidamento su questo
+  comportamento} dopo la chiamata a \func{fork}; dall'esempio si può notare
+infatti come nei primi due cicli sia stato eseguito per primo il padre (con la
+stampa del \acr{pid} del nuovo processo) per poi passare all'esecuzione del
+figlio (completata con i due avvisi di esecuzione ed uscita), e tornare
+all'esecuzione del padre (con la stampa del passaggio al ciclo successivo),
+mentre la terza volta è stato prima eseguito il figlio (fino alla conclusione)
+e poi il padre.
 
 In generale l'ordine di esecuzione dipenderà, oltre che dall'algoritmo di
 scheduling usato dal kernel, dalla particolare situazione in si trova la
@@ -423,14 +457,14 @@ 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
+essere messi in esecuzione. Se è necessaria una qualche forma di precedenza
 occorrerà provvedere ad espliciti meccanismi di sincronizzazione, pena il
 rischio di incorrere nelle cosiddette \textit{race condition} \index{race
   condition} (vedi \secref{sec:proc_race_cond}.
 
 Si noti inoltre che essendo i segmenti di memoria utilizzati dai singoli
 processi completamente separati, le modifiche delle variabili nei processi
-figli (come l'incremento di \var{i} in \texttt{\small 33}) sono visibili solo
+figli (come l'incremento di \var{i} in \texttt{\small 31}) sono visibili solo
 a loro, 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).
@@ -474,30 +508,29 @@ Il comportamento delle varie funzioni di interfaccia con i file 
 in gran dettaglio in \capref{cha:file_unix_interface} e in
 \secref{cha:files_std_interface}. Qui basta accennare che si sono usate le
 funzioni standard della libreria del C che prevedono l'output bufferizzato; e
-questa bufferizzazione (di veda \secref{sec:file_buffering}) varia a seconda
-che si tratti di un file su disco (in cui il buffer viene scaricato su disco
-solo quando necessario) o di un terminale (nel qual caso il buffer viene
-scaricato ad ogni carattere di a capo).
+questa bufferizzazione (trattata in dettaglio in \secref{sec:file_buffering})
+varia a seconda che si tratti di un file su disco (in cui il buffer viene
+scaricato su disco solo quando necessario) o di un terminale (nel qual caso il
+buffer viene scaricato ad ogni carattere di a capo).
 
 Nel primo esempio allora avevamo che ad ogni chiamata a \func{printf} il
 buffer veniva scaricato, e le singole righe erano stampate a video subito dopo
 l'esecuzione della \func{printf}. Ma con la redirezione su file la scrittura
-non avviene più alla fine di ogni riga e l'output resta nel buffer. 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 solo alla fine del file,
-dato che in questo caso il padre esce per ultimo, troveremo 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. 
+non avviene più alla fine di ogni riga e l'output resta nel buffer. Dato che
+ogni figlio riceve una copia della memoria del padre, esso riceverà anche
+quanto c'è nel buffer delle funzioni di I/O, comprese le linee scritte dal
+padre fino allora. Così quando il buffer viene scritto su disco all'uscita del
+figlio, troveremo nel file anche tutto quello che il processo padre aveva
+scritto prima della sua creazione.  E alla fine del file (dato che in questo
+caso il padre esce per ultimo) troveremo anche l'output completo del padre.
+
+L'esempio ci mostra un'altro aspetto fondamentale dell'interazione con i file,
+valido anche per l'esempio precedente, ma meno evidente: il fatto cioè che non
+solo processi diversi possono scrivere in contemporanea sullo stesso file
+(l'argomento della condivisione dei file è trattato in dettaglio in
+\secref{sec:file_sharing}), ma anche che, a differenza di quanto avviene per
+le variabili, la posizione corrente sul file è condivisa fra il padre e tutti
+i processi figli.
 
 Quello che succede è che quando lo standard output del padre viene rediretto,
 lo stesso avviene anche per tutti i figli; la funzione \func{fork} infatti ha
@@ -551,11 +584,10 @@ comune dopo l'esecuzione di una \func{fork} 
 \item gli identificatori per il controllo di accesso: il \textit{real user
     id}, il \textit{real group id}, l'\textit{effective user id},
   l'\textit{effective group id} ed i \textit{supplementary group id} (vedi
-  \secref{sec:proc_user_group}).
+  \secref{sec:proc_access_id}).
 \item gli identificatori per il controllo di sessione: il \textit{process
     group id} e il \textit{session id} ed il terminale di controllo (vedi
   \secref{sec:sess_xxx} e \secref{sec:sess_xxx}).
-\item i flag di \acr{suid} e \acr{sgid} (vedi \secref{sec:file_suid_sgid}).
 \item la directory di lavoro e la directory radice (vedi
   \secref{sec:file_work_dir} e \secref{sec:file_chroot}).
 \item la maschera dei permessi di creazione (vedi \secref{sec:file_umask}).
@@ -594,7 +626,7 @@ 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 è
@@ -607,19 +639,18 @@ trattarla ulteriormente.
 \label{sec:proc_termination}
 
 In \secref{sec:proc_conclusion} abbiamo già affrontato le modalità con cui
-chiudere 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.
+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 \secref{sec:proc_conclusion} le tre modalità con cui un
 programma viene terminato in maniera normale: la chiamata di \func{exit} (che
 esegue le funzioni registrate per l'uscita e chiude gli stream), il ritorno
 dalla funzione \func{main} (equivalente alla chiamata di \func{exit}), e la
 chiamata ad \func{\_exit} (che passa direttamente alle operazioni di
 terminazione del processo da parte del kernel).
 
-Ma oltre alla conclusione normale abbiamo accennato che esistono anche delle
+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
@@ -645,11 +676,12 @@ eseguite alla chiusura di un processo 
   inviati in successione i segnali \macro{SIGHUP} e \macro{SIGCONT}
   (vedi \secref{sec:sess_xxx}).
 \end{itemize*}
-ma al di la di queste operazioni è necessario poter disporre di un meccanismo
-ulteriore che consenta di sapere come questa terminazione è avvenuta; dato che
-in un sistema unix-like tutto viene gestito attraverso i processi il
-meccanismo scelto consiste nel riportare lo stato di terminazione (il
-cosiddetto \textit{termination status}) al processo padre.
+
+Oltre queste operazioni è però necessario poter disporre di un meccanismo
+ulteriore che consenta di sapere come la terminazione è avvenuta: dato che in
+un sistema unix-like tutto viene gestito attraverso i processi il meccanismo
+scelto consiste nel riportare lo stato di terminazione (il cosiddetto
+\textit{termination status}) al processo padre.
 
 Nel caso di conclusione normale, abbiamo visto in \secref{sec:proc_conclusion}
 che lo stato di uscita del processo viene caratterizzato tramite il valore del
@@ -673,15 +705,15 @@ che sia cos
 terminato (si potrebbe avere cioè quello che si chiama un processo
 \textsl{orfano}). 
 
-Questa complicazione viene superata facendo in modo che il processo figlio
-venga \textsl{adottato} da \cmd{init}: come già accennato quando un processo
+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 è:
+avrà sempre un padre (nel caso possiamo parlare di un padre \textsl{adottivo})
+cui riportare il suo stato di terminazione.  Come verifica di questo
+comportamento possiamo eseguire il nostro programma \cmd{forktest} imponendo a
+ciascun processo figlio due secondi di attesa prima di uscire, il risultato è:
 
 \footnotesize
 \begin{verbatim}
@@ -763,27 +795,27 @@ 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.
+(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.
+c'è modo di eliminarli con il comando \cmd{kill}; l'unica possibilità di
+cancellarli dalla tabella dei processi è quella di terminare il processo che
+li ha generati, in modo che \cmd{init} possa adottarli e provvedere a
+concluderne la terminazione.
 
 
 \subsection{Le funzioni \func{wait} e  \func{waitpid}}
 \label{sec:proc_wait}
 
-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 \textit{zombie} la tabella dei processi; le funzioni
+deputate a questo compito sono sostanzialmente due, \func{wait} e
+\func{waitpid}. La prima, il cui prototipo è:
 \begin{functions}
 \headdecl{sys/types.h}
 \headdecl{sys/wait.h}
@@ -792,16 +824,14 @@ prototipo 
 Sospende il processo corrente finché un figlio non è uscito, o finché un
 segnale termina il processo o chiama una funzione di gestione. 
 
-\bodydesc{
-La funzione restituisce il \acr{pid} del figlio in caso di successo e -1 in
-caso di errore; \var{errno} può assumere i valori:
+\bodydesc{La funzione restituisce il \acr{pid} del figlio in caso di successo
+  e -1 in caso di errore; \var{errno} può assumere i valori:
   \begin{errlist}
   \item[\macro{EINTR}] la funzione è stata interrotta da un segnale.
-  \end{errlist}
-}
+  \end{errlist}}
 \end{functions}
 \noindent
-è presente fin dalle prime versioni di unix; la funzione ritorna non appena un
+è 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.
 
@@ -835,8 +865,8 @@ Attende la conclusione di un processo figlio.
   \begin{errlist}
   \item[\macro{EINTR}] se non è stata specificata l'opzione \macro{WNOHANG} e
     la funzione è stata interrotta da un segnale.
-  \item[\macro{ECHILD}] il processo specificato da \var{pid} non esiste o non è
-    figlio del processo chiamante.
+  \item[\macro{ECHILD}] il processo specificato da \param{pid} non esiste o
+    non è figlio del processo chiamante.
   \end{errlist}}
 \end{functions}
 
@@ -844,7 +874,7 @@ 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
+base del valore fornito dall'argomento \param{pid}, secondo lo
 specchietto riportato in \ntab:
 \begin{table}[!htb]
   \centering
@@ -869,31 +899,33 @@ specchietto riportato in \ntab:
   \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.
+Il comportamento di \func{waitpid} può inoltre essere modificato passando
+delle opportune opzioni tramite l'argomento \param{option}. I valori possibili
+sono il già citato \macro{WNOHANG}, che previene il blocco della funzione
+quando il processo figlio non è terminato, e \macro{WUNTRACED} (usata per il
+controllo di sessione, trattato in \capref{cha:session}) che fa ritornare la
+funzione anche per i processi figli che sono bloccati ed il cui stato non è
+stato ancora riportato al padre. Il valore dell'opzione deve essere
+specificato come maschera binaria ottenuta con l'OR delle suddette costanti
+con zero.
 
 La terminazione di un processo figlio è chiaramente un evento asincrono
 rispetto all'esecuzione di un programma e può avvenire in un qualunque
-momento, per questo motivo, come 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.
+momento. Per questo motivo, come accennato nella sezione precedente, una delle
+azioni prese dal kernel alla conclusione di un processo è quella di mandare un
+segnale di \macro{SIGCHLD} al padre. L'azione di default (si veda
+\secref{sec:sig_base}) per questo segnale è di essere ignorato, ma la sua
+generazione costituisce il meccanismo di comunicazione asincrona con cui il
+kernel avverte il processo padre che uno dei suoi figli è terminato.
 
 In genere in un programma non si vuole essere forzati ad attendere la
 conclusione di un processo per proseguire, specie se tutto questo serve solo
 per leggerne lo stato di chiusura (ed evitare la presenza di \textit{zombie}),
 per questo la modalità più usata per chiamare queste funzioni è quella di
 utilizzarle all'interno di un \textit{signal handler} (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à.
+su come gestire \macro{SIGCHLD} in \secref{sec:sig_sigwait_xxx}). In questo
+caso infatti, dato che il segnale è generato dalla terminazione un figlio,
+avremo la certezza che la chiamata a \func{wait} non si bloccherà.
 
 \begin{table}[!htb]
   \centering
@@ -934,19 +966,21 @@ certezza che la chiamata a \func{wait} non si bloccher
 \end{table}
 
 Entrambe le funzioni di attesa restituiscono lo stato di terminazione del
-processo tramite il puntatore \var{status} (se non interessa memorizzare lo
+processo tramite il puntatore \param{status} (se non interessa memorizzare lo
 stato si può passare un puntatore nullo). Il valore restituito da entrambe le
-funzioni dipende dall'implementazione, e tradizionalmente alcuni bit 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, 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 \curtab\ (si tenga presente che
-queste macro prendono come parametro la variabile di tipo \type{int} puntata
-da \var{status}).
+funzioni dipende dall'implementazione, e tradizionalmente alcuni bit (in
+genere 8) sono riservati per memorizzare lo stato di uscita, e altri per
+indicare il segnale che ha causato la terminazione (in caso di conclusione
+anomala), uno per indicare se è stato generato un core file, ecc.\footnote{le
+  definizioni esatte si possono trovare in \file{<bits/waitstatus.h>} ma
+  questo file non deve mai essere usato direttamente, esso viene incluso
+  attraverso \file{<sys/wait.h>}.}
+
+Lo standard POSIX.1 definisce una serie di macro di preprocessore da usare per
+analizzare lo stato di uscita. Esse sono definite sempre in
+\file{<sys/wait.h>} ed elencate in \curtab\ (si tenga presente che queste
+macro prendono come parametro la variabile di tipo \type{int} puntata da
+\var{status}).
 
 Si tenga conto che nel caso di conclusione anomala il valore restituito da
 \macro{WTERMSIG} può essere controllato contro le costanti definite in
@@ -957,12 +991,13 @@ le apposite funzioni trattate in \secref{sec:sig_strsignal}.
 \subsection{Le funzioni \func{wait3} e \func{wait4}}
 \label{sec:proc_wait4}
 
-Linux, seguendo una estensione di BSD, supporta altre due funzioni per la
-lettura dello stato di terminazione di un processo, analoghe a \func{wait} e
-\func{waitpid}, ma che prevedono un ulteriore parametro attraverso il quale il
-kernel può restituire al padre informazioni sulle risorse usate dal processo
-terminato e dai vari figli.  Queste funzioni, che diventano accessibili
-definendo la costante \macro{\_USE\_BSD}, sono:
+Linux, seguendo una estensione di BSD, supporta altre due funzioni,
+\func{wait} e \func{waitpd}, per la lettura dello stato di terminazione di un
+processo, analoghe alle precedenti ma che prevedono un ulteriore parametro
+attraverso il quale il kernel può restituire al padre informazioni sulle
+risorse usate dal processo terminato e dai vari figli.  I prototipi di queste
+funzioni, che diventano accessibili definendo la costante \macro{\_USE\_BSD},
+sono:
 \begin{functions}
   \headdecl{sys/times.h} 
   \headdecl{sys/types.h} 
@@ -980,38 +1015,9 @@ definendo la costante \macro{\_USE\_BSD}, sono:
 \end{functions}
 \noindent 
 la struttura \type{rusage} è definita in \file{sys/resource.h}, e viene
-utilizzata anche dalla funzione \func{getrusage} per ottenere le risorse di
-sistema usate dal processo; la sua definizione è riportata in \nfig.
-\begin{figure}[!htb]
-  \footnotesize
-  \centering
-  \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
-struct rusage {
-     struct timeval ru_utime; /* user time used */
-     struct timeval ru_stime; /* system time used */
-     long ru_maxrss;          /* maximum resident set size */
-     long ru_ixrss;           /* integral shared memory size */
-     long ru_idrss;           /* integral unshared data size */
-     long ru_isrss;           /* integral unshared stack size */
-     long ru_minflt;          /* page reclaims */
-     long ru_majflt;          /* page faults */
-     long ru_nswap;           /* swaps */
-     long ru_inblock;         /* block input operations */
-     long ru_oublock;         /* block output operations */
-     long ru_msgsnd;          /* messages sent */
-     long ru_msgrcv;          /* messages received */
-     long ru_nsignals;   ;    /* signals received */
-     long ru_nvcsw;           /* voluntary context switches */
-     long ru_nivcsw;          /* involuntary context switches */
-};
-    \end{lstlisting}
-  \end{minipage} 
-  \normalsize 
-  \caption{La struttura \var{rusage} per la lettura delle informazioni dei 
-    delle risorse usate da un processo.}
-  \label{fig:proc_rusage_struct}
-\end{figure}
+utilizzata anche dalla funzione \func{getrusage} (vedi \secref{sec:sys_xxx})
+per ottenere le risorse di sistema usate da un processo; la sua definizione è
+riportata in \figref{fig:sys_rusage_struct}.
 
 In genere includere esplicitamente \file{<sys/time.h>} non è più
 necessario, ma aumenta la portabilità, e serve in caso si debba accedere
@@ -1177,12 +1183,12 @@ 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}
+\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
+\item il \textit{real user id} ed il \textit{real group id} (vedi
+  \secref{sec:proc_access_id}).
+\item i \textit{supplementary group id} (vedi \secref{sec:proc_access_id}).
+\item il \textit{session id} ed il \textit{process group id} (vedi
   \secref{sec:sess_xxx}).
 \item il terminale di controllo (vedi \secref{sec:sess_xxx}).
 \item il tempo restante ad un allarme (vedi \secref{sec:sig_xxx}).
@@ -1218,12 +1224,12 @@ attraverso una \func{exec}, in genere questo 
 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}
+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
+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
+bit settato, nel qual caso \textit{effective user id} e \textit{effective
+  group id} vengono settati rispettivamente all'utente o al gruppo cui il file
 appartiene (per i dettagli vedi \secref{sec:proc_perms}).
 
 Se il file da eseguire è in formato \emph{a.out} e necessita di librerie
@@ -1258,8 +1264,8 @@ nuovi processi, e le varie funzioni per la loro manipolazione diretta e tutte
 le problematiche connesse ad una gestione accorta dei privilegi.
 
 
-\subsection{Utente e gruppo di un processo}
-\label{sec:proc_user_group}
+\subsection{Gli identificatori del controllo di accesso}
+\label{sec:proc_access_id}
 
 Come accennato in \secref{sec:intro_multiuser} il modello base\footnote{in
   realtà già esistono estensioni di questo modello base, che lo rendono più
@@ -1329,8 +1335,8 @@ identificatori, chiamati rispettivamente \textit{real} ed \textit{effective}.
   \label{tab:proc_uid_gid}
 \end{table}
 
-Al primo gruppo appartengono il \textit{real user ID} e il \textit{real group
-  ID}: questi vengono settati al login ai valori corrispondenti all'utente con
+Al primo gruppo appartengono il \textit{real user id} e il \textit{real group
+  id}: questi vengono settati al login ai valori corrispondenti all'utente con
 cui si accede al sistema (e relativo gruppo di default). Servono per
 l'identificazione dell'utente e normalmente non vengono mai cambiati. In
 realtà vedremo (in \secref{sec:proc_setuid}) che è possibile modificarli, ma
@@ -1339,8 +1345,8 @@ possibilit
 procedura di autenticazione lancia una shell per la quale setta questi
 identificatori ai valori corrispondenti all'utente che entra nel sistema.
 
-Al secondo gruppo appartengono l'\textit{effective user ID} e
-l'\textit{effective group ID} (a cui si aggiungono gli eventuali
+Al secondo gruppo appartengono l'\textit{effective user id} e
+l'\textit{effective group id} (a cui si aggiungono gli eventuali
 \textit{supplementary group id} dei gruppi dei quale l'utente fa parte).
 Questi sono invece gli identificatori usati nella verifiche dei permessi del
 processo e per il controllo di accesso ai file (argomento affrontato in
@@ -1361,16 +1367,16 @@ prototipi sono i seguenti:
 \begin{functions}
   \headdecl{unistd.h}
   \headdecl{sys/types.h}  
-  \funcdecl{uid\_t getuid(void)} Restituisce il \textit{real user ID} del
+  \funcdecl{uid\_t getuid(void)} Restituisce il \textit{real user id} del
   processo corrente.
 
-  \funcdecl{uid\_t geteuid(void)} Restituisce l'\textit{effective user ID} del
+  \funcdecl{uid\_t geteuid(void)} Restituisce l'\textit{effective user id} del
   processo corrente.
 
-  \funcdecl{gid\_t getgid(void)} Restituisce il \textit{real group ID} del
+  \funcdecl{gid\_t getgid(void)} Restituisce il \textit{real group id} del
   processo corrente.
 
-  \funcdecl{gid\_t getegid(void)} Restituisce l'\textit{effective group ID} del
+  \funcdecl{gid\_t getegid(void)} Restituisce l'\textit{effective group id} del
   processo corrente.
   
   \bodydesc{Queste funzioni non riportano condizioni di errore.}
@@ -1421,7 +1427,7 @@ di utente e gruppo associati dal kernel ad ogni processo, 
 
 Le due funzioni che vengono usate per cambiare identità (cioè utente e gruppo
 di appartenenza) ad un processo sono rispettivamente \func{setuid} e
-\func{setgid}; come accennato in \secref{sec:proc_user_group} in Linux esse
+\func{setgid}; come accennato in \secref{sec:proc_access_id} in Linux esse
 seguono la semantica POSIX che prevede l'esistenza del \textit{saved user id}
 e del \textit{saved group id}; i loro prototipi sono:
 \begin{functions}
@@ -1528,11 +1534,11 @@ e \textit{real id}. I loro prototipi sono:
 \headdecl{sys/types.h}
 
 \funcdecl{int setreuid(uid\_t ruid, uid\_t euid)} Setta il \textit{real user
-  ID} e l'\textit{effective user ID} del processo corrente ai valori
+  id} e l'\textit{effective user id} del processo corrente ai valori
 specificati da \var{ruid} e \var{euid}.
   
 \funcdecl{int setregid(gid\_t rgid, gid\_t egid)} Setta il \textit{real group
-  ID} e l'\textit{effective group ID} del processo corrente ai valori
+  id} e l'\textit{effective group id} del processo corrente ai valori
 specificati da \var{rgid} e \var{egid}.
 
 \bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
@@ -1571,6 +1577,34 @@ identificatori ad un valore diverso dal \textit{real id} precedente, il
 \textit{saved id} viene sempre settato al valore dell'\textit{effective id}.
 
 
+
+\subsection{Le funzioni \func{seteuid} e \func{setegid}}
+\label{sec:proc_seteuid}
+
+Queste funzioni sono un'estensione allo standard POSIX.1 (ma sono comunque
+supportate dalla maggior parte degli Unix) e usate per cambiare gli
+\textit{effective id}; i loro prototipi sono:
+\begin{functions}
+\headdecl{unistd.h}
+\headdecl{sys/types.h}
+
+\funcdecl{int seteuid(uid\_t uid)} Setta l'\textit{effective user id} del
+processo corrente a \var{uid}.
+
+\funcdecl{int setegid(gid\_t gid)} Setta l'\textit{effective group id} del
+processo corrente a \var{gid}.
+
+\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
+  di fallimento: l'unico errore possibile è \macro{EPERM}.}
+\end{functions}
+
+Gli utenti normali possono settare l'\textit{effective id} solo al valore del
+\textit{real id} o del \textit{saved id}, l'amministratore può specificare
+qualunque valore. Queste funzioni sono usate per permettere a root di settare
+solo l'\textit{effective id}, dato che l'uso normale di \func{setuid} comporta
+il settaggio di tutti gli identificatori.
+
 \subsection{Le funzioni \func{setresuid} e \func{setresgid}}
 \label{sec:proc_setresuid}
 
@@ -1582,13 +1616,13 @@ e permettono un completo controllo su tutti gli identificatori (\textit{real},
 \headdecl{sys/types.h}
 
 \funcdecl{int setresuid(uid\_t ruid, uid\_t euid, uid\_t suid)} Setta il
-\textit{real user ID}, l'\textit{effective user ID} e il \textit{saved user
-  ID} del processo corrente ai valori specificati rispettivamente da
+\textit{real user id}, l'\textit{effective user id} e il \textit{saved user
+  id} del processo corrente ai valori specificati rispettivamente da
 \var{ruid}, \var{euid} e \var{suid}.
   
 \funcdecl{int setresgid(gid\_t rgid, gid\_t egid, gid\_t sgid)} Setta il
-\textit{real group ID}, l'\textit{effective group ID} e il \textit{saved group
-  ID} del processo corrente ai valori specificati rispettivamente da
+\textit{real group id}, l'\textit{effective group id} e il \textit{saved group
+  id} del processo corrente ai valori specificati rispettivamente da
 \var{rgid}, \var{egid} e \var{sgid}.
 
 \bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
@@ -1601,41 +1635,39 @@ identificatori usando uno qualunque dei valori correnti di \textit{real id},
 valori che vuole; un valore di -1 per un qualunque parametro lascia inalterato
 l'identificatore corrispondente.
 
-
-
-\subsection{Le funzioni \func{seteuid} e \func{setegid}}
-\label{sec:proc_seteuid}
-
-Queste funzioni sono un'estensione allo standard POSIX.1 (ma sono comunque
-supportate dalla maggior parte degli Unix) e usate per cambiare gli
-\textit{effective id}; i loro prototipi sono:
+Per queste funzioni esistono anche due controparti che permettono di leggere
+in blocco i vari identificatori: \func{getresuid} e \func{getresgid}; i loro
+prototipi sono: 
 \begin{functions}
 \headdecl{unistd.h}
 \headdecl{sys/types.h}
 
-\funcdecl{int seteuid(uid\_t uid)} Setta l'\textit{effective user ID} del
-processo corrente a \var{uid}.
-
-\funcdecl{int setegid(gid\_t gid)} Setta l'\textit{effective group ID} del
-processo corrente a \var{gid}.
+\funcdecl{int getresuid(uid\_t *ruid, uid\_t *euid, uid\_t *suid)} Legge il
+\textit{real user id}, l'\textit{effective user id} e il \textit{saved user
+  id} del processo corrente.
+  
+\funcdecl{int getresgid(gid\_t *rgid, gid\_t *egid, gid\_t *sgid)} Legge il
+\textit{real group id}, l'\textit{effective group id} e il \textit{saved group
+  id} del processo corrente.
 
-\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
-  di fallimento: l'unico errore possibile è \macro{EPERM}.}
+\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso di
+  fallimento: l'unico errore possibile è \macro{EFAULT} se gli indirizzi delle
+  variabili di ritorno non sono validi.}
 \end{functions}
 
-Gli utenti normali possono settare l'\textit{effective id} solo al valore del
-\textit{real id} o del \textit{saved id}, l'amministratore può specificare
-qualunque valore. Queste funzioni sono usate per permettere a root di settare
-solo l'\textit{effective id}, dato che l'uso normale di \func{setuid} comporta
-il settaggio di tutti gli identificatori.
+Anche queste funzioni sono una estensione specifica di Linux, e non richiedono
+nessun privilegio. I valori sono restituiti negli argomenti, che vanno
+specificati come puntatori (è un'altro esempio di \textit{value result
+  argument}). Si noti che queste funzioni sono le uniche in grado di leggere i
+\textit{saved id}.
+
 
 \subsection{Le funzioni \func{setfsuid} e \func{setfsgid}}
 \label{sec:proc_setfsuid}
 
 Queste funzioni sono usate per settare gli identificatori usati da Linux per
 il controllo dell'accesso ai file. Come già accennato in
-\secref{sec:proc_user_group} in Linux è definito questo ulteriore gruppo di
+\secref{sec:proc_access_id} in Linux è definito questo ulteriore gruppo di
 identificatori, che di norma sono assolutamente equivalenti agli
 \textit{effective id}, dato che ogni cambiamento di questi ultimi viene
 immediatamente riportato sui \textit{filesystem id}.
@@ -1658,10 +1690,10 @@ usate se si intendono scrivere programmi portabili; i loro prototipi sono:
 \begin{functions}
 \headdecl{sys/fsuid.h}
 
-\funcdecl{int setfsuid(uid\_t fsuid)} Setta il \textit{filesystem user ID} del
+\funcdecl{int setfsuid(uid\_t fsuid)} Setta il \textit{filesystem user id} del
 processo corrente a \var{fsuid}.
 
-\funcdecl{int setfsgid(gid\_t fsgid)} Setta l'\textit{filesystem group ID} del
+\funcdecl{int setfsgid(gid\_t fsgid)} Setta l'\textit{filesystem group id} del
 processo corrente a \var{fsgid}.
 
 \bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
@@ -1672,23 +1704,130 @@ privilegi di amministratore o, per gli altri utenti, se il valore specificato
 coincide con uno dei \textit{real}, \textit{effective} o \textit{saved id}.
 
 
+\subsection{Le funzioni \func{setgroups} e \func{getgroups}}
+\label{sec:proc_setgroups}
+
+Le ultime funzioni che esamineremo sono quelle sono quelle che permettono di
+operare sui gruppi supplementari. Ogni processo può avere fino a
+\macro{NGROUPS\_MAX} gruppi supplementari 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 è \func{getgroups};
+questa funzione è definita nello standard POSIX 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 del processo sul vettore \param{list} di dimensione
+  \param{size}.
+  
+  \bodydesc{La funzione restituisce il numero di gruppi letti in caso di
+    successo e -1 in caso di fallimento, nel qual caso \var{errno} viene
+    settata a: 
+    \begin{errlist}
+    \item[\macro{EFAULT}] \param{list} non ha un indirizzo valido.
+    \item[\macro{EINVAL}] il valore di \param{size} è diverso da zero ma
+      minore del numero di gruppi supplementari del processo.
+    \end{errlist}}
+\end{functions}
+\noindent non è specificato se la funzione inserisca o meno nella lista
+l'\textit{effective user id} 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, \func{getgrouplist}, può invece essere usata per
+ottenere tutti i gruppi a cui appartiene un 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 dell'utente \param{user}.
+  
+  \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}
+\noindent la funzione esegue una scansione del database dei gruppi (si veda
+\secref{sec:sys_xxx}) e ritorna 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
+e passando indietro il numero dei gruppi trovati.
+
+Per settare 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 è \func{setgroups}, ed il suo prototipo è:
+\begin{functions}
+  \headdecl{sys/types.h}
+  \headdecl{grp.h}
+  
+  \funcdecl{int setgroups(size\_t size, gid\_t *list)} Setta i gruppi
+  supplementari del processo ai valori specificati in \param{list}.
+
+  \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+    fallimento, nel qual caso \var{errno} viene settata a:
+    \begin{errlist}
+    \item[\macro{EFAULT}] \param{list} non ha un indirizzo valido.
+    \item[\macro{EPERM}] il processo non ha i privilegi di amministratore.
+    \item[\macro{EINVAL}] il valore di \param{size} è maggiore del valore
+    massimo (\macro{NGROUPS}, che per Linux è 32).
+    \end{errlist}}
+\end{functions}
+
+Se invece si vogliono settare i gruppi supplementari del processo a quelli di
+un utente specifico si può usare \func{initgroups} il cui prototipo è:
+\begin{functions}
+  \headdecl{sys/types.h}
+  \headdecl{grp.h}
+
+  \funcdecl{int initgroups(const char *user, gid\_t group)} Setta i gruppi
+  supplementari del processo a quelli di cui è membro l'utente \param{user},
+  aggiungendo il gruppo addizionale \param{group}.
+  
+  \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+    fallimento, nel qual caso \var{errno} viene settata agli stessi valori di
+    \func{setgroups} più \macro{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
+\file{/etc/groups}) cercando i gruppi di cui è membro \param{user} costruendo
+una lista di gruppi supplementari a cui aggiunge \param{group}, che poi setta
+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}.
+
+
+\section{La gestione della priorità di esecuzione}
+\label{sec:proc_priority}
+
+In questa sezione tratteremo più approfonditamente i meccanismi con il quale
+lo \textit{scheduler} assegna la CPU ai vari processi attivi, illustrando le
+varie funzioni che permettono di leggere e modificare le priorità di
+esecuzione dei programmi.
+
+
+
+
+
 \section{Problematiche di programmazione multitasking}
 \label{sec:proc_multi_prog}
 
 Benché i processi siano strutturati in modo da apparire il più possibile come
-indipendenti l'uno dall'altro, nella programmazione in un sistema multiutente
-occorre tenere conto di tutta una serie di problematiche che normalmente non
+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. 
+programma alla volta.
 
-Pur non essendo tutto questo direttamente legato alla modalità specifica in
-cui il multitasking è implementato in un sistema unix-like, né al solo
-concetto di multitasking (le stesse problematiche si presentano ad esempio
-nella gestione degli interrupt hardware), in questa sezione conclusiva del
-capitolo in cui abbiamo affrontato la gestione dei processi, introdurremo
-sinteticamente queste problematiche, che ritroveremo a più riprese in capitoli
-successivi, con una breve definizione della terminologia e delle loro
-caratteristiche di fondo.
+Pur essendo questo argomento di carattere generale, in questa sezione
+conclusiva del capitolo in cui abbiamo affrontato la gestione dei processi ci
+è parso opportuno introdurre sinteticamente queste problematiche, che
+ritroveremo a più riprese in capitoli successivi, dando una breve descrizione
+delle loro caratteristiche principali e della terminologia relativa.
 
 
 \subsection{Le operazioni atomiche}
@@ -1819,4 +1958,7 @@ varie funzioni di libreria, che sono identificate aggiungendo il suffisso
 
 
 
-
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "gapil"
+%%% End: