Correzioni minime
[gapil.git] / prochand.tex
index 3b40d63c067da2a040a08f67c9b246d53227329b..22da5c0194b660c71df60ba5a39403221ef5c9c3 100644 (file)
@@ -16,165 +16,329 @@ funzioni a questo connesse.
 
 Partiremo con una introduzione generale ai concetti che stanno alla base della
 gestione dei processi in unix. Introdurremo in questa sezione l'architettura
 
 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.  
+della gestione dei processi e le sue principali caratteristiche, e daremo una
+panoramica sull'uso delle principali funzioni per la gestione dei processi.
 
 \subsection{La gerarchia dei processi}
 \label{sec:proc_hierarchy}
 
 
 \subsection{La gerarchia dei processi}
 \label{sec:proc_hierarchy}
 
-Una delle caratteristiche essenziali di unix (che esamineremo in dettaglio più
-avanti) è che ogni processo può a sua volta generare altri processi figli
-(\textit{child}): questo è ad esempio quello che fa la shell quando mette in
-esecuzione il programma che gli indichiamo nella linea di comando.
-
-Una seconda caratteristica di unix è che ogni processo viene sempre generato
-in tale modo da un processo genitore (\textit{parent}) attraverso una apposita
-system call. Questo vale per tutti i processi, tranne per un processo
-speciale, che normalmente è \file{/sbin/init}, che invece viene lanciato dal
-kernel finita la fase di avvio e che quindi non è figlio di nessuno.
-
-Tutto ciò significa che, come per i file su disco, i processi sono organizzati
-gerarchicamente dalla relazione fra genitori e figli; alla base dell'albero in
-questo caso c'è \file{init} che è progenitore di ogni altro processo.
-
-
-\subsection{La gestione dei processi}
+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
+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 \acr{pid} (da \textit{process identifier}).
+
+Una seconda caratteristica è che la generazione di un processo è una
+operazione separata rispetto al lancio di un programma. In genere la sequenza
+è sempre quella di creare un nuovo processo, il quale si eseguirà, in un passo
+successivo, il programma voluto: questo è ad esempio quello che fa la shell
+quando mette in esecuzione il programma che gli indichiamo nella linea di
+comando.
+
+Una terza caratteristica è che ogni processo viene sempre generato da un altro
+che viene chiamato processo genitore (\textit{parent process}). Questo vale
+per tutti i processi, con una eccezione (dato che ci deve essere un punto di
+partenza), esiste sempre infatti un processo speciale, che normalmente è
+\cmd{/sbin/init}, che viene lanciato dal kernel quando questo ha finito la
+fase di avvio, esso essendo il primo processo lanciato ha sempre il \acr{pid}
+uguale a 1 e non è figlio di nessuno.
+
+Questo è ovviamente un processo speciale, che in genere si occupa di far
+partire tutti gli processi altri necessari al funzionamento del sistema,
+inoltre \cmd{init} è essenziale per svolgere una serie di compiti
+amministrativi nelle operazioni ordinarie del sistema (torneremo si alcuni di
+essi in \secref{}) 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, è possibile farlo ad esempio passando la riga \cmd{init=/bin/sh}
+all'avvio).
+
+Dato che tutti i processi successivi sono comunque generati da \cmd{init} o da
+suoi figli tutto ciò comporta che, i processi sono organizzati gerarchicamente
+dalla relazione fra genitori e figli, in maniera analoga a come i file sono
+organizzati in un albero di directory con alla base \file{/} (si veda
+\secref{sec:file_file_struct}); in questo caso alla base dell'albero c'è il
+processo \cmd{init} che è progenitore di ogni altro processo\footnote{in
+  realtà questo non è del tutto vero, in Linux ci sono alcuni processi che pur
+  comparendo come figli di init (ad esempio in \cmd{pstree}) sono generati
+  direttamente dal kernel, come \cmd{keventd}, \cmd{kswapd}, etc.}.
+
+
+\subsection{Una panoramica sulle funzioni di gestione}
 \label{sec:proc_handling_intro}
 
 \label{sec:proc_handling_intro}
 
-I processi vengono creati dalla funzione \texttt{fork}; in genere questa è una
-system call, ma Linux però usa un'altra nomenclatura, e la funzione fork è
-basata a sua volta sulla system call \texttt{clone}, che viene usata anche per
-generare i \textit{thread}.  Il processo figlio creato dalla \textit{fork} è
-una copia identica del processo processo padre, solo che ha un suo pid
-proprio.
+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}).
 
 Se si vuole che il processo padre si fermi fino alla conclusione del processo
 
 Se si vuole che il processo padre si fermi fino alla conclusione del processo
