X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=prochand.tex;h=9f6ae1fd2854f9c84bc67e013136f026b78dcc42;hp=177155d436192e9a36ea0584c709041277243a59;hb=c474f4307db945bc45287edd0ea4c2c29374d0ee;hpb=687f101ae37d793ffda23c39ca8735e127b5fc9d diff --git a/prochand.tex b/prochand.tex index 177155d..9f6ae1f 100644 --- a/prochand.tex +++ b/prochand.tex @@ -43,7 +43,7 @@ caratteristiche di Unix (che esamineremo in dettaglio pi qualunque processo può a sua volta generarne altri, detti processi figli (\textit{child process}). Ogni processo è identificato presso il sistema da un numero univoco, il cosiddetto \textit{process identifier} o, più brevemente, -\acr{pid}, assegnato in forma progressiva (vedi \secref{sec:proc_pid}) quando +\acr{pid}, assegnato in forma progressiva (vedi sez.~\ref{sec:proc_pid}) quando il processo viene creato. Una seconda caratteristica di un sistema Unix è che la generazione di un @@ -65,7 +65,7 @@ Ovviamente \cmd{init} partire tutti gli altri processi necessari al funzionamento del sistema, inoltre \cmd{init} è essenziale per svolgere una serie di compiti amministrativi nelle operazioni ordinarie del sistema (torneremo su alcuni di -essi in \secref{sec:proc_termination}) e non può mai essere terminato. La +essi in sez.~\ref{sec:proc_termination}) 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) è ad esempio possibile lanciare una shell al suo @@ -120,7 +120,7 @@ Dato che tutti i processi attivi nel sistema sono comunque generati da possono classificare i 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 \figref{fig:proc_tree} si è mostrato il +sez.~\ref{sec:file_organization}); in fig.~\ref{fig:proc_tree} si è mostrato 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. @@ -133,7 +133,7 @@ strutture usate a questo scopo sono dichiarate nell'header file \file{linux/sched.h}, ed uno schema semplificato, che riporta la struttura delle principali informazioni contenute nella \struct{task\_struct} (che in seguito incontreremo a più riprese), è mostrato in -\figref{fig:proc_task_struct}. +fig.~\ref{fig:proc_task_struct}. \begin{figure}[htb] \centering @@ -143,7 +143,7 @@ seguito incontreremo a pi \label{fig:proc_task_struct} \end{figure} -Come accennato in \secref{sec:intro_unix_struct} è lo +Come accennato in sez.~\ref{sec:intro_unix_struct} è lo \textit{scheduler}\index{scheduler} che decide quale processo mettere in esecuzione; esso viene eseguito ad ogni system call ed ad ogni interrupt,\footnote{più in una serie di altre occasioni. NDT completare questa @@ -154,12 +154,12 @@ interrupt periodico secondo la frequenza specificata dalla costante Hertz.\footnote{Il valore usuale di questa costante è 100, per tutte le architetture eccetto l'alpha, per la quale è 1000. Occorre fare attenzione a non confondere questo valore con quello dei clock tick (vedi - \secref{sec:sys_unix_time}).} + sez.~\ref{sec:sys_unix_time}).} %Si ha cioè un interrupt dal timer ogni centesimo di secondo. Ogni volta che viene eseguito, lo \textit{scheduler}\index{scheduler} effettua il calcolo delle priorità dei vari processi attivi (torneremo su questo in -\secref{sec:proc_priority}) e stabilisce quale di essi debba essere posto in +sez.~\ref{sec:proc_priority}) e stabilisce quale di essi debba essere posto in esecuzione fino alla successiva invocazione. @@ -171,17 +171,17 @@ tramite la funzione \func{fork}; il nuovo processo (che viene chiamato \textsl{figlio}) creato dalla \func{fork} è una copia identica del processo processo originale (detto \textsl{padre}), ma ha un nuovo \acr{pid} e viene eseguito in maniera indipendente (le differenze fra padre e figlio sono -affrontate in dettaglio in \secref{sec:proc_fork}). +affrontate in dettaglio in sez.~\ref{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 un'informazione +sez.~\ref{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 risolvibile esso può essere terminato con la funzione \func{exit} (si veda -quanto discusso in \secref{sec:proc_conclusion}). La vita del processo però +quanto discusso in sez.~\ref{sec:proc_conclusion}). 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. @@ -230,18 +230,18 @@ intero con segno (nel caso di Linux e delle \acr{glibc} il tipo usato Il \acr{pid} viene assegnato in forma progressiva\footnote{in genere viene assegnato il numero successivo a quello usato per l'ultimo processo creato, a meno che questo numero non sia già utilizzato per un altro \acr{pid}, - \acr{pgid} o \acr{sid} (vedi \secref{sec:sess_proc_group}).} ogni volta che -un nuovo processo viene creato, fino ad un limite che, essendo il \acr{pid} un -numero positivo memorizzato in un intero a 16 bit, arriva ad un massimo di -32768. Oltre questo valore l'assegnazione riparte dal numero più basso -disponibile a partire da un minimo di 300,\footnote{questi valori, fino al - kernel 2.4.x, sono definiti dalla macro \const{PID\_MAX} in \file{threads.h} - e direttamente in \file{fork.c}, con il kernel 2.5.x e la nuova interfaccia - per i thread creata da Ingo Molnar anche il meccanismo di allocazione dei - \acr{pid} è stato modificato.} che serve a riservare i \acr{pid} più bassi -ai processi eseguiti direttamente dal kernel. Per questo motivo, come visto -in \secref{sec:proc_hierarchy}, il processo di avvio (\cmd{init}) ha sempre il -\acr{pid} uguale a uno. + \acr{pgid} o \acr{sid} (vedi sez.~\ref{sec:sess_proc_group}).} ogni volta +che un nuovo processo viene creato, fino ad un limite che, essendo il +\acr{pid} un numero positivo memorizzato in un intero a 16 bit, arriva ad un +massimo di 32768. Oltre questo valore l'assegnazione riparte dal numero più +basso disponibile a partire da un minimo di 300,\footnote{questi valori, fino + al kernel 2.4.x, sono definiti dalla macro \const{PID\_MAX} in + \file{threads.h} e direttamente in \file{fork.c}, con il kernel 2.5.x e la + nuova interfaccia per i thread creata da Ingo Molnar anche il meccanismo di + allocazione dei \acr{pid} è stato modificato.} che serve a riservare i +\acr{pid} più bassi ai processi eseguiti direttamente dal kernel. Per questo +motivo, come visto in sez.~\ref{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 @@ -262,30 +262,30 @@ prototipi sono: \bodydesc{Entrambe le funzioni non riportano condizioni di errore.} \end{functions} \noindent esempi dell'uso di queste funzioni sono riportati in -\figref{fig:proc_fork_code}, nel programma \file{ForkTest.c}. +fig.~\ref{fig:proc_fork_code}, nel programma \file{ForkTest.c}. Il fatto che il \acr{pid} sia un numero univoco per il sistema lo rende un candidato per generare ulteriori indicatori associati al processo di cui diventa possibile garantire l'unicità: ad esempio in alcune implementazioni la -funzione \func{tmpname} (si veda \secref{sec:file_temp_file}) usa il \acr{pid} -per generare un pathname univoco, che non potrà essere replicato da un altro -processo che usi la stessa funzione. +funzione \func{tmpname} (si veda sez.~\ref{sec:file_temp_file}) usa il +\acr{pid} per generare un pathname univoco, che non potrà essere replicato da +un altro processo che usi la stessa funzione. Tutti i processi figli dello stesso processo padre sono detti \textit{sibling}, questa è una delle relazioni usate nel \textsl{controllo di sessione}, in cui si raggruppano i processi creati su uno stesso terminale, o relativi allo stesso login. Torneremo su questo argomento in dettaglio in -\secref{cha:session}, dove esamineremo gli altri identificativi associati ad +cap.~\ref{cha:session}, dove esamineremo gli altri identificativi associati ad un processo e le varie relazioni fra processi utilizzate per definire una sessione. Oltre al \acr{pid} e al \acr{ppid}, (e a quelli che vedremo in -\secref{sec:sess_proc_group}, relativi al controllo di sessione), ad ogni +sez.~\ref{sec:sess_proc_group}, relativi al controllo di sessione), ad ogni processo vengono associati degli altri identificatori che vengono usati per il controllo di accesso. Questi servono per determinare se un processo può eseguire o meno le operazioni richieste, a seconda dei privilegi e dell'identità di chi lo ha posto in esecuzione; l'argomento è complesso e sarà -affrontato in dettaglio in \secref{sec:proc_perms}. +affrontato in dettaglio in sez.~\ref{sec:proc_perms}. \subsection{La funzione \func{fork}} @@ -318,7 +318,7 @@ Dopo il successo dell'esecuzione di una \func{fork} sia il processo padre che il processo figlio continuano ad essere eseguiti normalmente a partire dall'istruzione successiva alla \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 +sez.~\ref{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. @@ -344,7 +344,7 @@ La scelta di questi valori di ritorno non avere più figli, ed il valore di ritorno di \func{fork} è l'unico modo che gli 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}, vedi \secref{sec:proc_pid}) per cui si usa il valore nullo, +\func{getppid}, vedi sez.~\ref{sec:proc_pid}) per cui si usa il valore nullo, che non è il \acr{pid} di nessun processo. \begin{figure}[!htb] @@ -361,14 +361,14 @@ Normalmente la chiamata a \func{fork} pu sono già troppi processi nel sistema (il che di solito è sintomo che qualcos'altro non sta andando per il verso giusto) o si è ecceduto il limite sul numero totale di processi permessi all'utente (vedi -\secref{sec:sys_resource_limit}, ed in particolare -\tabref{tab:sys_rlimit_values}). +sez.~\ref{sec:sys_resource_limit}, ed in particolare +tab.~\ref{tab:sys_rlimit_values}). L'uso di \func{fork} avviene secondo due modalità principali; la prima è quella in cui all'interno di un programma si creano processi figli cui viene affidata l'esecuzione di una certa sezione di codice, mentre il processo padre ne esegue un'altra. È il caso tipico dei programmi server (il modello -\textit{client-server} è illustrato in \secref{sec:net_cliserv}) in cui il +\textit{client-server} è illustrato in sez.~\ref{sec:net_cliserv}) in cui il padre riceve ed accetta le richieste da parte dei programmi client, per ciascuna delle quali pone in esecuzione un figlio che è incaricato di fornire il servizio. @@ -376,7 +376,7 @@ il servizio. La seconda modalità è quella in cui il processo vuole eseguire un altro programma; questo è ad esempio il caso della shell. In questo caso il processo crea un figlio la cui unica operazione è quella di fare una \func{exec} (di -cui parleremo in \secref{sec:proc_exec}) subito dopo la \func{fork}. +cui parleremo in sez.~\ref{sec:proc_exec}) subito dopo la \func{fork}. Alcuni sistemi operativi (il VMS ad esempio) combinano le operazioni di questa seconda modalità (una \func{fork} seguita da una \func{exec}) in un'unica @@ -390,7 +390,7 @@ dell'output, identificatori) prima della \func{exec}, rendendo cos relativamente facile intervenire sulle le modalità di esecuzione del nuovo programma. -In \figref{fig:proc_fork_code} è riportato il corpo del codice del programma +In fig.~\ref{fig:proc_fork_code} è riportato il corpo del codice del programma di esempio \cmd{forktest}, che permette di illustrare molte caratteristiche dell'uso della funzione \func{fork}. Il programma crea un numero di figli specificato da linea di comando, e prende anche alcune opzioni per indicare @@ -465,7 +465,7 @@ essere messi in esecuzione. Se occorrerà provvedere ad espliciti meccanismi di sincronizzazione, pena il rischio di incorrere nelle cosiddette \textit{race condition}\index{race condition} -(vedi \secref{sec:proc_race_cond}). +(vedi sez.~\ref{sec:proc_race_cond}). Si noti inoltre che essendo i segmenti di memoria utilizzati dai singoli processi completamente separati, le modifiche delle variabili nei processi @@ -510,10 +510,10 @@ Go to next child che come si vede è completamente diverso da quanto ottenevamo sul terminale. Il comportamento delle varie funzioni di interfaccia con i file è analizzato -in gran dettaglio in \capref{cha:file_unix_interface} e in -\secref{cha:files_std_interface}. Qui basta accennare che si sono usate le +in gran dettaglio in cap.~\ref{cha:file_unix_interface} e in +cap.~\ref{cha:files_std_interface}. Qui basta accennare che si sono usate le funzioni standard della libreria del C che prevedono l'output bufferizzato; e -questa bufferizzazione (trattata in dettaglio in \secref{sec:file_buffering}) +questa bufferizzazione (trattata in dettaglio in sez.~\ref{sec:file_buffering}) varia a seconda che si tratti di un file su disco (in cui il buffer viene scaricato su disco solo quando necessario) o di un terminale (nel qual caso il buffer viene scaricato ad ogni carattere di a capo). @@ -533,7 +533,7 @@ L'esempio ci mostra un altro aspetto fondamentale dell'interazione con i file, valido anche per l'esempio precedente, ma meno evidente: il fatto cioè che non solo processi diversi possono scrivere in contemporanea sullo stesso file (l'argomento della condivisione dei file è trattato in dettaglio in -\secref{sec:file_sharing}), ma anche che, a differenza di quanto avviene per +sez.~\ref{sec:file_sharing}), ma anche che, a differenza di quanto avviene per le variabili, la posizione corrente sul file è condivisa fra il padre e tutti i processi figli. @@ -541,9 +541,9 @@ Quello che succede lo stesso avviene anche per tutti i figli; la funzione \func{fork} infatti ha la caratteristica di duplicare nei figli tutti i file descriptor aperti nel padre (allo stesso modo in cui lo fa la funzione \func{dup}, trattata in -\secref{sec:file_dup}), il che comporta che padre e figli condividono le +sez.~\ref{sec:file_dup}), il che comporta che padre e figli condividono le stesse voci della \textit{file table} (per la spiegazione di questi termini si -veda \secref{sec:file_sharing}) fra cui c'è anche la posizione corrente nel +veda sez.~\ref{sec:file_sharing}) fra cui c'è anche la posizione corrente nel file. In questo modo se un processo scrive sul file aggiornerà la posizione corrente @@ -586,23 +586,23 @@ comune dopo l'esecuzione di una \func{fork} \begin{itemize*} \item i file aperti e gli eventuali flag di \textit{close-on-exec}\index{close-on-exec} impostati (vedi - \secref{sec:proc_exec} e \secref{sec:file_fcntl}). + sez.~\ref{sec:proc_exec} e sez.~\ref{sec:file_fcntl}). \item gli identificatori per il controllo di accesso: l'\textsl{user-ID reale}, il \textsl{group-ID reale}, l'\textsl{user-ID effettivo}, il \textsl{group-ID effettivo} ed i \textit{group-ID supplementari} (vedi - \secref{sec:proc_access_id}). + sez.~\ref{sec:proc_access_id}). \item gli identificatori per il controllo di sessione: il \textit{process group-ID} e il \textit{session id} ed il terminale di controllo (vedi - \secref{sec:sess_proc_group}). + sez.~\ref{sec:sess_proc_group}). \item la directory di lavoro e la directory radice (vedi - \secref{sec:file_work_dir} e \secref{sec:file_chroot}). -\item la maschera dei permessi di creazione (vedi \secref{sec:file_umask}). -\item la maschera dei segnali bloccati (vedi \secref{sec:sig_sigmask}) e le - azioni installate (vedi \secref{sec:sig_gen_beha}). + sez.~\ref{sec:file_work_dir} e sez.~\ref{sec:file_chroot}). +\item la maschera dei permessi di creazione (vedi sez.~\ref{sec:file_umask}). +\item la maschera dei segnali bloccati (vedi sez.~\ref{sec:sig_sigmask}) e le + azioni installate (vedi sez.~\ref{sec:sig_gen_beha}). \item i segmenti di memoria condivisa agganciati al processo (vedi - \secref{sec:ipc_sysv_shm}). -\item i limiti sulle risorse (vedi \secref{sec:sys_resource_limit}). -\item le variabili di ambiente (vedi \secref{sec:proc_environ}). + sez.~\ref{sec:ipc_sysv_shm}). +\item i limiti sulle risorse (vedi sez.~\ref{sec:sys_resource_limit}). +\item le variabili di ambiente (vedi sez.~\ref{sec:proc_environ}). \end{itemize*} le differenze fra padre e figlio dopo la \func{fork} invece sono: \begin{itemize*} @@ -611,10 +611,10 @@ le differenze fra padre e figlio dopo la \func{fork} invece sono: \item il \acr{ppid} (\textit{parent process id}), quello del figlio viene impostato al \acr{pid} del padre. \item i valori dei tempi di esecuzione della struttura \struct{tms} (vedi - \secref{sec:sys_cpu_times}) che nel figlio sono posti a zero. -\item i \textit{lock} sui file (vedi \secref{sec:file_locking}), che non + sez.~\ref{sec:sys_cpu_times}) che nel figlio sono posti a zero. +\item i \textit{lock} sui file (vedi sez.~\ref{sec:file_locking}), che non vengono ereditati dal figlio. -\item gli allarmi ed i segnali pendenti (vedi \secref{sec:sig_gen_beha}), che +\item gli allarmi ed i segnali pendenti (vedi sez.~\ref{sec:sig_gen_beha}), che per il figlio vengono cancellati. \end{itemize*} @@ -645,12 +645,12 @@ deprecato; per questo eviteremo di trattarla ulteriormente. \subsection{La conclusione di un processo.} \label{sec:proc_termination} -In \secref{sec:proc_conclusion} abbiamo già affrontato le modalità con cui +In sez.~\ref{sec:proc_conclusion} abbiamo già affrontato le modalità con cui chiudere un programma, ma dall'interno del programma stesso; avendo a che fare con un sistema multitasking resta da affrontare l'argomento dal punto di vista di come il sistema gestisce la conclusione dei processi. -Abbiamo visto in \secref{sec:proc_conclusion} le tre modalità con cui un +Abbiamo visto in sez.~\ref{sec:proc_conclusion} le tre modalità con cui un programma viene terminato in maniera normale: la chiamata di \func{exit} (che esegue le funzioni registrate per l'uscita e chiude gli stream), il ritorno dalla funzione \func{main} (equivalente alla chiamata di \func{exit}), e la @@ -674,15 +674,15 @@ eseguite alla chiusura di un processo \item ad ogni processo figlio viene assegnato un nuovo padre (in genere \cmd{init}). \item viene inviato il segnale \const{SIGCHLD} al processo padre (vedi - \secref{sec:sig_sigchld}). + sez.~\ref{sec:sig_sigchld}). \item se il processo è un leader di sessione ed il suo terminale di controllo è quello della sessione viene mandato un segnale di \const{SIGHUP} a tutti i processi del gruppo di foreground e il terminale di controllo viene - disconnesso (vedi \secref{sec:sess_ctrl_term}). + disconnesso (vedi sez.~\ref{sec:sess_ctrl_term}). \item se la conclusione di un processo rende orfano un \textit{process group} ciascun membro del gruppo viene bloccato, e poi gli vengono inviati in successione i segnali \const{SIGHUP} e \const{SIGCONT} - (vedi ancora \secref{sec:sess_ctrl_term}). + (vedi ancora sez.~\ref{sec:sess_ctrl_term}). \end{itemize*} Oltre queste operazioni è però necessario poter disporre di un meccanismo @@ -691,18 +691,19 @@ un sistema unix-like tutto viene gestito attraverso i processi, il meccanismo scelto consiste nel riportare lo stato di terminazione (il cosiddetto \textit{termination status}) al processo padre. -Nel caso di conclusione normale, abbiamo visto in \secref{sec:proc_conclusion} -che lo stato di uscita del processo viene caratterizzato tramite il valore del -cosiddetto \textit{exit status}, cioè il valore passato alle funzioni -\func{exit} o \func{\_exit} (o dal valore di ritorno per \func{main}). Ma se -il processo viene concluso in maniera anomala il programma non può specificare -nessun \textit{exit status}, ed è il kernel che deve generare autonomamente il -\textit{termination status} per indicare le ragioni della conclusione anomala. +Nel caso di conclusione normale, abbiamo visto in +sez.~\ref{sec:proc_conclusion} che lo stato di uscita del processo viene +caratterizzato tramite il valore del cosiddetto \textit{exit status}, cioè il +valore passato alle funzioni \func{exit} o \func{\_exit} (o dal valore di +ritorno per \func{main}). Ma se il processo viene concluso in maniera anomala +il programma non può specificare nessun \textit{exit status}, ed è il kernel +che deve generare autonomamente il \textit{termination status} per indicare le +ragioni della conclusione anomala. Si noti la distinzione fra \textit{exit status} e \textit{termination status}: quello che contraddistingue lo stato di chiusura del processo e viene riportato attraverso le funzioni \func{wait} o \func{waitpid} (vedi -\secref{sec:proc_wait}) è sempre quest'ultimo; in caso di conclusione normale +sez.~\ref{sec:proc_wait}) è sempre quest'ultimo; in caso di conclusione normale il kernel usa il primo (nel codice eseguito da \func{\_exit}) per produrre il secondo. @@ -754,16 +755,16 @@ informazioni riguardo ai processi che sta terminando. Questo viene fatto mantenendo attiva la voce nella tabella dei processi, e memorizzando alcuni dati essenziali, come il \acr{pid}, i tempi di CPU usati -dal processo (vedi \secref{sec:sys_unix_time}) e lo stato di terminazione, +dal processo (vedi sez.~\ref{sec:sys_unix_time}) e lo stato di terminazione, mentre la memoria in uso ed i file aperti vengono rilasciati immediatamente. I processi che sono terminati, ma il cui stato di terminazione non è stato ancora ricevuto dal padre sono chiamati \textit{zombie}\index{zombie}, essi restano presenti nella tabella dei processi ed in genere possono essere identificati dall'output di \cmd{ps} per la presenza di una \texttt{Z} nella -colonna che ne indica lo stato (vedi \tabref{tab:proc_proc_states}). Quando il -padre effettuerà la lettura dello stato di uscita anche questa informazione, -non più necessaria, verrà scartata e la terminazione potrà dirsi completamente -conclusa. +colonna che ne indica lo stato (vedi tab.~\ref{tab:proc_proc_states}). Quando +il padre effettuerà la lettura dello stato di uscita anche questa +informazione, non più necessaria, verrà scartata e la terminazione potrà dirsi +completamente conclusa. Possiamo utilizzare il nostro programma di prova per analizzare anche questa condizione: lanciamo il comando \cmd{forktest} in background, indicando al @@ -792,10 +793,11 @@ presente quando si scrive un programma che deve essere mantenuto in esecuzione a lungo e creare molti figli. In questo caso si deve sempre avere cura di far leggere l'eventuale stato di uscita di tutti i figli (in genere questo si fa attraverso un apposito \textit{signal handler}, che chiama la funzione -\func{wait}, vedi \secref{sec:sig_sigchld} e \secref{sec:proc_wait}). Questa -operazione è necessaria perché anche se gli \textit{zombie}\index{zombie} non -consumano risorse di memoria o processore, occupano comunque una voce nella -tabella dei processi, che a lungo andare potrebbe esaurirsi. +\func{wait}, vedi sez.~\ref{sec:sig_sigchld} e sez.~\ref{sec:proc_wait}). +Questa operazione è necessaria perché anche se gli +\textit{zombie}\index{zombie} non consumano risorse di memoria o processore, +occupano comunque una voce nella tabella dei processi, che a lungo andare +potrebbe esaurirsi. Si noti che quando un processo adottato da \cmd{init} termina, esso non diviene uno \textit{zombie}\index{zombie}; questo perché una delle funzioni di @@ -846,7 +848,7 @@ pi Al ritorno della funzione lo stato di terminazione del figlio viene salvato nella variabile puntata da \param{status} e tutte le risorse del kernel -relative al processo (vedi \secref{sec:proc_termination}) vengono rilasciate. +relative al processo (vedi sez.~\ref{sec:proc_termination}) vengono rilasciate. Nel caso un processo abbia più figli il valore di ritorno (il \acr{pid} del figlio) permette di identificare qual'è quello che è uscito. @@ -860,7 +862,7 @@ sia ancora attivo. Per questo motivo lo standard POSIX.1 ha introdotto la funzione \funcd{waitpid} che effettua lo stesso servizio, ma dispone di una serie di funzionalità più ampie, legate anche al controllo di sessione (si veda -\secref{sec:sess_job_control}). Dato che è possibile ottenere lo stesso +sez.~\ref{sec:sess_job_control}). Dato che è possibile ottenere lo stesso comportamento di \func{wait} si consiglia di utilizzare sempre questa funzione, il cui prototipo è: \begin{functions} @@ -885,7 +887,7 @@ sempre fino a che un processo figlio non termina, mentre \func{waitpid} ha la possibilità si specificare un'opzione \const{WNOHANG} che ne previene il blocco; inoltre \func{waitpid} può specificare in maniera flessibile quale processo attendere, sulla base del valore fornito dall'argomento \param{pid}, -secondo lo specchietto riportato in \tabref{tab:proc_waidpid_pid}. +secondo lo specchietto riportato in tab.~\ref{tab:proc_waidpid_pid}. \begin{table}[!htb] \centering @@ -896,7 +898,7 @@ secondo lo specchietto riportato in \tabref{tab:proc_waidpid_pid}. \hline \hline $<-1$& -- & attende per un figlio il cui \textit{process group} (vedi - \secref{sec:sess_proc_group}) è uguale al + sez.~\ref{sec:sess_proc_group}) è uguale al valore assoluto di \param{pid}. \\ $-1$ & \const{WAIT\_ANY} & attende per un figlio qualsiasi, usata in questa maniera è equivalente a \func{wait}.\\ @@ -919,19 +921,20 @@ tracciare i processi bloccati. Il valore dell'opzione deve essere specificato come maschera binaria ottenuta con l'OR delle suddette costanti con zero. In genere si utilizza \const{WUNTRACED} all'interno del controllo di sessione, -(l'argomento è trattato in \secref{sec:sess_job_control}). In tal caso infatti -la funzione ritorna, restituendone il \acr{pid}, quando c'è un processo figlio -che è entrato in stato di sleep (vedi \tabref{tab:proc_proc_states}) e del -quale non si è ancora letto lo stato (con questa stessa opzione). In Linux -sono previste altre opzioni non standard relative al comportamento con i -thread, che riprenderemo in \secref{sec:thread_xxx}. +(l'argomento è trattato in sez.~\ref{sec:sess_job_control}). In tal caso +infatti la funzione ritorna, restituendone il \acr{pid}, quando c'è un +processo figlio che è entrato in stato di sleep (vedi +tab.~\ref{tab:proc_proc_states}) e del quale non si è ancora letto lo stato +(con questa stessa opzione). In Linux sono previste altre opzioni non standard +relative al comportamento con i thread, che riprenderemo in +sez.~\ref{sec:thread_xxx}. La terminazione di un processo figlio è chiaramente un evento asincrono rispetto all'esecuzione di un programma e può avvenire in un qualunque momento. Per questo motivo, come accennato nella sezione precedente, una delle azioni prese dal kernel alla conclusione di un processo è quella di mandare un segnale di \const{SIGCHLD} al padre. L'azione predefinita (si veda -\secref{sec:sig_base}) per questo segnale è di essere ignorato, ma la sua +sez.~\ref{sec:sig_base}) per questo segnale è di essere ignorato, ma la sua generazione costituisce il meccanismo di comunicazione asincrona con cui il kernel avverte il processo padre che uno dei suoi figli è terminato. @@ -941,7 +944,7 @@ per leggerne lo stato di chiusura (ed evitare la presenza di \textit{zombie}\index{zombie}), per questo la modalità più usata per chiamare queste funzioni è quella di utilizzarle all'interno di un \textit{signal handler} (vedremo un esempio di come gestire \const{SIGCHLD} con i segnali -in \secref{sec:sig_example}). In questo caso infatti, dato che il segnale è +in sez.~\ref{sec:sig_example}). In questo caso infatti, dato che il segnale è generato dalla terminazione di un figlio, avremo la certezza che la chiamata a \func{wait} non si bloccherà. @@ -961,7 +964,7 @@ generato dalla terminazione di un figlio, avremo la certezza che la chiamata a \val{WIFEXITED} ha restituito un valore non nullo.\\ \macro{WIFSIGNALED(s)} & Vera se il processo figlio è terminato in maniera anomala a causa di un segnale che non è stato catturato (vedi - \secref{sec:sig_notification}).\\ + sez.~\ref{sec:sig_notification}).\\ \macro{WTERMSIG(s)} & restituisce il numero del segnale che ha causato la terminazione anomala del processo. Può essere valutata solo se \val{WIFSIGNALED} ha restituito un valore non nullo.\\ @@ -997,14 +1000,14 @@ 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{} ed elencate in \tabref{tab:proc_status_macro} (si tenga +\file{} ed elencate in tab.~\ref{tab:proc_status_macro} (si tenga presente che queste macro prendono come parametro la variabile di tipo \ctyp{int} puntata da \param{status}). Si tenga conto che nel caso di conclusione anomala il valore restituito da \val{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}. +\file{signal.h} ed elencate in tab.~\ref{tab:sig_signal_list}, e stampato +usando le apposite funzioni trattate in sez.~\ref{sec:sig_strsignal}. \subsection{Le funzioni \func{wait3} e \func{wait4}} @@ -1034,8 +1037,8 @@ sono: \noindent la struttura \struct{rusage} è definita in \file{sys/resource.h}, e viene utilizzata anche dalla funzione \func{getrusage} (vedi -\secref{sec:sys_resource_use}) per ottenere le risorse di sistema usate da un -processo; la sua definizione è riportata in \figref{fig:sys_rusage_struct}. +sez.~\ref{sec:sys_resource_use}) per ottenere le risorse di sistema usate da un +processo; la sua definizione è riportata in fig.~\ref{fig:sys_rusage_struct}. \subsection{Le funzioni \func{exec}} @@ -1052,7 +1055,7 @@ disco. Ci sono sei diverse versioni di \func{exec} (per questo la si è chiamata famiglia di funzioni) che possono essere usate per questo compito, in realtà -(come mostrato in \figref{fig:proc_exec_relat}), sono tutte un front-end a +(come mostrato in fig.~\ref{fig:proc_exec_relat}), sono tutte un front-end a \funcd{execve}. Il prototipo di quest'ultima è: \begin{prototype}{unistd.h} {int execve(const char *filename, char *const argv[], char *const envp[])} @@ -1114,7 +1117,7 @@ linea di comando e l'ambiente ricevuti dal nuovo processo. \end{functions} Per capire meglio le differenze fra le funzioni della famiglia si può fare -riferimento allo specchietto riportato in \tabref{tab:proc_exec_scheme}. La +riferimento allo specchietto riportato in tab.~\ref{tab:proc_exec_scheme}. La prima differenza riguarda le modalità di passaggio dei parametri che poi andranno a costituire gli argomenti a linea di comando (cioè i valori di \param{argv} e \param{argc} visti dalla funzione \func{main} del programma @@ -1189,7 +1192,7 @@ La terza differenza Con lo mnemonico \code{e} vengono indicate quelle funzioni che necessitano di un vettore di parametri \var{envp[]} analogo a quello usato per gli argomenti a riga di comando (terminato quindi da un \val{NULL}), le altre usano il -valore della variabile \var{environ} (vedi \secref{sec:proc_environ}) del +valore della variabile \var{environ} (vedi sez.~\ref{sec:proc_environ}) del processo di partenza per costruire l'ambiente. Oltre a mantenere lo stesso \acr{pid}, il nuovo programma fatto partire da @@ -1199,21 +1202,21 @@ la lista completa \item il \textit{process id} (\acr{pid}) ed il \textit{parent process id} (\acr{ppid}). \item l'\textsl{user-ID reale}, il \textit{group-ID reale} ed i - \textsl{group-ID supplementari} (vedi \secref{sec:proc_access_id}). + \textsl{group-ID supplementari} (vedi sez.~\ref{sec:proc_access_id}). \item il \textit{session id} (\acr{sid}) ed il \textit{process group-ID} - (\acr{pgid}), vedi \secref{sec:sess_proc_group}. -\item il terminale di controllo (vedi \secref{sec:sess_ctrl_term}). -\item il tempo restante ad un allarme (vedi \secref{sec:sig_alarm_abort}). + (\acr{pgid}), vedi sez.~\ref{sec:sess_proc_group}. +\item il terminale di controllo (vedi sez.~\ref{sec:sess_ctrl_term}). +\item il tempo restante ad un allarme (vedi sez.~\ref{sec:sig_alarm_abort}). \item la directory radice e la directory di lavoro corrente (vedi - \secref{sec:file_work_dir}). + sez.~\ref{sec:file_work_dir}). \item la maschera di creazione dei file (\var{umask}, vedi - \secref{sec:file_umask}) ed i \textit{lock} sui file (vedi - \secref{sec:file_locking}). + sez.~\ref{sec:file_umask}) ed i \textit{lock} sui file (vedi + sez.~\ref{sec:file_locking}). \item i segnali sospesi (\textit{pending}) e la maschera dei segnali (si veda - \secref{sec:sig_sigmask}). -\item i limiti sulle risorse (vedi \secref{sec:sys_resource_limit}). + sez.~\ref{sec:sig_sigmask}). +\item i limiti sulle risorse (vedi sez.~\ref{sec:sys_resource_limit}). \item i valori delle variabili \var{tms\_utime}, \var{tms\_stime}, - \var{tms\_cutime}, \var{tms\_ustime} (vedi \secref{sec:sys_cpu_times}). + \var{tms\_cutime}, \var{tms\_ustime} (vedi sez.~\ref{sec:sys_cpu_times}). \end{itemize*} Inoltre i segnali che sono stati impostati per essere ignorati nel processo @@ -1221,11 +1224,11 @@ chiamante mantengono la stessa impostazione pure nel nuovo programma, tutti gli altri segnali vengono impostati alla loro azione predefinita. Un caso speciale è il segnale \const{SIGCHLD} che, quando impostato a \const{SIG\_IGN}, può anche non essere reimpostato a \const{SIG\_DFL} (si veda -\secref{sec:sig_gen_beha}). +sez.~\ref{sec:sig_gen_beha}). La gestione dei file aperti dipende dal valore che ha il flag di \textit{close-on-exec}\index{close-on-exec} (vedi anche -\secref{sec:file_fcntl}) per ciascun file descriptor. I file per cui è +sez.~\ref{sec:file_fcntl}) per ciascun file descriptor. I file per cui è impostato vengono chiusi, tutti gli altri file restano aperti. Questo significa che il comportamento predefinito è che i file restano aperti attraverso una \func{exec}, a meno di una chiamata esplicita a \func{fcntl} @@ -1233,18 +1236,18 @@ che imposti il suddetto flag. 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 +\func{opendir} (vedi sez.~\ref{sec:file_dir_read}) che effettua da sola l'impostazione del flag di \textit{close-on-exec}\index{close-on-exec} sulle directory che apre, in maniera trasparente all'utente. Abbiamo detto che l'\textsl{user-ID reale} ed il \textsl{group-ID reale} restano gli stessi all'esecuzione di \func{exec}; lo stesso vale per l'\textsl{user-ID effettivo} ed il \textsl{group-ID effettivo} (il significato -di questi identificatori è trattato in \secref{sec:proc_access_id}), tranne +di questi identificatori è trattato in sez.~\ref{sec:proc_access_id}), tranne quando il file che si va ad eseguire abbia o il \acr{suid} bit o lo \acr{sgid} bit impostato, in questo caso l'\textsl{user-ID effettivo} ed il \textsl{group-ID effettivo} vengono impostati rispettivamente all'utente o al -gruppo cui il file appartiene (per i dettagli vedi \secref{sec:proc_perms}). +gruppo cui il file appartiene (per i dettagli vedi sez.~\ref{sec:proc_perms}). Se il file da eseguire è in formato \emph{a.out} e necessita di librerie condivise, viene lanciato il \textit{linker} dinamico \cmd{ld.so} prima del @@ -1281,7 +1284,7 @@ problematiche connesse ad una gestione accorta dei privilegi. \subsection{Gli identificatori del controllo di accesso} \label{sec:proc_access_id} -Come accennato in \secref{sec:intro_multiuser} il modello base\footnote{in +Come accennato in sez.~\ref{sec:intro_multiuser} il modello base\footnote{in realtà già esistono estensioni di questo modello base, che lo rendono più flessibile e controllabile, come le \textit{capabilities}, le ACL per i file o il \textit{Mandatory Access Control} di SELinux; inoltre basandosi sul @@ -1302,7 +1305,7 @@ Abbiamo gi identificatori univoci, lo user-ID ed il group-ID; questi servono al kernel per identificare uno specifico utente o un gruppo di utenti, per poi poter controllare che essi siano autorizzati a compiere le operazioni richieste. Ad -esempio in \secref{sec:file_access_control} vedremo come ad ogni file vengano +esempio in sez.~\ref{sec:file_access_control} vedremo come ad ogni file vengano associati un utente ed un gruppo (i suoi \textsl{proprietari}, indicati appunto tramite un \acr{uid} ed un \acr{gid}) che vengono controllati dal kernel nella gestione dei permessi di accesso. @@ -1320,7 +1323,8 @@ prevedono che i processi abbiano almeno due gruppi di identificatori, chiamati rispettivamente \textit{real} ed \textit{effective} (cioè \textsl{reali} ed \textsl{effettivi}). Nel caso di Linux si aggiungono poi altri due gruppi, il \textit{saved} (\textsl{salvati}) ed il \textit{filesystem} (\textsl{di - filesystem}), secondo la situazione illustrata in \tabref{tab:proc_uid_gid}. + filesystem}), secondo la situazione illustrata in +tab.~\ref{tab:proc_uid_gid}. \begin{table}[htb] \footnotesize @@ -1364,7 +1368,7 @@ Al primo gruppo appartengono l'\textsl{user-ID reale} ed il \textsl{group-ID reale}: questi vengono impostati al login ai valori corrispondenti all'utente con cui si accede al sistema (e relativo gruppo principale). Servono per l'identificazione dell'utente e normalmente non vengono mai -cambiati. In realtà vedremo (in \secref{sec:proc_setuid}) che è possibile +cambiati. In realtà vedremo (in sez.~\ref{sec:proc_setuid}) che è possibile modificarli, ma solo ad un processo che abbia i privilegi di amministratore; questa possibilità è usata proprio dal programma \cmd{login} che, una volta completata la procedura di autenticazione, lancia una shell per la quale @@ -1376,13 +1380,13 @@ Al secondo gruppo appartengono lo \textsl{user-ID effettivo} ed il supplementari} 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}). +sez.~\ref{sec:file_perm_overview}). Questi identificatori normalmente sono identici ai corrispondenti del gruppo \textit{real} tranne nel caso in cui, come accennato in -\secref{sec:proc_exec}, il programma che si è posto in esecuzione abbia i bit +sez.~\ref{sec:proc_exec}, il programma che si è posto in esecuzione abbia i bit \acr{suid} o \acr{sgid} impostati (il significato di questi bit è affrontato -in dettaglio in \secref{sec:file_suid_sgid}). In questo caso essi saranno +in dettaglio in sez.~\ref{sec:file_suid_sgid}). In questo caso essi saranno impostati all'utente e al gruppo proprietari del file. Questo consente, per programmi in cui ci sia necessità, di dare a qualunque utente normale privilegi o permessi di un altro (o dell'amministratore). @@ -1435,10 +1439,10 @@ e gruppo effettivi all'inizio dell'esecuzione di un nuovo programma. L'\textsl{user-ID di filesystem} e il \textsl{group-ID di filesystem} sono un'estensione introdotta in Linux per rendere più sicuro l'uso di NFS -(torneremo sull'argomento in \secref{sec:proc_setfsuid}). Essi sono una +(torneremo sull'argomento in sez.~\ref{sec:proc_setfsuid}). Essi sono una replica dei corrispondenti identificatori del gruppo \textit{effective}, ai quali si sostituiscono per tutte le operazioni di verifica dei permessi -relativi ai file (trattate in \secref{sec:file_perm_overview}). Ogni +relativi ai file (trattate in sez.~\ref{sec:file_perm_overview}). Ogni cambiamento effettuato sugli identificatori effettivi viene automaticamente riportato su di essi, per cui in condizioni normali si può tranquillamente ignorarne l'esistenza, in quanto saranno del tutto equivalenti ai precedenti. @@ -1449,7 +1453,7 @@ ignorarne l'esistenza, in quanto saranno del tutto equivalenti ai precedenti. Le due funzioni che vengono usate per cambiare identità (cioè utente e gruppo di appartenenza) ad un processo sono rispettivamente \funcd{setuid} e -\funcd{setgid}; come accennato in \secref{sec:proc_access_id} in Linux esse +\funcd{setgid}; come accennato in sez.~\ref{sec:proc_access_id} in Linux esse seguono la semantica POSIX che prevede l'esistenza dell'\textit{user-ID salvato} e del \textit{group-ID salvato}; i loro prototipi sono: \begin{functions} @@ -1482,8 +1486,8 @@ all'\textsl{user-ID salvato}. Negli altri casi viene segnalato un errore (con Come accennato l'uso principale di queste funzioni è quello di poter consentire ad un programma con i bit \acr{suid} o \acr{sgid} impostati (vedi -\secref{sec:file_suid_sgid}) di riportare l'\textsl{user-ID effettivo} a quello -dell'utente che ha lanciato il programma, effettuare il lavoro che non +sez.~\ref{sec:file_suid_sgid}) di riportare l'\textsl{user-ID effettivo} 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 l'uso di queste funzioni prendiamo quello con cui @@ -1540,7 +1544,7 @@ processo, rendendo impossibile riguadagnare i privilegi di amministratore. Questo comportamento è corretto per l'uso che ne fa \cmd{login} una volta che crea una nuova shell per l'utente; ma quando si vuole cambiare soltanto l'\textsl{user-ID effettivo} del processo per cedere i privilegi occorre -ricorrere ad altre funzioni (si veda ad esempio \secref{sec:proc_seteuid}). +ricorrere ad altre funzioni (si veda ad esempio sez.~\ref{sec:proc_seteuid}). \subsection{Le funzioni \func{setreuid} e \func{setregid}} @@ -1568,12 +1572,12 @@ specificati da \param{rgid} e \param{egid}. \end{functions} La due funzioni sono analoghe ed il loro comportamento è identico; quanto -detto per la prima prima riguardo l'user-ID, si applica immediatamente alla -seconda per il group-ID. I processi non privilegiati possono impostare solo i -valori del loro user-ID effettivo o reale; valori diversi comportano il -fallimento della chiamata; l'amministratore invece può specificare un valore -qualunque. Specificando un argomento di valore -1 l'identificatore -corrispondente verrà lasciato inalterato. +detto per la prima riguardo l'user-ID, si applica immediatamente alla seconda +per il group-ID. I processi non privilegiati possono impostare solo i valori +del loro user-ID effettivo o reale; valori diversi comportano il fallimento +della chiamata; l'amministratore invece può specificare un valore qualunque. +Specificando un argomento di valore -1 l'identificatore corrispondente verrà +lasciato inalterato. Con queste funzioni si possono scambiare fra loro gli user-ID reale e effettivo, e pertanto è possibile implementare un comportamento simile a @@ -1691,7 +1695,7 @@ gli identificatori del gruppo \textit{saved}. Queste funzioni servono per impostare gli identificatori del gruppo \textit{filesystem} che sono usati da Linux per il controllo dell'accesso ai -file. Come già accennato in \secref{sec:proc_access_id} Linux definisce +file. Come già accennato in sez.~\ref{sec:proc_access_id} Linux definisce questo ulteriore gruppo di identificatori, che in circostanze normali sono assolutamente equivalenti a quelli del gruppo \textit{effective}, dato che ogni cambiamento di questi ultimi viene immediatamente riportato su di essi. @@ -1738,7 +1742,7 @@ Le ultime funzioni che esamineremo sono quelle che permettono di operare sui gruppi supplementari cui un utente può appartenere. Ogni processo può avere almeno \const{NGROUPS\_MAX} gruppi supplementari\footnote{il numero massimo di gruppi secondari può essere ottenuto con \func{sysconf} (vedi - \secref{sec:sys_sysconf}), leggendo il parametro + sez.~\ref{sec:sys_sysconf}), leggendo il parametro \texttt{\_SC\_NGROUPS\_MAX}.} in aggiunta al gruppo primario; questi vengono ereditati dal processo padre e possono essere cambiati con queste funzioni. @@ -1784,8 +1788,8 @@ ottenere tutti i gruppi a cui appartiene un certo utente; il suo prototipo La funzione legge i gruppi supplementari dell'utente specificato da \param{user}, eseguendo una scansione del database dei gruppi (si veda -\secref{sec:sys_user_group}). Ritorna poi in \param{groups} la lista di quelli -a cui l'utente appartiene. Si noti che \param{ngroups} è passato come +sez.~\ref{sec:sys_user_group}). Ritorna poi 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, passando indietro il numero dei gruppi trovati. @@ -1814,7 +1818,7 @@ La funzione imposta i gruppi supplementari del processo corrente ai valori specificati nel vettore passato con l'argomento \param{list}, di dimensioni date dall'argomento \param{size}. Il numero massimo di gruppi supplementari è un parametro di sistema, che può essere ricavato con le modalità spiegate in -\secref{sec:sys_characteristics}. +sez.~\ref{sec:sys_characteristics}. Se invece si vogliono impostare i gruppi supplementari del processo a quelli di un utente specifico, si può usare \funcd{initgroups} il cui prototipo è: @@ -1880,7 +1884,7 @@ cosiddetto \textit{prehemptive multitasking}: questo significa che al contrario di altri sistemi (che usano invece il cosiddetto \textit{cooperative multitasking}) non sono i singoli processi, ma il kernel stesso a decidere quando la CPU deve essere passata ad un altro processo. Come accennato in -\secref{sec:proc_hierarchy} questa scelta viene eseguita da una sezione +sez.~\ref{sec:proc_hierarchy} questa scelta viene eseguita da una sezione apposita del kernel, lo \textit{scheduler}\index{scheduler}, il cui scopo è quello di distribuire al meglio il tempo di CPU fra i vari processi. @@ -1905,7 +1909,7 @@ kernel provvedere a mettere in esecuzione un altro processo. Tutte queste possibilità sono caratterizzate da un diverso \textsl{stato} del processo, in Linux un processo può trovarsi in uno degli stati riportati in -\tabref{tab:proc_proc_states}; ma soltanto i processi che sono nello stato +tab.~\ref{tab:proc_proc_states}; ma soltanto i processi che sono nello stato \textit{runnable} concorrono per l'esecuzione. Questo vuol dire che, qualunque sia la sua priorità, un processo non potrà mai essere messo in esecuzione fintanto che esso si trova in uno qualunque degli altri stati. @@ -1949,12 +1953,12 @@ non abbia risultati significativi in termini di prestazioni. Il meccanismo tradizionale di scheduling di Unix (che tratteremo in -\secref{sec:proc_sched_stand}) è sempre stato basato su delle \textsl{priorità - dinamiche}, in modo da assicurare che tutti i processi, anche i meno -importanti, possano ricevere un po' di tempo di CPU. In sostanza quando un -processo ottiene la CPU la sua priorità viene diminuita. In questo modo alla -fine, anche un processo con priorità iniziale molto bassa, finisce per avere -una priorità sufficiente per essere eseguito. +sez.~\ref{sec:proc_sched_stand}) è sempre stato basato su delle +\textsl{priorità dinamiche}, in modo da assicurare che tutti i processi, anche +i meno importanti, possano ricevere un po' di tempo di CPU. In sostanza quando +un processo ottiene la CPU la sua priorità viene diminuita. In questo modo +alla fine, anche un processo con priorità iniziale molto bassa, finisce per +avere una priorità sufficiente per essere eseguito. Lo standard POSIX.1b però ha introdotto il concetto di \textsl{priorità assoluta}, (chiamata anche \textsl{priorità statica}, in contrapposizione @@ -1975,7 +1979,7 @@ Ovviamente questo avviene solo per i processi che sono pronti per essere eseguiti (cioè nello stato \textit{runnable}). La priorità assoluta viene in genere indicata con un numero intero, ed un valore più alto comporta una priorità maggiore. Su questa politica di scheduling torneremo in -\secref{sec:proc_real_time}. +sez.~\ref{sec:proc_real_time}. In generale quello che succede in tutti gli Unix moderni è che ai processi normali viene sempre data una priorità assoluta pari a zero, e la decisione di @@ -2078,9 +2082,9 @@ librerie, ma La funzione permette, a seconda del valore di \param{which}, di leggere la priorità di un processo, di un gruppo di processi (vedi -\secref{sec:sess_proc_group}) o di un utente, specificando un corrispondente -valore per \param{who} secondo la legenda di \tabref{tab:proc_getpriority}; un -valore nullo di quest'ultimo indica il processo, il gruppo di processi o +sez.~\ref{sec:sess_proc_group}) o di un utente, specificando un corrispondente +valore per \param{who} secondo la legenda di tab.~\ref{tab:proc_getpriority}; +un valore nullo di quest'ultimo indica il processo, il gruppo di processi o l'utente correnti. \begin{table}[htb] @@ -2141,9 +2145,9 @@ Ultrix, *BSD) la corrispondenza pu \subsection{Il meccanismo di \textit{scheduling real-time}} \label{sec:proc_real_time} -Come spiegato in \secref{sec:proc_sched} lo standard POSIX.1b ha introdotto le -priorità assolute per permettere la gestione di processi real-time. In realtà -nel caso di Linux non si tratta di un vero hard real-time, in quanto in +Come spiegato in sez.~\ref{sec:proc_sched} lo standard POSIX.1b ha introdotto +le priorità assolute per permettere la gestione di processi real-time. In +realtà nel caso di Linux non si tratta di un vero hard real-time, in quanto in presenza di eventuali interrupt il kernel interrompe l'esecuzione di un processo qualsiasi sia la sua priorità,\footnote{questo a meno che non si siano installate le patch di RTLinux, RTAI o Adeos, con i quali è possibile @@ -2154,7 +2158,7 @@ processo qualsiasi sia la sua priorit più elevata di un \textit{interrupt handler}.} mentre con l'incorrere in un page fault\index{page fault} si possono avere ritardi non previsti. Se l'ultimo problema può essere aggirato attraverso l'uso delle funzioni di -controllo della memoria virtuale (vedi \secref{sec:proc_mem_lock}), il primo +controllo della memoria virtuale (vedi sez.~\ref{sec:proc_mem_lock}), il primo non è superabile e può comportare ritardi non prevedibili riguardo ai tempi di esecuzione di qualunque processo. @@ -2205,7 +2209,7 @@ prototipo La funzione esegue l'impostazione per il processo specificato dall'argomento \param{pid}; un valore nullo esegue l'impostazione per il processo corrente. La politica di scheduling è specificata dall'argomento \param{policy} i cui -possibili valori sono riportati in \tabref{tab:proc_sched_policy}; un valore +possibili valori sono riportati in tab.~\ref{tab:proc_sched_policy}; un valore negativo per \param{policy} mantiene la politica di scheduling corrente. Solo un processo con i privilegi di amministratore può impostare priorità assolute diverse da zero o politiche \const{SCHED\_FIFO} e \const{SCHED\_RR}. @@ -2230,8 +2234,8 @@ assolute diverse da zero o politiche \const{SCHED\_FIFO} e \const{SCHED\_RR}. \end{table} Il valore della priorità è passato attraverso la struttura -\struct{sched\_param} (riportata in \figref{fig:sig_sched_param}), il cui solo -campo attualmente definito è \var{sched\_priority}, che nel caso delle +\struct{sched\_param} (riportata in fig.~\ref{fig:sig_sched_param}), il cui +solo campo attualmente definito è \var{sched\_priority}, che nel caso delle priorità assolute deve essere specificato nell'intervallo fra un valore massimo ed uno minimo, che nel caso sono rispettivamente 1 e 99 (il valore zero è legale, ma indica i processi normali). @@ -2299,7 +2303,7 @@ La priorit \end{prototype} La funzione restituisce il valore (secondo quanto elencato in -\tabref{tab:proc_sched_policy}) della politica di scheduling per il processo +tab.~\ref{tab:proc_sched_policy}) della politica di scheduling per il processo specificato; se \param{pid} è nullo viene restituito quello del processo chiamante. @@ -2348,7 +2352,7 @@ il suo prototipo La funzione restituisce il valore dell'intervallo di tempo usato per la politica \textit{round robin} in una struttura \struct{timespec}, (la cui -definizione si può trovare in \figref{fig:sys_timeval_struct}). +definizione si può trovare in fig.~\ref{fig:sys_timeval_struct}). Come accennato ogni processo che usa lo scheduling real-time può rilasciare @@ -2400,14 +2404,14 @@ essere interrotto in qualunque momento dal kernel che mette in esecuzione un altro processo o dalla ricezione di un segnale; occorre pertanto essere accorti nei confronti delle possibili \textit{race condition}\index{race condition} (vedi -\secref{sec:proc_race_cond}) derivanti da operazioni interrotte in una fase in -cui non erano ancora state completate. +sez.~\ref{sec:proc_race_cond}) derivanti da operazioni interrotte in una fase +in cui non erano ancora state completate. Nel caso dell'interazione fra processi la situazione è molto più semplice, ed occorre preoccuparsi della atomicità delle operazioni solo quando si ha a che fare con meccanismi di intercomunicazione (che esamineremo in dettaglio in -\capref{cha:IPC}) o nelle operazioni con i file (vedremo alcuni esempi in -\secref{sec:file_atomic}). In questi casi in genere l'uso delle appropriate +cap.~\ref{cha:IPC}) o nelle operazioni con i file (vedremo alcuni esempi in +sez.~\ref{sec:file_atomic}). In questi casi in genere l'uso delle appropriate funzioni di libreria per compiere le operazioni necessarie è garanzia sufficiente di atomicità in quanto le system call con cui esse sono realizzate non possono essere interrotte (o subire interferenze pericolose) da altri @@ -2419,7 +2423,7 @@ qualunque momento, e le operazioni di un eventuale \textit{signal handler} 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:sig_control}). +sez.~\ref{sec:sig_control}). In questo caso il sistema provvede un tipo di dato, il \type{sig\_atomic\_t}, il cui accesso è assicurato essere atomico. In pratica comunque si può @@ -2463,7 +2467,7 @@ di eseguire atomicamente le operazioni necessarie, occorre che quelle parti di codice in cui si compiono le operazioni sulle risorse condivise (le cosiddette \textsl{sezioni critiche}\index{sezioni critiche}) del programma, siano opportunamente protette da meccanismi di sincronizzazione (torneremo su queste -problematiche di questo tipo in \capref{cha:IPC}). +problematiche di questo tipo in cap.~\ref{cha:IPC}). Un caso particolare di \textit{race condition}\index{race condition} sono poi i cosiddetti \textit{deadlock}\index{deadlock}, particolarmente gravi in @@ -2484,7 +2488,7 @@ accorgessimo proprio fra il controllo e la messa in attesa, quest'ultima diventerà perpetua (da cui il nome di \textit{deadlock}\index{deadlock}). In tutti questi casi è di fondamentale importanza il concetto di atomicità -visto in \secref{sec:proc_atom_oper}; questi problemi infatti possono essere +visto in sez.~\ref{sec:proc_atom_oper}; questi problemi infatti possono essere risolti soltanto assicurandosi, quando essa sia richiesta, che sia possibile eseguire in maniera atomica le operazioni necessarie.