Risistemata introduzione e panoramica sulla gestione dei processi
[gapil.git] / prochand.tex
index 3b40d63c067da2a040a08f67c9b246d53227329b..b337e4de05fa73b64c708a9cf62a2c6da36ad7b4 100644 (file)
@@ -16,109 +16,99 @@ 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
-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}
 
-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}
 
-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
-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
-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
-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
-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).
 
-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{Il controllo dei processi}
 \label{sec:proc_control}
@@ -130,13 +120,13 @@ trattare in dettaglio le singole funzioni,
 \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.
+Come accennato 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