From: Simone Piccardi Date: Fri, 15 Feb 2002 19:02:04 +0000 (+0000) Subject: Correzioni varie, prima parte. X-Git-Url: https://gapil.gnulinux.it/gitweb/?a=commitdiff_plain;h=30cb49b067deded2d7f8c8331d466c3a937c4288;p=gapil.git Correzioni varie, prima parte. --- diff --git a/pref.tex b/pref.tex index 5e5776e..60410b1 100644 --- a/pref.tex +++ b/pref.tex @@ -2,10 +2,11 @@ \label{cha:preface} Nelle motivazioni in cui si introduce la GNU Free Documentation License (FDL) -(reperibili su http://www.gnu.org/philosophy/free-doc.html) si dà una grande -rilevanza all'importanza di disporre di buoni manuali, in quanto la fruibilità -e la possibilità di usare appieno il software libero, vengono notevolmente -ridotte senza la presenza di un valido manuale che sia altrettanto liberamente +(reperibili su \href{http://www.gnu.org/philosophy/free-doc.html} +{http://www.gnu.org/philosophy/free-doc.html}) si dà una grande rilevanza +all'importanza di disporre di buoni manuali, in quanto la fruibilità e la +possibilità di usare appieno il software libero vengono notevolmente ridotte +senza la presenza di un valido manuale che sia altrettanto liberamente disponibile. E, come per il software libero, è anche in questo caso è di fondamentale @@ -28,11 +29,12 @@ ampliati, o anche ridotti per usi specifici, nello stesso modo in cui si fa per il software libero. Questo progetto mira alla stesura di un libro il più completo e chiaro -possibile sulla programmazione in GNU/Linux (che da qui in avanti spesso -chiameremo semplicemente Linux per brevità). Ovviamente essendo i concetti in -gran parte gli stessi, esso dovrebbe restare valido anche per la -programmazione in ambito Unix generico, pur restando l'intenzione di -approfondire in maniera specifica le caratteristiche peculiari di GNU/Linux. +possibile sulla programmazione in GNU/Linux (che per brevità chiameremo spesso +Linux, anche nei casi in cui sarebbe comunque più appropriato il nome +compelto). Ovviamente essendo i concetti in gran parte gli stessi, esso +dovrebbe restare valido anche per la programmazione in ambito Unix generico, +pur restando l'intenzione di approfondire in maniera specifica le +caratteristiche peculiari di GNU/Linux. L'idea è quella di riuscire a ottenere alla fine un testo utilizzabile per apprendere la programmazione, sotto GNU/Linux della stessa qualità dei testi @@ -46,9 +48,9 @@ particolari dell'argomento in esame (in particolare lo \textit{GNU C Library Reference Manual} non brilla certo per chiarezza espositiva). Per questo motivo si è cercato di fare tesoro di quanto appreso dai testi di -R. Stevens (in particolare \textit{Advanced Programming in the Unix - Environment} e \textit{Unix Network Programming}) per rendere la trattazione -dei vari argomenti in una sequenza logica il più esplicativa possibile. +R. Stevens (in particolare \cite{APUE} e \cite{UNP1}) per rendere la +trattazione dei vari argomenti in una sequenza logica il più esplicativa +possibile. Il progetto prevede il rilascio del testo sotto licenza FDL, ed una modalità di realizzazione aperta che permetta di accogliere i contributi di chiunque diff --git a/prochand.tex b/prochand.tex index 70d7eb1..173c0be 100644 --- a/prochand.tex +++ b/prochand.tex @@ -1,17 +1,17 @@ \chapter{La gestione dei processi} \label{cha:process_handling} -Come accennato nell'introduzione in un sistema Unix ogni attività del sistema -viene svolta tramite i processi. In sostanza i processi costituiscono l'unità -base per l'allocazione e l'uso delle risorse del sistema. +Come accennato nell'introduzione in un sistema Unix tutte le operazioni +vengono svolte tramite opportuni processi. In sostanza questi ultimi vengono +a costituire l'unità base per l'allocazione e l'uso delle risorse del sistema. Nel precedente capitolo abbiamo esaminato il funzionamento di un processo come unità a se stante, in questo esamineremo il funzionamento dei processi all'interno del sistema. Saranno cioè affrontati i dettagli della creazione e -della distruzione dei processi, della gestione dei loro attributi e privilegi, -e di tutte le funzioni a questo connesse. Infine nella sezione finale -affronteremo alcune problematiche generiche della programmazione in ambiente -multitasking. +della terminazione dei processi, della gestione dei loro attributi e +privilegi, e di tutte le funzioni a questo connesse. Infine nella sezione +finale introdurremo alcune problematiche generiche della programmazione in +ambiente multitasking. @@ -163,8 +163,7 @@ 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 una informazione -abbastanza limitata (lo stato di terminazione) sulle cause della terminazione -del processo figlio. +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 @@ -216,9 +215,9 @@ intero con segno (nel caso di Linux e delle \acr{glibc} il tipo usato 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. +riparte dal numero più basso disponibile\footnote{FIXME: verificare, non sono + sicuro}. Per questo motivo processo il processo di avvio (\cmd{init}) ha +sempre il \acr{pid} uguale a uno. Tutti i processi inoltre memorizzano anche il \acr{pid} del genitore da cui sono stati creati, questo viene chiamato in genere \acr{ppid} (da @@ -236,12 +235,12 @@ ottenuti da programma usando le funzioni: \noindent esempi dell'uso di queste funzioni sono riportati in \figref{fig:proc_fork_code}, nel programma di esempio \file{ForkTest.c}. -Il fatto che il \acr{pid} sia un numero univoco per il sistema lo rende il -candidato ideale per generare ulteriori 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. +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. Tutti i processi figli dello stesso processo padre sono detti \textit{sibling}, questa è una delle relazioni usate nel \textsl{controllo di @@ -296,7 +295,7 @@ padre, ma la memoria 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 della creazione di - un nuovo processo}, pertanto padre e figlio vedono variabili diverse. + un nuovo processo.}, 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 \func{fork} è il \acr{pid} del processo figlio, mentre @@ -369,11 +368,11 @@ qualcos'altro non sta andando per il verso giusto) o si sul numero totale di processi permessi all'utente (vedi \secref{sec:sys_xxx}). L'uso di \func{fork} avviene secondo due modalità principali; la prima è -quella in cui all'interno di un programma si creano processi figli per -affidargli l'esecuzione di una certa sezione di codice, mentre il processo -padre ne esegue un'altra. È il caso tipico dei server di rete in cui il padre -riceve ed accetta le richieste da parte dei client, per ciascuna delle quali -pone in esecuzione un figlio che è incaricato di fornire il servizio. +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 server di rete in cui il padre riceve +ed accetta le richieste da parte dei client, per ciascuna delle quali pone in +esecuzione un figlio che è incaricato di fornire 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 @@ -402,12 +401,12 @@ descrizione delle opzioni); 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 +(\texttt{\small 24--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 + 25--29}); ciascun figlio (\texttt{\small 31--34}) si limita a stampare il suo numero di successione, eventualmente attendere il numero di secondi specificato e scrivere un messaggio prima di uscire. Il processo padre invece -(\texttt{\small 29--31}) stampa un messaggio di creazione, eventualmente +(\texttt{\small 36--38}) stampa un messaggio di creazione, eventualmente attende il numero di secondi specificato, e procede nell'esecuzione del ciclo; alla conclusione del ciclo, prima di uscire, può essere specificato un altro periodo di attesa. @@ -458,14 +457,14 @@ figli venisse messo in esecuzione. Pertanto non si può fare nessuna assunzione sulla sequenza di esecuzione delle istruzioni del codice fra padre e figli, nè sull'ordine in cui questi potranno -essere messi in esecuzione, e se è necessaria una qualche forma di precedenza +essere messi in esecuzione. Se è necessaria una qualche forma di precedenza occorrerà provvedere ad espliciti meccanismi di sincronizzazione, pena il rischio di incorrere nelle cosiddette \textit{race condition} \index{race condition} (vedi \secref{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 -figli (come l'incremento di \var{i} in \texttt{\small 33}) sono visibili solo +figli (come l'incremento di \var{i} in \texttt{\small 31}) sono visibili solo a loro, e non hanno alcun effetto sul valore che le stesse variabili hanno nel processo padre (ed in eventuali altri processi figli che eseguano lo stesso codice). @@ -509,30 +508,29 @@ Il comportamento delle varie funzioni di interfaccia con i file in gran dettaglio in \capref{cha:file_unix_interface} e in \secref{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 (di veda \secref{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). +questa bufferizzazione (trattata in dettaglio in \secref{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). Nel primo esempio allora avevamo che ad ogni chiamata a \func{printf} il buffer veniva scaricato, e le singole righe erano stampate a video subito dopo l'esecuzione della \func{printf}. Ma con la redirezione su file la scrittura -non avviene più alla fine di ogni riga e l'output resta nel buffer. Per questo -motivo, dato che ogni figlio riceve una copia della memoria del padre, esso -riceverà anche quanto c'è nel buffer delle funzioni di I/O, comprese le linee -scritte dal padre fino allora. Così quando all'uscita del figlio il buffer -viene scritto su disco, troveremo nel file anche tutto quello che il processo -padre aveva scritto prima della sua creazione. E solo alla fine del file, -dato che in questo caso il padre esce per ultimo, troveremo anche l'output del -padre. - -Ma l'esempio ci mostra un'altro aspetto fondamentale dell'interazione con i -file, che era 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 in unix è trattato -in dettaglio in \secref{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. +non avviene più alla fine di ogni riga e l'output resta nel buffer. Dato che +ogni figlio riceve una copia della memoria del padre, esso riceverà anche +quanto c'è nel buffer delle funzioni di I/O, comprese le linee scritte dal +padre fino allora. Così quando il buffer viene scritto su disco all'uscita del +figlio, troveremo nel file anche tutto quello che il processo padre aveva +scritto prima della sua creazione. E alla fine del file (dato che in questo +caso il padre esce per ultimo) troveremo anche l'output completo del padre. + +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 +le variabili, la posizione corrente sul file è condivisa fra il padre e tutti +i processi figli. Quello che succede è che quando lo standard output del padre viene rediretto, lo stesso avviene anche per tutti i figli; la funzione \func{fork} infatti ha @@ -628,7 +626,7 @@ ritornare o uscire con \func{exit} ma usare esplicitamente \func{\_exit}. Questa funzione è un rimasuglio dei vecchi tempi in cui eseguire una \func{fork} comportava anche la copia completa del segmento dati del processo padre, che costituiva un inutile appesantimento in tutti quei casi in cui la -\func{fork} veniva fatto solo per poi eseguire una \func{exec}. La funzione +\func{fork} veniva fatta solo per poi eseguire una \func{exec}. La funzione venne introdotta in BSD per migliorare le prestazioni. Dato che Linux supporta il \textit{copy on write} la perdita di prestazioni è @@ -641,19 +639,18 @@ trattarla ulteriormente. \label{sec:proc_termination} In \secref{sec:proc_conclusion} abbiamo già affrontato le modalità con cui -chiudere un programma, ma dal punto di vista del programma stesso; avendo a -che fare con un sistema multitasking occorre adesso affrontare l'argomento dal -punto di vista generale di come il sistema gestisce la conclusione dei -processi. +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 già visto in \secref{sec:proc_conclusion} le tre modalità con cui un +Abbiamo visto in \secref{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 chiamata ad \func{\_exit} (che passa direttamente alle operazioni di terminazione del processo da parte del kernel). -Ma oltre alla conclusione normale abbiamo accennato che esistono anche delle +Ma abbiamo accennato che oltre alla conclusione normale esistono anche delle modalità di conclusione anomala; queste sono in sostanza due: il programma può chiamare la funzione \func{abort} per invocare una chiusura anomala, o essere terminato da un segnale. In realtà anche la prima modalità si riconduce alla @@ -679,11 +676,12 @@ eseguite alla chiusura di un processo inviati in successione i segnali \macro{SIGHUP} e \macro{SIGCONT} (vedi \secref{sec:sess_xxx}). \end{itemize*} -ma al di la di queste operazioni è necessario poter disporre di un meccanismo -ulteriore che consenta di sapere come questa terminazione è avvenuta; dato che -in 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. + +Oltre queste operazioni è però necessario poter disporre di un meccanismo +ulteriore che consenta di sapere come la terminazione è avvenuta: dato che in +un sistema unix-like tutto viene gestito attraverso i processi il meccanismo +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 @@ -707,15 +705,15 @@ che sia cos terminato (si potrebbe avere cioè quello che si chiama un processo \textsl{orfano}). -Questa complicazione viene superata facendo in modo che il processo figlio -venga \textsl{adottato} da \cmd{init}: come già accennato quando un processo +Questa complicazione viene superata facendo in modo che il processo orfano +venga \textsl{adottato} da \cmd{init}. Come già accennato quando un processo termina il kernel controlla se è il padre di altri processi in esecuzione: in caso positivo allora il \acr{ppid} di tutti questi processi viene sostituito con il \acr{pid} di \cmd{init} (e cioè con 1); in questo modo ogni processo -avrà sempre un padre (nel caso \textsl{adottivo}) cui riportare il suo stato -di terminazione. Come verifica di questo comportamento possiamo eseguire il -comando \cmd{forktest} imponendo a ciascun processo figlio due -secondi di attesa prima di uscire, il risultato è: +avrà sempre un padre (nel caso possiamo parlare di un padre \textsl{adottivo}) +cui riportare il suo stato di terminazione. Come verifica di questo +comportamento possiamo eseguire il nostro programma \cmd{forktest} imponendo a +ciascun processo figlio due secondi di attesa prima di uscire, il risultato è: \footnotesize \begin{verbatim} @@ -797,27 +795,27 @@ appunto quella di chiamare la funzione \func{wait} per i processi cui fa da padre, completandone la terminazione. Questo è quanto avviene anche quando, come nel caso del precedente esempio con \cmd{forktest}, il padre termina con dei figli in stato di zombie: alla sua terminazione infatti tutti i suoi figli -vengono ereditati (compresi gli zombie) verranno adottati da \cmd{init}, il -quale provvederà a completarne la terminazione. +(compresi gli zombie) verranno adottati da \cmd{init}, il quale provvederà a +completarne la terminazione. Si tenga presente infine che siccome gli zombie sono processi già usciti, non -c'è modo di eliminarli con il comando \cmd{kill}; l'unica possibilità è quella -di terminare il processo che li ha generati, in modo che \cmd{init} possa -adottarli e provvedere a concludere la terminazione. +c'è modo di eliminarli con il comando \cmd{kill}; l'unica possibilità di +cancellarli dalla tabella dei processi è quella di terminare il processo che +li ha generati, in modo che \cmd{init} possa adottarli e provvedere a +concluderne la terminazione. \subsection{Le funzioni \func{wait} e \func{waitpid}} \label{sec:proc_wait} -Abbiamo già accennato come uno degli usi possibili delle capacità multitasking -di un sistema unix-like consista nella creazione di programmi di tipo server, -in cui un processo principale attende le richieste che vengono poi soddisfatte -creando una serie di processi figli. Si è già sottolineato al paragrafo -precedente come in questo caso diventi necessario gestire esplicitamente la -conclusione dei vari processi figli onde evitare di riempire di -\textit{zombie} la tabella dei processi; le funzioni deputate a questo compito -sono sostanzialmente due, \func{wait} e \func{waitpid}. La prima, il cui -prototipo è: +Uno degli usi più comuni delle capacità multitasking di un sistema unix-like +consiste nella creazione di programmi di tipo server, in cui un processo +principale attende le richieste che vengono poi soddisfatte da una serie di +processi figli. Si è già sottolineato al paragrafo precedente come in questo +caso diventi necessario gestire esplicitamente la conclusione dei figli onde +evitare di riempire di \textit{zombie} la tabella dei processi; le funzioni +deputate a questo compito sono sostanzialmente due, \func{wait} e +\func{waitpid}. La prima, il cui prototipo è: \begin{functions} \headdecl{sys/types.h} \headdecl{sys/wait.h} @@ -833,7 +831,7 @@ segnale termina il processo o chiama una funzione di gestione. \end{errlist}} \end{functions} \noindent -è presente fin dalle prime versioni di unix; la funzione ritorna non appena un +è presente fin dalle prime versioni di Unix; la funzione ritorna non appena un processo figlio termina. Se un figlio è già terminato la funzione ritorna immediatamente. @@ -867,8 +865,8 @@ Attende la conclusione di un processo figlio. \begin{errlist} \item[\macro{EINTR}] se non è stata specificata l'opzione \macro{WNOHANG} e la funzione è stata interrotta da un segnale. - \item[\macro{ECHILD}] il processo specificato da \var{pid} non esiste o non è - figlio del processo chiamante. + \item[\macro{ECHILD}] il processo specificato da \param{pid} non esiste o + non è figlio del processo chiamante. \end{errlist}} \end{functions} @@ -876,7 +874,7 @@ Le differenze principali fra le due funzioni sono che \func{wait} si blocca sempre fino a che un processo figlio non termina, mentre \func{waitpid} ha la possibilità si specificare un'opzione \macro{WNOHANG} che ne previene il blocco; inoltre \func{waitpid} può specificare quale processo attendere sulla -base del valore specificato tramite la variabile \var{pid}, secondo lo +base del valore fornito dall'argomento \param{pid}, secondo lo specchietto riportato in \ntab: \begin{table}[!htb] \centering @@ -901,31 +899,33 @@ specchietto riportato in \ntab: \label{tab:proc_waidpid_pid} \end{table} -Il comportamento di \func{waitpid} può essere modificato passando delle -opportune opzioni tramite la variabile \var{option}. I valori possibili sono -il già citato \macro{WNOHANG}, che previene il blocco della funzione quando il -processo figlio non è terminato, e \macro{WUNTRACED} (usata per il controllo -di sessione, trattato in \capref{cha:session}) che fa ritornare la funzione -anche per i processi figli che sono bloccati ed il cui stato non è stato -ancora riportato al padre. Il valore dell'opzione deve essere specificato come -maschera binaria ottenuta con l'OR delle suddette costanti con zero. +Il comportamento di \func{waitpid} può inoltre essere modificato passando +delle opportune opzioni tramite l'argomento \param{option}. I valori possibili +sono il già citato \macro{WNOHANG}, che previene il blocco della funzione +quando il processo figlio non è terminato, e \macro{WUNTRACED} (usata per il +controllo di sessione, trattato in \capref{cha:session}) che fa ritornare la +funzione anche per i processi figli che sono bloccati ed il cui stato non è +stato ancora riportato al padre. Il valore dell'opzione deve essere +specificato come maschera binaria ottenuta con l'OR delle suddette costanti +con zero. 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 si è visto nella sezione precedente, una -delle azioni prese dal kernel alla conclusione di un processo è quella di -mandare un segnale di \macro{SIGCHLD} al padre. Questo segnale viene ignorato -di default, ma costituisce il meccanismo di comunicazione asincrona con cui il -kernel avverte un processo padre che uno dei suoi figli è terminato. +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 \macro{SIGCHLD} al padre. L'azione di default (si veda +\secref{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. In genere in un programma non si vuole essere forzati ad attendere la conclusione di un processo per proseguire, specie se tutto questo serve solo per leggerne lo stato di chiusura (ed evitare la presenza di \textit{zombie}), per questo la modalità più usata per chiamare queste funzioni è quella di utilizzarle all'interno di un \textit{signal handler} (torneremo sui segnali e -su come gestire \macro{SIGCHLD} in \secref{sec:sig_sigwait_xxx}) nel qual -caso, dato che il segnale è generato dalla terminazione un figlio, avremo la -certezza che la chiamata a \func{wait} non si bloccherà. +su come gestire \macro{SIGCHLD} in \secref{sec:sig_sigwait_xxx}). In questo +caso infatti, dato che il segnale è generato dalla terminazione un figlio, +avremo la certezza che la chiamata a \func{wait} non si bloccherà. \begin{table}[!htb] \centering @@ -966,19 +966,21 @@ certezza che la chiamata a \func{wait} non si bloccher \end{table} Entrambe le funzioni di attesa restituiscono lo stato di terminazione del -processo tramite il puntatore \var{status} (se non interessa memorizzare lo +processo tramite il puntatore \param{status} (se non interessa memorizzare lo stato si può passare un puntatore nullo). Il valore restituito da entrambe le -funzioni dipende dall'implementazione, e tradizionalmente alcuni bit sono -riservati per memorizzare lo stato di uscita (in genere 8) altri per indicare -il segnale che ha causato la terminazione (in caso di conclusione anomala), -uno per indicare se è stato generato un core file, ecc\footnote{le - definizioni esatte si possono trovare in \file{}}. 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 \curtab\ (si tenga presente che -queste macro prendono come parametro la variabile di tipo \type{int} puntata -da \var{status}). +funzioni dipende dall'implementazione, e tradizionalmente alcuni bit (in +genere 8) sono riservati per memorizzare lo stato di uscita, e altri per +indicare il segnale che ha causato la terminazione (in caso di conclusione +anomala), uno per indicare se è stato generato un core file, ecc.\footnote{le + definizioni esatte si possono trovare in \file{} ma + questo file non deve mai essere usato direttamente, esso viene incluso + attraverso \file{}.} + +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 \curtab\ (si tenga presente che queste +macro prendono come parametro la variabile di tipo \type{int} puntata da +\var{status}). Si tenga conto che nel caso di conclusione anomala il valore restituito da \macro{WTERMSIG} può essere controllato contro le costanti definite in @@ -989,12 +991,13 @@ le apposite funzioni trattate in \secref{sec:sig_strsignal}. \subsection{Le funzioni \func{wait3} e \func{wait4}} \label{sec:proc_wait4} -Linux, seguendo una estensione di BSD, supporta altre due funzioni per la -lettura dello stato di terminazione di un processo, analoghe a \func{wait} e -\func{waitpid}, ma che prevedono un ulteriore parametro attraverso il quale il -kernel può restituire al padre informazioni sulle risorse usate dal processo -terminato e dai vari figli. Queste funzioni, che diventano accessibili -definendo la costante \macro{\_USE\_BSD}, sono: +Linux, seguendo una estensione di BSD, supporta altre due funzioni, +\func{wait} e \func{waitpd}, per la lettura dello stato di terminazione di un +processo, analoghe alle precedenti ma che prevedono un ulteriore parametro +attraverso il quale il kernel può restituire al padre informazioni sulle +risorse usate dal processo terminato e dai vari figli. I prototipi di queste +funzioni, che diventano accessibili definendo la costante \macro{\_USE\_BSD}, +sono: \begin{functions} \headdecl{sys/times.h} \headdecl{sys/types.h} @@ -1013,7 +1016,7 @@ definendo la costante \macro{\_USE\_BSD}, sono: \noindent la struttura \type{rusage} è definita in \file{sys/resource.h}, e viene utilizzata anche dalla funzione \func{getrusage} (vedi \secref{sec:sys_xxx}) -per ottenere le risorse di sistema usate dal processo; la sua definizione è +per ottenere le risorse di sistema usate da un processo; la sua definizione è riportata in \figref{fig:sys_rusage_struct}. In genere includere esplicitamente \file{} non è più