-figlio questo deve essere specificato subito dopo la fork chiamando la
-funzione \texttt{wait} o la funzione \texttt{waitpid}, che restituiscono anche
-una informazione abbastanza limitata (il codice di uscita) sulle cause della
-terminazione del processo.
+figlio questo deve essere specificato subito dopo la \func{fork} chiamando la
+funzione \func{wait} o la funzione \func{waitpid}; queste funzioni
+restituiscono anche una informazione abbastanza limitata (il codice di uscita)
+sulle cause della terminazione del processo.
 
 Quando un processo ha concluso il suo compito o ha incontrato un errore non
 
 Quando un processo ha concluso il suo compito o ha incontrato un errore non
-risolvibile esso può essere terminato con la funzione \texttt{exit} (si veda
-quanto discusso in \secref{sec:proc_termination}). La vita del processo
-però termina solo quando viene chiamata la quando la sua conclusione viene
-ricevuta dal processo padre, a quel punto tutte le risorse allocate nel
-sistema ad esso associate vengono rilasciate.
+risolvibile esso può essere terminato con la funzione \func{exit} (si veda
+quanto discusso in \secref{sec:proc_termination}). 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.
 
 Avere due processi che eseguono esattamente lo stesso codice non è molto
 
 Avere due processi che eseguono esattamente lo stesso codice non è molto
-utile, normalmente si genera un secondo processo per affidargli l'esecuzione di
-un compito specifico (ad esempio gestire una connessione dopo che questa è
+utile, normalmente si genera un secondo processo per affidargli l'esecuzione
+di un compito specifico (ad esempio gestire una connessione dopo che questa è
 stata stabilita), o fargli eseguire (come fa la shell) un altro programma. Per
 stata stabilita), o fargli eseguire (come fa la shell) un altro programma. Per
-questo si usa la seconda funzione fondamentale per programmazione coi processi
-che è la \texttt{exec}.
+quest'ultimo caso si usa la seconda funzione fondamentale per programmazione
+coi processi che è la \func{exec}.
 
 
-Il programma che un processo sta eseguendo si chiama immagine del processo
-(\textit{process image}), le funzioni della famiglia \func{exec} permettono
-di caricare un'altro programma da disco sostituendo quest'ultimo alla process
-image corrente, questo fa si che la precedente immagine venga completamente
-cancellata e quando il nuovo programma esce anche il processo termina, senza
-ritornare alla precedente immagine.
+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
+processo termina, e non si può tornare alla precedente immagine.
 
 Per questo motivo la \func{fork} e la \func{exec} sono funzioni molto
 particolari con caratteristiche uniche rispetto a tutte le altre, infatti la
 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).
 
 
 Per questo motivo la \func{fork} e la \func{exec} sono funzioni molto
 particolari con caratteristiche uniche rispetto a tutte le altre, infatti la
 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).
 
-I processi vengono creati dalla funzione \texttt{fork}; in genere questa è una
-system call, ma Linux però usa un'altra nomenclatura, e la funzione fork è
-basata a sua volta sulla system call \texttt{clone}, che viene usata anche per
-generare i \textit{thread}.  Il processo figlio creato dalla \textit{fork} è
-una copia identica del processo processo padre, solo che ha un suo pid
-proprio.
-
-Se si vuole che il processo padre si fermi fino alla conclusione del processo
-figlio questo deve essere specificato subito dopo la fork chiamando la
-funzione \texttt{wait} o la funzione \texttt{waitpid}, che restituiscono anche
-una informazione abbastanza limitata (il codice di uscita) sulle cause della
-terminazione del processo.
-
-Quando un processo ha concluso il suo compito o ha incontrato un errore non
-risolvibile esso può essere terminato con la funzione \texttt{exit} (si veda
-quanto discusso in \secref{sec:proc_termination}). La vita del processo
-però termina solo quando viene chiamata la quando la 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 di
-un compito specifico (ad esempio gestire una connessione dopo che questa è
-stata stabilita), o fargli eseguire (come fa la shell) un altro programma. Per
-questo si usa la seconda funzione fondamentale per programmazione coi processi
-che è la \texttt{exec}.
-
-Il programma che un processo sta eseguendo si chiama immagine del processo
-(\textit{process image}), le funzioni della famiglia \func{exec} permettono
-di caricare un'altro programma da disco sostituendo quest'ultimo alla process
-image corrente, questo fa si che la precedente immagine venga completamente
-cancellata e quando il nuovo programma esce anche il processo termina, senza
-ritornare alla precedente immagine.
-
-Per questo motivo la \func{fork} e la \func{exec} sono funzioni molto
-particolari con caratteristiche uniche rispetto a tutte le altre, infatti la
-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}
+\label{sec:proc_handling}
 
 
-\section{Il controllo dei processi}
-\label{sec:proc_control}
+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 lore creazione, terminazione, e la messa in esecuzione di altri
+programmi.
 
 
-Esamineremo in questa sezione le varie funzioni per il controllo dei processi:
-la loro creazione, la terminazione, l'esecuzione di altri programmi. Prima di
-trattare in dettaglio le singole funzioni, 
 
 \subsection{Gli identificatori dei processi}
 
 \subsection{Gli identificatori dei processi}
