Integrate una altra serie di correzioni e riscritte parti coi suggerimenti
[gapil.git] / prochand.tex
index dcad87688627b3e71577586a24b12835bb8941a4..38a9b2f18799685c4e5c23a94ce5279a33f37521 100644 (file)
@@ -14,13 +14,12 @@ finale introdurremo alcune problematiche generiche della programmazione in
 ambiente multitasking.
 
 
-
 \section{Introduzione}
 \label{sec:proc_gen}
 
-Inizieremo con una 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
+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.
 
@@ -37,9 +36,9 @@ numero unico, il cosiddetto \textit{process identifier} o, pi
 \acr{pid}.
 
 Una seconda caratteristica di un sistema Unix è che la generazione di un
-processo è unoperazione separata rispetto al lancio di un programma. In
+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.
 
@@ -107,10 +106,10 @@ Dato che tutti i processi attivi nel sistema sono comunque generati da
   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 unorganizzazione gerarchica ad
+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 \secref{sec:file_organization}); in \curfig\ si è mostrato
-il risultato del comando \cmd{pstree} che permette di mostrare questa
+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.
 
@@ -162,7 +161,7 @@ figlio sono affrontate in dettaglio in \secref{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 uninformazione
+\secref{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
@@ -182,8 +181,8 @@ 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
+corrente; questo fa sì che l'immagine precedente venga completamente
+cancellata. Questo significa che quando il nuovo programma esce, 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
@@ -207,17 +206,18 @@ programmi.
 \subsection{Gli identificatori dei processi}
 \label{sec:proc_pid}
 
-Come accennato nell'introduzione ogni processo viene identificato dal sistema
+Come accennato nell'introduzione, ogni processo viene identificato dal sistema
 da un numero identificativo unico, il \textit{process id} o \acr{pid};
 quest'ultimo è un tipo di dato standard, il \type{pid\_t} che in genere è un
-intero con segno (nel caso di Linux e delle \acr{glibc} il tipo usato è \type{int}).
+intero con segno (nel caso di Linux e delle \acr{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\footnote{FIXME: verificare, non sono
-  sicuro}.  Per questo motivo processo il processo di avvio (\cmd{init}) ha
-sempre il \acr{pid} uguale a uno.
+  sicuro}.  Per questo motivo, come visto in \secref{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
@@ -273,9 +273,9 @@ prototipo della funzione 
   \funcdecl{pid\_t fork(void)} 
   Crea un nuovo processo.
   
-  \bodydesc{Restituisce zero al padre e il \acr{pid} al figlio in caso di
-    successo, ritorna -1 al padre (senza creare il figlio) in caso di errore;
-    \var{errno} può assumere i valori:
+  \bodydesc{In caso di successo restituisce il \acr{pid} del figlio al padre e
+    zero al figlio; ritorna -1 al padre (senza creare il figlio) in caso di
+    errore; \var{errno} può assumere i valori:
   \begin{errlist}
   \item[\macro{EAGAIN}] non ci sono risorse sufficienti per creare un'altro
     processo (per allocare la tabella delle pagine e le strutture del task) o
@@ -286,12 +286,12 @@ prototipo della funzione 
 \end{functions}
 
 Dopo il successo dell'esecuzione di una \func{fork} sia il processo padre che
-il processo figlio continuano ad essere eseguiti normalmente allistruzione
+il processo figlio continuano ad essere eseguiti normalmente all'istruzione
 seguente la \func{fork}; il processo figlio è però una copia del padre, e
 riceve una copia dei segmenti di testo, stack e dati (vedi
 \secref{sec:proc_mem_layout}), ed esegue esattamente lo stesso codice del
-padre. Si tenga presente però che la memoria è copiata, non condivisa, pertanto
-padre e figlio vedono variabili diverse.
+padre. Si tenga presente però che la memoria è copiata, non condivisa,
+pertanto padre e figlio vedono variabili diverse.
 
 Per quanto riguarda la gestione della memoria in generale il segmento di
 testo, che è identico, è condiviso e tenuto in read-only per il padre e per i
@@ -392,7 +392,7 @@ operazione che viene chiamata \textit{spawn}. Nei sistemi unix-like 
 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à duso, avere le due funzioni separate permette al figlio di
+seconda modalità d'uso, avere le due funzioni separate permette al figlio di
 cambiare gli attributi del processo (maschera dei segnali, redirezione
 dell'output, \textit{user id}) prima della \func{exec}, rendendo così
 relativamente facile intervenire sulle le modalità di esecuzione del nuovo
@@ -401,11 +401,14 @@ programma.
 In \curfig\ si è riportato il corpo del codice del programma di esempio
 \cmd{forktest}, che ci permette di illustrare molte caratteristiche dell'uso
 della funzione \func{fork}. Il programma permette di creare un numero di figli
-specificato a linea di comando, e prende anche alcune opzioni per indicare
+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://firenze.linux.it/~piccardi/gapil_source.tgz}
+{\texttt{http://firenze.linux.it/\~~\hspace{-2.0mm}piccardi/gapil\_source.tgz}}.
 
 Decifrato il numero di figli da creare, il ciclo principale del programma
 (\texttt{\small 24--40}) esegue in successione la creazione dei processi figli
@@ -441,8 +444,8 @@ Go to next child
 \end{verbatim} %$
 \normalsize
 
-Esaminiamo questo risultato: una prima conclusione che si può trarre è non si
-può dire quale processo fra il padre ed il figlio venga eseguito per
+Esaminiamo questo risultato: una prima conclusione che si può trarre è che non
+si può dire quale processo fra il padre ed il figlio venga eseguito per
 primo\footnote{a partire dal kernel 2.5.2-pre10 è stato introdotto il nuovo
   scheduler di Ingo Molnar che esegue sempre per primo il figlio; per
   mantenere la portabilità è opportuno non fare comunque affidamento su questo
@@ -463,7 +466,7 @@ cui il processo padre ha eseguito pi
 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
+istruzioni del codice fra padre e figli, né sull'ordine in cui questi potranno
 essere messi in esecuzione. Se è necessaria una qualche forma di precedenza
 occorrerà provvedere ad espliciti meccanismi di sincronizzazione, pena il
 rischio di incorrere nelle cosiddette \textit{race condition} \index{race
@@ -472,9 +475,9 @@ rischio di incorrere nelle cosiddette \textit{race condition} \index{race
 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, 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).
+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
@@ -687,7 +690,7 @@ eseguite alla chiusura di un processo 
 
 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
+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.
 
@@ -715,7 +718,7 @@ terminato (si potrebbe avere cio
 
 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
+termina, il kernel controlla se è il padre di altri processi in esecuzione: in
 caso positivo allora il \acr{ppid} di tutti questi processi viene sostituito
 con il \acr{pid} di \cmd{init} (e cioè con 1); in questo modo ogni processo
 avrà sempre un padre (nel caso possiamo parlare di un padre \textsl{adottivo})
@@ -932,7 +935,7 @@ 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}). In questo
-caso infatti, dato che il segnale è generato dalla terminazione un figlio,
+caso infatti, dato che il segnale è generato dalla terminazione di un figlio,
 avremo la certezza che la chiamata a \func{wait} non si bloccherà.
 
 \begin{table}[!htb]
@@ -986,12 +989,12 @@ anomala), uno per indicare se 
 
 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}).
+\file{<sys/wait.h>} ed elencate in \tabref{tab:proc_status_macro} (si tenga
+presente che queste macro prendono come parametro la variabile di tipo
+\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
+\macro{WTERMSIG} può essere confrontato con le costanti definite in
 \file{signal.h} ed elencate in \tabref{tab:sig_signal_list}, e stampato usando
 le apposite funzioni trattate in \secref{sec:sig_strsignal}.
 
@@ -999,7 +1002,7 @@ le apposite funzioni trattate in \secref{sec:sig_strsignal}.
 \subsection{Le funzioni \func{wait3} e \func{wait4}}
 \label{sec:proc_wait4}
 
-Linux, seguendo unestensione di BSD, supporta altre due funzioni per la
+Linux, seguendo un'estensione di BSD, supporta altre due funzioni per la
 lettura dello stato di terminazione di un processo \func{wait3} e
 \func{wait4}, analoghe alle precedenti ma che prevedono un ulteriore
 parametro attraverso il quale il kernel può restituire al padre informazioni
@@ -1164,11 +1167,12 @@ 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}.
+viene posto in esecuzione è il primo che viene trovato. Se si ha un errore
+relativo a permessi di accesso insufficienti (cioè l'esecuzione della
+sottostante \func{execve} ritorna un \macro{EACCESS}), la ricerca viene
+proseguita nelle eventuali ulteriori directory indicate in \var{PATH}; solo se
+non viene trovato nessun altro file viene finalmente restituito
+\macro{EACCESS}.
 
 Le altre quattro funzioni si limitano invece a cercare di eseguire il file
 indicato dal parametro \var{path}, che viene interpretato come il
@@ -1177,7 +1181,7 @@ indicato dal parametro \var{path}, che viene interpretato come il
 \begin{figure}[htb]
   \centering
   \includegraphics[width=13cm]{img/exec_rel}
-  \caption{La interrelazione fra le sei funzioni della famiglia \func{exec}}
+  \caption{La interrelazione fra le sei funzioni della famiglia \func{exec}.}
   \label{fig:proc_exec_relat}
 \end{figure}
 
@@ -1213,12 +1217,11 @@ la lista completa 
   \var{tms\_cutime}, \var{tms\_ustime} (vedi \secref{sec:xxx_xxx}).
 \end{itemize*}
 
-Oltre a questo i segnali che sono stati settati per essere ignorati nel
-processo chiamante mantengono lo stesso settaggio pure nel nuovo programma,
-tutti gli altri segnali vengono settati alla loro azione di default. Un caso
-speciale è il segnale \macro{SIGCHLD} che, quando settato a \macro{SIG\_IGN},
-può anche non essere resettato a \macro{SIG\_DFL} (si veda
-\secref{sec:sig_gen_beha}).
+Inoltre i segnali che sono stati settati per essere ignorati nel processo
+chiamante mantengono lo stesso settaggio pure nel nuovo programma, tutti gli
+altri segnali vengono settati alla loro azione di default. Un caso speciale è
+il segnale \macro{SIGCHLD} che, quando settato a \macro{SIG\_IGN}, può anche
+non essere resettato a \macro{SIG\_DFL} (si veda \secref{sec:sig_gen_beha}).
 
 La gestione dei file aperti dipende dal valore che ha il flag di
 \textit{close-on-exec} (trattato in \secref{sec:file_fcntl}) per ciascun file
@@ -1227,7 +1230,7 @@ restano aperti. Questo significa che il comportamento di default 
 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
+Per le directory, lo standard POSIX.1 richiede che esse vengano chiuse
 attraverso una \func{exec}, in genere questo è fatto dalla funzione
 \func{opendir} (vedi \secref{sec:file_dir_read}) che effettua da sola il
 settaggio del flag di \textit{close-on-exec} sulle directory che apre, in
@@ -1356,13 +1359,13 @@ identificatori ai valori corrispondenti all'utente che entra nel sistema.
 
 Al secondo gruppo appartengono l'\textit{effective user id} e
 l'\textit{effective group id} (a cui si aggiungono gli eventuali
-\textit{supplementary group id} dei gruppi dei quale l'utente fa parte).
+\textit{supplementary group id} dei gruppi dei quali l'utente fa parte).
 Questi sono invece gli identificatori usati nella verifiche dei permessi del
 processo e per il controllo di accesso ai file (argomento affrontato in
 dettaglio in \secref{sec:file_perm_overview}). 
 
 Questi identificatori normalmente sono identici ai corrispondenti del gruppo
-\textsl{reale} tranne nel caso in cui, come accennato in
+\textit{real} tranne nel caso in cui, come accennato in
 \secref{sec:proc_exec}, il programma che si è posto in esecuzione abbia i bit
 \acr{suid} o \acr{sgid} settati (il significato di questi bit è affrontato in
 dettaglio in \secref{sec:file_suid_sgid}). In questo caso essi saranno settati
@@ -1401,10 +1404,10 @@ servano di nuovo.
 Questo in Linux viene fatto usando altri due gruppi di identificatori, il
 \textit{saved} ed il \textit{filesystem}, analoghi ai precedenti. Il primo
 gruppo è lo stesso usato in SVr4, e previsto dallo standard POSIX quando è
-definita la costante \macro{\_POSIX\_SAVED\_IDS}\footnote{in caso si abbia a
+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
+  definita.} il secondo gruppo è specifico di Linux e viene usato per
 migliorare la sicurezza con NFS.
 
 Il \textit{saved user id} e il \textit{saved group id} sono copie
@@ -1473,7 +1476,7 @@ riportare l'\textit{effective user id} a quello dell'utente che ha lanciato il
 programma, effettuare il lavoro che non necessita di privilegi aggiuntivi, ed
 eventualmente tornare indietro.
 
-Come esempio per chiarire dell'uso di queste funzioni prendiamo quello con cui
+Come esempio per chiarire l'uso di queste funzioni prendiamo quello con cui
 viene gestito l'accesso al file \file{/var/log/utmp}.  In questo file viene
 registrato chi sta usando il sistema al momento corrente; chiaramente non può
 essere lasciato aperto in scrittura a qualunque utente, che potrebbe
@@ -1484,7 +1487,7 @@ esempio tutti i programmi di terminale in X, o il programma \cmd{screen} che
 crea terminali multipli su una console) appartengono a questo gruppo ed hanno
 il bit \acr{sgid} settato.
 
-Quando uno di questi programmi (ad esempio \cmd{xterm}) viene lanciato la
+Quando uno di questi programmi (ad esempio \cmd{xterm}) viene lanciato, la
 situazione degli identificatori è la seguente:
 \begin{eqnarray*}
   \label{eq:1}
@@ -1493,7 +1496,7 @@ situazione degli identificatori 
   \textit{saved group id}     &=& \textrm{\acr{utmp}}
 \end{eqnarray*}
 in questo modo, dato che l'\textit{effective group id} è quello giusto, il
-programma può accedere a \file{/var/log/utmp} in scrittura ed aggiornarlo, a
+programma può accedere a \file{/var/log/utmp} in scrittura ed aggiornarlo. A
 questo punto il programma può eseguire una \code{setgid(getgid())} per settare
 l'\textit{effective group id} a quello dell'utente (e dato che il \textit{real
   group id} corrisponde la funzione avrà successo), in questo modo non sarà
@@ -1509,9 +1512,9 @@ e ogni processo lanciato dal terminale avrebbe comunque \acr{gid} come
 \textit{effective group id}. All'uscita dal terminale, per poter di nuovo
 aggiornare lo stato di \file{/var/log/utmp} il programma eseguirà una
 \code{setgid(utmp)} (dove \var{utmp} è il valore numerico associato al gruppo
-\acr{utmp}, ottenuto ad esempio con una \func{getegid}), dato che in questo
-caso il valore richiesto corrisponde al \textit{saved group id} la funzione
-avrà successo e riporterà la situazione a:
+\acr{utmp}, ottenuto ad esempio con una precedente \func{getegid}), dato che
+in questo caso il valore richiesto corrisponde al \textit{saved group id} la
+funzione avrà successo e riporterà la situazione a:
 \begin{eqnarray*}
   \label{eq:3}
   \textit{real group id}      &=& \textrm{\acr{gid} (invariato)}  \\
@@ -1580,7 +1583,7 @@ Lo stesso problema di propagazione dei privilegi ad eventuali processi figli
 si porrebbe per i \textit{saved id}: queste funzioni derivano da
 un'implementazione che non ne prevede la presenza, e quindi non è possibile
 usarle per correggere la situazione come nel caso precedente. Per questo
-motivo in Linux tutte le volte che vengono usata per modificare uno degli
+motivo in Linux tutte le volte che vengono usate per modificare uno degli
 identificatori ad un valore diverso dal \textit{real id} precedente, il
 \textit{saved id} viene sempre settato al valore dell'\textit{effective id}.
 
@@ -1616,7 +1619,7 @@ il settaggio di tutti gli identificatori.
 \subsection{Le funzioni \func{setresuid} e \func{setresgid}}
 \label{sec:proc_setresuid}
 
-Queste due funzioni sono unestensione introdotta in Linux dal kernel 2.1.44,
+Queste due funzioni sono un'estensione introdotta in Linux dal kernel 2.1.44,
 e permettono un completo controllo su tutti gli identificatori (\textit{real},
 \textit{effective} e \textit{saved}), i prototipi sono:
 \begin{functions}
@@ -1663,7 +1666,7 @@ prototipi sono:
   variabili di ritorno non sono validi.}
 \end{functions}
 
-Anche queste funzioni sono unestensione specifica di Linux, e non richiedono
+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 \textit{value result
   argument}). Si noti che queste funzioni sono le uniche in grado di leggere i
@@ -1715,11 +1718,10 @@ 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.
+Le ultime funzioni che esamineremo 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 è:
@@ -1760,8 +1762,8 @@ ottenere tutti i gruppi a cui appartiene un utente; il suo prototipo 
 \noindent la funzione esegue una scansione del database dei gruppi (si veda
 \secref{sec:sys_user_group}) 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.
+perché qualora il valore specificato sia troppo piccolo la funzione ritorna
+-1, 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
@@ -1784,7 +1786,7 @@ delle due 
 \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 è:
+un utente specifico, si può usare \func{initgroups} il cui prototipo è:
 \begin{functions}
   \headdecl{sys/types.h}
   \headdecl{grp.h}
@@ -1800,9 +1802,9 @@ un utente specifico si pu
 \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}.
+\file{/etc/groups}) cercando i gruppi di cui è membro \param{user} e
+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
@@ -1817,8 +1819,8 @@ In questa sezione tratteremo pi
 lo \textit{scheduler}\footnote{che è la parte del kernel che si occupa di
   stabilire quale processo dovrà essere posto in esecuzione.} assegna la CPU
 ai vari processi attivi. In particolare prendremo in esame i vari meccanismi
-con cui viene gestita l'assgnazione del tempo di CPU, ed illustreremo le varie
-funzioni di gestione.
+con cui viene gestita l'assegnazione del tempo di CPU, ed illustreremo le
+varie funzioni di gestione.
 
 
 \subsection{I meccanismi di \textit{scheduling}}
@@ -1829,16 +1831,20 @@ il tempo di CPU per l'esecuzione dei processi 
 ed oggetto di numerose ricerche; in ogni caso essa dipende in maniera
 essenziale anche dal tipo di utilizzo che deve essere fatto del sistema.
 
-La cosa è resa ancora più complicata dal fatto che con sistemi
-multi-processore si introduce anche la complessità dovuta alla scelta di 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 occorrono meccanismi per
-  determininare quale è la migliore scelta fra le diverse CPU.} Tutto questo
-comunque appartiene alle sottigliezze dell'implementazione del kernel, e dal
-punto di vista dei programmi che girano in user space di può pensare sempre
-alla risorsa tempo di esecuzione, governata dagli stessi mecca, che nel caso
-di più processori sarà a disposizione di più di un processo alla volta.
+La cosa è resa ancora più complicata dal fatto che con le architetture
+multi-processore si introduce anche la problematica dovuta alla scelta di
+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 occorrono
+  meccanismi per determininare quale è la migliore scelta fra le diverse CPU.}
+Tutto questo comunque appartiene alle sottigliezze dell'implementazione del
+kernel, e dal punto di vista dei programmi che girano in user space anche
+quando si hanno più processori, e quindi potenzialmente anche dei processi che
+sono eseguiti davvero in contemporanea, si può pensare alle politiche di
+scheduling come concernenti la risorsa \textsl{tempo di esecuzione}, la cui
+assegnazione sarà governata dagli stessi meccanismi di scelta di priorità,
+solo che nel caso di più processori sarà a disposizione di più di un processo
+alla volta.
 
 Si tenga presente inoltre che l'utilizzo della CPU è soltanto una delle
 risorse (insieme alla memoria e all'accesso alle periferiche) che sono
@@ -1849,8 +1855,8 @@ prestazioni.
 
 La politica tradizionale di scheduling di Unix (che tratteremo in
 \secref{sec:proc_sched_stand}) è sempre stata basata su delle priorità
-dinamiche, che assicurassaro che tutti i processi, anche i meno importanti,
-potessero ricevere un po' di tempo di CPU. 
+dinamiche, che assicurassero che tutti i processi, anche i meno importanti,
+potessero ricevere un po' di tempo di CPU.
 
 Lo standard POSIX però per tenere conto dei sistemi real-time,\footnote{per
   sistema real-time si intende un sistema in grado di eseguire operazioni in
@@ -1859,8 +1865,8 @@ Lo standard POSIX per
   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 in che devono essere
-eseguiti in un determinato momento non debbano aspettare la conclusione di un
+  ritenuto accettabile.} in cui è vitale che i processi che devono essere
+eseguiti in un determinato momento non debbano aspettare la conclusione di 
 altri processi che non hanno questa necessità, ha introdotto il concetto di
 \textsl{priorità assoluta}, chimata anche \textsl{priorità statica}, in
 contrapposizione con la normale priorità dinamica.
@@ -1882,7 +1888,6 @@ Questa viene in genere indicata con un numero
 
 
 
-
 \subsection{Il meccanismo di \textit{scheduling} standard}
 \label{sec:proc_sched_stand}
 
@@ -1917,7 +1922,7 @@ abbiamo affrontato la gestione dei processi.
 \label{sec:proc_atom_oper}
 
 La nozione di \textsl{operazione atomica} deriva dal significato greco della
-parola atomo, cioè indivisibile; si dice infatti che unoperazione è atomica
+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.
@@ -1942,7 +1947,7 @@ 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
+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 \secref{sec:sign_xxx}).
 
@@ -1963,7 +1968,7 @@ condiviso, onde evitare problemi con le ottimizzazioni del codice.
 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 unoperazione che viene eseguita da un processo in più
+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.
@@ -2010,26 +2015,26 @@ eseguire in maniera atomica le operazioni necessarie.
 
 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 thread di esecuzione senza che questo comporti nessun problema nella
-esecuzione della stessa. La problematica è comune nella programmazione
+un altro thread di esecuzione senza che questo comporti nessun problema
+nell'esecuzione della stessa. La problematica è comune nella programmazione
 multi-thread, ma si hanno gli stessi problemi quando si vogliono chiamare
 delle funzioni all'interno dei manipolatori dei segnali.
 
 Fintanto che una funzione opera soltanto con le variabili locali è rientrante;
-queste infatti vengono tutte le volte allocate nello stack, e un'altra
-invocazione non fa altro che allocarne un'altra copia. Una funzione può non
-essere rientrante quando opera su memoria che non è nello 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.
+queste infatti vengono allocate nello stack, e un'altra invocazione non fa
+altro che allocarne un'altra copia. Una funzione può non essere rientrante
+quando opera su memoria che non è nello 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