Poche aggiunte
[gapil.git] / prochand.tex
index 3b40d63c067da2a040a08f67c9b246d53227329b..3ddfa4b0b23506451daaeb750afdcfe8ffd3fb64 100644 (file)
@@ -16,159 +16,187 @@ 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.
+\section{La gestione dei processi}
+\label{sec:proc_handling}
 
 
-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}.
+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.
 
 
-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}
-
-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
+Dopo l'esecuzione di una \func{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
 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,
-mentre nel figlio è zero; in questo modo il programma può identificare se
-viene eseguito dal padre o dal figlio. 
-
+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.
 
 
 
 
 
 
@@ -184,8 +212,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}