-\label{sec:proc_id}
-
-Ogni processo viene identificato dal sistema da un numero identificativo
-unico, il \textit{process id} o \acr{pid}. Questo 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 (init) ha sempre il pid uguale a uno.
-
-Ogni processo è identificato univocamente dal sistema per il suo pid;
-quest'ultimo è un tipo di dato standard, il \texttt{pid\_t} che in genere è un
-intero con segno (nel caso di Linux e delle glibc il tipo usato è
-\texttt{int}).
-
-Tutti i processi inoltre portano traccia del pid del genitore, chiamato in
-genere \textit{ppid} (da \textit{Parente Process Id}). Questi identificativi
-possono essere ottenuti da un programma usando le funzioni:
+\label{sec:proc_pid}
+
+Come accennato nell'introduzione ogni processo viene identificato dal sistema
+da un numero identificativo unico, il \textit{process id} o \acr{pid};
+quest'ultimo è un tipo di dato standard, il \type{pid\_t} che in genere è un
+intero con segno (nel caso di Linux e delle glibc il tipo usato è \type{int}).
+
+Il \acr{pid} viene assegnato in forma progressiva ogni volta che un nuovo
+processo viene creato, fino ad un limite massimo (in genere essendo detto
+numero memorizzato in un intero a 16 bit si arriva a 32767) oltre il quale si
+riparte dal numero più basso disponibile (FIXME: verificare, non sono sicuro).
+Per questo motivo processo il processo di avvio (\cmd{init}) ha sempre il
+\acr{pid} uguale a uno. 
+
+Tutti i processi inoltre memorizzano anche il \acr{pid} del genitore da cui
+sono stati creati, questo viene chiamato in genere \acr{ppid} (da
+\textit{parent process id}) ed è normalmente utilizzato per il controllo di
+sessione.  Questi due identificativi possono essere ottenuti da programma
+usando le funzioni:
 \begin{functions}
 \headdecl{sys/types.h}
 \headdecl{unistd.h}
 \funcdecl{pid\_t getpid(void)} restituisce il pid del processo corrente.
 \funcdecl{pid\_t getppid(void)} restituisce il pid del padre del processo
     corrente.
 \begin{functions}
 \headdecl{sys/types.h}
 \headdecl{unistd.h}
 \funcdecl{pid\_t getpid(void)} restituisce il pid del processo corrente.
 \funcdecl{pid\_t getppid(void)} restituisce il pid del padre del processo
     corrente.
+
+Entrambe le funzioni non riportano condizioni di errore. 
 \end{functions}
 
 \end{functions}
 
+Il fatto che il \acr{pid} sia un numero univoco per il sistema lo rende il
+candidato ideale per generare ultieriori indicatori associati al processo di
+cui diventa possibile garantire l'unicità: ad esempio la funzione
+\func{tmpname} (si veda \secref{sec:file_temp_file}) usa il \acr{pid} per
+generare un pathname univoco, che non potrà essere replicato da un'altro
+processo che usi la stessa funzione. 
+
+Tutti i processi figli dello stesso processo padre sono detti
+\textit{sibling}, questa è un'altra delle relazioni usate nel controllo di
+sessione, in cui si raggruppano tutti i processi creati su uno stesso
+terminale una volta che si è effettuato il login. Torneremo su questo
+argomento in \secref{cap:terminal}, dove esamineremo tutti gli altri
+identificativi associati ad un processo relativi al controllo di sessione.
 
 
 \subsection{La funzione \func{fork}}
 \label{sec:proc_fork}
 
 
 
 \subsection{La funzione \func{fork}}
 \label{sec:proc_fork}
 
-La funzione \func{fork} 
+La funzione \func{fork} è la funzione fondamentale della gestione dei processi
+in unix; come si è detto l'unico modo di creare un nuovo processo è attraverso
+l'uso di questa funzione, che è quindi la base per il multitasking; il protipo
+della funzione è:
 
 
+\begin{functions}
+  \headdecl{sys/types.h} 
+  \headdecl{unistd.h} 
+  
+  \funcdecl{pid\_t fork(void)} 
+  
+  Restituisce zero al padre e il \acr{pid} al figlio in caso di successo,
+  ritorna -1 al padre (senza creare il figlio) in caso di errore;
+  \texttt{errno} può assumere i valori:
+  \begin{errlist}
+  \item \macro{EAGAIN} non ci sono risorse sufficienti per creare un'altro
+    processo (per allocare la tabella delle pagine e le strutture del task) o
+    si è esaurito il numero di processi disponibili.
+  \item \macro{ENOMEM} non è stato possibile allocare la memoria per le
+    strutture necessarie al kernel per creare il nuovo processo.
+  \end{errlist}
+\end{functions}
 
 
-Dopo l'esecuzione di una fork sia il processo padre che il processo figlio
-continuano ad essere eseguiti normalmente, ed il processo figlio esegue
-esattamente lo stesso codice del padre. La sola differenza è che nel processo
-padre il valore di ritorno della funzione fork è il pid del processo figlio,
+Dopo l'esecuzione di una \func{fork} sia il processo padre che il processo
+figlio continuano ad essere eseguiti normalmente alla istruzione seguente la
+\func{fork}; il processo figlio è però una copia del padre, e riceve una copia
+dei segmenti di testo, stack e dati (vedi \secref{sec:proc_mem_layout}), ed
+esegue esattamente lo stesso codice del padre, ma la memoria è copiata, non
+condivisa\footnote{In generale il segmento di testo, che è identico, è
+  condiviso e tenuto in read-only, linux poi utilizza la tecnica del
+  \textit{copy-on-write}, per cui la memoria degli altri segmenti viene
+  copiata dal kernel per il nuovo processo solo in caso di scrittura, rendendo
+  molto più efficiente il meccanismo} pertanto padre e figlio vedono variabili
+diverse.
+
+La differenza che si ha nei due processi è che nel processo padre il valore di
+ritorno della funzione fork è il \acr{pid} del processo figlio, mentre nel
+figlio è zero; in questo modo il programma può identificare se viene eseguito
+dal padre o dal figlio.
+
+\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 i;
+    int nchild;
+    pid_t pid;
+
+    ...        /* handling options */
+
+    /* There must be remaing parameters */
+    if (optind == argc) {
+        usage();
+    }
+    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) {
+            printf("Error on %d child creation, %s\n", i, strerror(errno));
+        }
+        if (pid == 0) {   /* child */
+            printf("Child %d successfully executing\n", i++);
+            sleep(2);
+            printf("Child %d exiting\n", i);
+            exit(0);
+        } else {          /* parent */
+            printf("Spawned %d child, pid %d \n", i, pid);
+        }
+    }
+    /* normal exit */
+    return 0;
+}
+  \end{lstlisting}
+  \caption{Esempio di codice per la creazione di nuovi processi.}
+  \label{fig:proc_fork_code}
+\end{figure}
+
+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. 
 
 mentre nel figlio è zero; in questo modo il programma può identificare se
 viene eseguito dal padre o dal figlio. 
 
-
+La scelta di questi valori comunque 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}, vista in \secref{sec:proc_pid}) e si usa il valore nullo, che
+non può essere il \acr{pid} di nessun processo.
+
+In \curfig\ si è riportato il corpo del codice dell'esempio \cmd{forktest},
+che ci permette di illustrare l'uso della funzione \func{fork}, creando un
+numero di figli specificato a linea di comando; il codice completo, compresa
+la parte che gestisce le opzioni a riga di comando, è disponibile nel file
+\file{ForkTest.c}.
+
+Decifrato il numero di figli da creare, il ciclo principale del programma
+(\texttt{\small 28--40}) esegue in successione la creazione dei processi figli
+controllando il successo della chiamata a \func{fork} (\texttt{\small
+  29--31}); ciascun figlio (\texttt{\small 29--31}) si limita a stampare il
+suo numero di successione, attendere 3 secondi e scrivere un messaggio prima
+di uscire. Il processo padre invece (\texttt{\small 29--31}) stampa un
+messaggio di creazione e procede nell'esecuzione del ciclo. Se eseguiamo il
+comando otterremo come output sul terminale:
+\begin{verbatim}
+[piccardi@selidor sources]$ ./forktest 5
+Test for forking 5 child
+Spawned 1 child, pid 840 
+Child 1 successfully executing
+Child 2 successfully executing
+Spawned 2 child, pid 841 
+Spawned 3 child, pid 842 
+Child 3 successfully executing
+Spawned 4 child, pid 843 
+Child 4 successfully executing
+Child 5 successfully executing
+Spawned 5 child, pid 844 
+[piccardi@selidor sources]$ Child 2 exiting
+Child 1 exiting
+Child 4 exiting
+Child 3 exiting
+Child 5 exiting
+\end{verbatim}
+
+Come si vede 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}, nel caso
+mostrato sopra ad esempio si può notare come dopo la creazione il secondo ed
+il quinto figlio sia stato stati eseguiti per primi, mantre per gli altri
+figli è stato eseguito per primo 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, si sono ottenute situazioni
+completamente diverse, compreso 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, e se è necessaria una qualche forma
+di precedenza occorrerà provvedere ad espliciti meccanismi di
+sincronizzazione, pena il rischio di incorrere nelle cosiddette \textit{race
+  conditions}.
+
+Si ricordi 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}) saranno effettive solo per essi, e non hanno alcun effetto sul valore
+che le stesse variabili hanno nel processo padre.
 
 
 \subsection{Le funzioni \texttt{wait} e  \texttt{waitpid}}
 \label{sec:proc_wait}
 
 
 
 \subsection{Le funzioni \texttt{wait} e  \texttt{waitpid}}
 \label{sec:proc_wait}
 
+
 \subsection{Le funzioni \texttt{exec}}
 \label{sec:proc_exec}
 
 \subsection{Le funzioni \texttt{exec}}
 \label{sec:proc_exec}
 
@@ -184,8 +348,79 @@ viene eseguito dal padre o dal figlio.
 \section{Il controllo di accesso}
 \label{sec:proc_perms}
 
 \section{Il controllo di accesso}
 \label{sec:proc_perms}
 
-Va messo qui tutta la storia su effective, real, saved uid, e pure le cose di
-Linux come il filesystem uid.
+In questa sezione esamineremo le problematiche relative al controllo di
+accesso dal punto di vista del processi; gli identificativi usati, come questi
+vengono modificati nella creazione e nel lancio di nuovi processi, e le varie
+funzioni per la loro manipolazione diretta.
+
+
+\subsection{Utente e gruppo di un processo}
+\label{sec:proc_user_group}
+
+Abbiamo già accennato in \secref{sec:intro_multiuser} ad ogni utente ed gruppo
+sono associati due identificatori univoci, lo \acr{uid} e il \acr{gid} che li
+contraddistinguono nei confonti del kernel. Questi identificatori stanno alla
+base del sistema di permessi e protezioni di un sistema unix, e vengono usati
+anche nella gestione dei privilegi di accesso dei processi.
+
+In realtà ad ogni processo è associato un certo numero di identificatori, il
+cui elenco è riportato \ntab, in genere questi derivano direttamente
+dall'utente che ha lanciato il processo (attraverso i valori di \acr{uid} e
+\acr{gid}), e vengono usati sia per il controllo di accesso ai file che per la
+gestione dei privilegi associati ai processi stessi.
+\begin{table}[htb]
+  \centering
+  \begin{tabular}[c]{|c|l|l|}
+    \hline
+    Sigla & Significato & Utilizzo \\ 
+    \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{daved 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  \\ 
+    \hline
+  \end{tabular}
+  \caption{Identificatori di utente e gruppo associati a ciascun processo.}
+  \label{tab:proc_uid_gid}
+\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}.
+Questi non vengono mai cambiati nella creazione di nuovi processi e restano
+sempre gli stessi per tutti i processi avviati in una sessione. In realtà è
+possibile modificarli (vedi \secref{sec:proc_setuid}), ma solo per un processo
+che abbia i privilegi di amministratore (ed è così infatti che \cmd{login},
+che gira con i privilegi di amministratore, li setta 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 gli identificativi usati per il controllo
+di accesso ai file secondo quanto descritto in dettaglio in
+\secref{sec:file_perm_overview}. Normalmente sono uguali al \textit{real user
+  id} e al \textit{real group id}, a meno che il file posto in esecuzione non
+abbia i bit \acr{suid} o \acr{sgid} settati, nel qual caso vengono settati
+rispettivamente all'\acr{uid} e \acr{gid} del 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 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}.
+
 
 \subsection{Le funzioni \texttt{setuid} e \texttt{setgid}}
 \label{sec:proc_setuid}
 
 \subsection{Le funzioni \texttt{setuid} e \texttt{setgid}}
 \label{sec:proc_setuid}