From 4eaaee43e4e0df09fae1ba66466ee77ff78db517 Mon Sep 17 00:00:00 2001 From: Simone Piccardi Date: Wed, 1 May 2013 13:45:07 +0000 Subject: [PATCH] Cancellazione dell'uso della macro Command e sostituzione con Console --- filedir.tex | 38 ++++----- ipc.tex | 197 +++++++++++++++++++++++--------------------- listati/char_list.c | 2 +- prochand.tex | 110 ++++++++++++++----------- 4 files changed, 177 insertions(+), 170 deletions(-) diff --git a/filedir.tex b/filedir.tex index 89d65c8..b0e42ac 100644 --- a/filedir.tex +++ b/filedir.tex @@ -1623,26 +1623,22 @@ Un altro punto da tenere sempre presente è che, come abbiamo accennato, un collegamento simbolico può fare riferimento anche ad un file che non esiste; ad esempio possiamo usare il comando \cmd{ln} per creare un collegamento simbolico nella nostra directory con: -\begin{Command} -$ ln -s /tmp/tmp_file symlink -\end{Command} +\begin{Console} +piccardi@hain:~/gapil$ \textbf{ln -s /tmp/tmp_file symlink} +\end{Console} %$ e questo avrà successo anche se \file{/tmp/tmp\_file} non esiste: -\begin{Command} -$ ls symlink -\end{Command} -\begin{Terminal} +\begin{Console} +piccardi@hain:~/gapil$ \textbf{ls symlink} symlink -\end{Terminal} +\end{Console} %$ ma questo può generare confusione, perché accedendo in sola lettura a \file{symlink}, ad esempio con \cmd{cat}, otterremmo un errore: -\begin{Command} -$ cat symlink -\end{Command} -\begin{Terminal} +\begin{Console} +piccardi@hain:~/gapil$ \textbf{cat symlink} cat: symlink: No such file or directory -\end{Terminal} +\end{Console} %$ con un errore che può sembrare sbagliato, dato che \cmd{ls} ci ha mostrato l'esistenza di \file{symlink}, se invece scrivessimo su \file{symlink} @@ -4233,12 +4229,10 @@ condizioni: Un classico esempio di directory che ha questo bit impostato è \file{/tmp}, i cui permessi infatti di solito sono i seguenti: -\begin{Command} -$ ls -ld /tmp -\end{Command} -\begin{Terminal} +\begin{Console} +piccardi@hain:~/gapil$ \textbf{ls -ld /tmp} drwxrwxrwt 6 root root 1024 Aug 10 01:03 /tmp -\end{Terminal} +\end{Console} %$ quindi con lo \textit{sticky bit} bit impostato. In questo modo qualunque utente nel sistema può creare dei file in questa directory, che come @@ -7597,16 +7591,14 @@ allocare autonomamente e che al solito deve essere disallocato con \errval{ESRCH}. Gli stessi valori possono essere letti direttamente nel filesystem \textit{proc}, nei file \texttt{/proc//status}; ad esempio per \texttt{init} si otterrà qualcosa del tipo: -\begin{Command} -$ cat /proc/1/status -\end{Command} -\begin{Terminal} +\begin{Console} +piccardi@hain:~/gapil$ \textbf{cat /proc/1/status} ... CapInh: 0000000000000000 CapPrm: 00000000fffffeff CapEff: 00000000fffffeff ... -\end{Terminal} +\end{Console} %$ \itindend{capability~state} diff --git a/ipc.tex b/ipc.tex index 45917eb..41c64c4 100644 --- a/ipc.tex +++ b/ipc.tex @@ -552,13 +552,14 @@ fintanto che non si supera il limite delle dimensioni di \const{PIPE\_BUF} (si ricordi quanto detto in sez.~\ref{sec:ipc_pipes}). A parte il caso precedente, che resta probabilmente il più comune, Stevens -riporta in \cite{APUE} altre due casistiche principali per l'uso delle fifo: +riporta in \cite{APUE} altre due casistiche principali per l'uso delle +\textit{fifo}: \begin{itemize*} \item Da parte dei comandi di shell, per evitare la creazione di file temporanei quando si devono inviare i dati di uscita di un processo sull'input di parecchi altri (attraverso l'uso del comando \cmd{tee}). -\item Come canale di comunicazione fra un \textit{client} ed un - \textit{server} (il modello \textit{client-server} è illustrato in +\item Come canale di comunicazione fra un client ed un + server (il modello \textit{client-server} è illustrato in sez.~\ref{sec:net_cliserv}). \end{itemize*} @@ -572,38 +573,38 @@ varie \textit{fifo}. Il secondo caso è relativamente semplice qualora si debba comunicare con un processo alla volta, nel qual caso basta usare due \textit{fifo}, una per leggere ed una per scrivere. Le cose diventano invece molto più complesse -quando si vuole effettuare una comunicazione fra un \textit{server} ed un -numero imprecisato di \textit{client}. Se il primo infatti può ricevere le -richieste attraverso una fifo ``\textsl{nota}'', per le risposte non si può +quando si vuole effettuare una comunicazione fra un server ed un numero +imprecisato di client. Se il primo infatti può ricevere le richieste +attraverso una \textit{fifo} ``\textsl{nota}'', per le risposte non si può fare altrettanto, dato che, per la struttura sequenziale delle \textit{fifo}, -i \textit{client} dovrebbero sapere prima di leggerli quando i dati inviati -sono destinati a loro. +i client dovrebbero sapere prima di leggerli quando i dati inviati sono +destinati a loro. Per risolvere questo problema, si può usare un'architettura come quella -illustrata in fig.~\ref{fig:ipc_fifo_server_arch} in cui i \textit{client} -inviano le richieste al \textit{server} su una \textit{fifo} nota mentre le -risposte vengono reinviate dal \textit{server} a ciascuno di essi su una +illustrata in fig.~\ref{fig:ipc_fifo_server_arch} in cui i client +inviano le richieste al server su una \textit{fifo} nota mentre le +risposte vengono reinviate dal server a ciascuno di essi su una \textit{fifo} temporanea creata per l'occasione. \begin{figure}[!htb] \centering \includegraphics[height=9cm]{img/fifoserver} - \caption{Schema dell'utilizzo delle fifo nella realizzazione di una - architettura di comunicazione client/server.} + \caption{Schema dell'utilizzo delle \textit{fifo} nella realizzazione di una + architettura di comunicazione client/server.} \label{fig:ipc_fifo_server_arch} \end{figure} -Come esempio di uso questa architettura e dell'uso delle fifo, abbiamo scritto -un server di \textit{fortunes}, che restituisce, alle richieste di un client, -un detto a caso estratto da un insieme di frasi; sia il numero delle frasi -dell'insieme, che i file da cui esse vengono lette all'avvio, sono importabili -da riga di comando. Il corpo principale del server è riportato in -fig.~\ref{fig:ipc_fifo_server}, dove si è tralasciata la parte che tratta la -gestione delle opzioni a riga di comando, che effettua l'impostazione delle -variabili \var{fortunefilename}, che indica il file da cui leggere le frasi, -ed \var{n}, che indica il numero di frasi tenute in memoria, ad un valore -diverso da quelli preimpostati. Il codice completo è nel file -\file{FortuneServer.c}. +Come esempio di uso questa architettura e dell'uso delle \textit{fifo}, +abbiamo scritto un server di \textit{fortunes}, che restituisce, alle +richieste di un client, un detto a caso estratto da un insieme di frasi. Sia +il numero delle frasi dell'insieme, che i file da cui esse vengono lette +all'avvio, sono impostabili da riga di comando. Il corpo principale del +server è riportato in fig.~\ref{fig:ipc_fifo_server}, dove si è +tralasciata la parte che tratta la gestione delle opzioni a riga di comando, +che effettua l'impostazione delle variabili \var{fortunefilename}, che indica +il file da cui leggere le frasi, ed \var{n}, che indica il numero di frasi +tenute in memoria, ad un valore diverso da quelli preimpostati. Il codice +completo è nel file \file{FortuneServer.c}. \begin{figure}[!htbp] \footnotesize \centering @@ -612,7 +613,7 @@ diverso da quelli preimpostati. Il codice completo è nel file \end{minipage} \normalsize \caption{Sezione principale del codice del server di \textit{fortunes} - basato sulle fifo.} + basato sulle \textit{fifo}.} \label{fig:ipc_fifo_server} \end{figure} @@ -623,7 +624,7 @@ presenza di un valore nullo provoca l'uscita dal programma attraverso la funzione (non riportata) che ne stampa le modalità d'uso. Dopo di che installa (\texttt{\small 13--15}) la funzione che gestisce i segnali di interruzione (anche questa non è riportata in fig.~\ref{fig:ipc_fifo_server}) -che si limita a rimuovere dal filesystem la fifo usata dal server per +che si limita a rimuovere dal filesystem la \textit{fifo} usata dal server per comunicare. Terminata l'inizializzazione (\texttt{\small 16}) si effettua la chiamata alla @@ -634,61 +635,64 @@ Anche il codice della funzione non è riportato, in quanto non direttamente attinente allo scopo dell'esempio. Il passo successivo (\texttt{\small 17--22}) è quello di creare con -\func{mkfifo} la fifo nota sulla quale il server ascolterà le richieste, -qualora si riscontri un errore il server uscirà (escludendo ovviamente il caso -in cui la funzione \func{mkfifo} fallisce per la precedente esistenza della -fifo). - -Una volta che si è certi che la fifo di ascolto esiste la procedura di -inizializzazione è completata. A questo punto si può chiamare (\texttt{\small - 23}) la funzione \func{daemon} per far proseguire l'esecuzione del programma -in background come demone. Si può quindi procedere (\texttt{\small 24--33}) -alla apertura della fifo: si noti che questo viene fatto due volte, prima in -lettura e poi in scrittura, per evitare di dover gestire all'interno del ciclo -principale il caso in cui il server è in ascolto ma non ci sono client che -effettuano richieste. Si ricordi infatti che quando una fifo è aperta solo -dal capo in lettura, l'esecuzione di \func{read} ritorna con zero byte (si ha -cioè una condizione di end-of-file). +\func{mkfifo} la \textit{fifo} nota sulla quale il server ascolterà le +richieste, qualora si riscontri un errore il server uscirà (escludendo +ovviamente il caso in cui la funzione \func{mkfifo} fallisce per la precedente +esistenza della \textit{fifo}). + +Una volta che si è certi che la \textit{fifo} di ascolto esiste la procedura +di inizializzazione è completata. A questo punto si può chiamare +(\texttt{\small 23}) la funzione \func{daemon} per far proseguire l'esecuzione +del programma in background come demone. Si può quindi procedere +(\texttt{\small 24--33}) alla apertura della \textit{fifo}: si noti che questo +viene fatto due volte, prima in lettura e poi in scrittura, per evitare di +dover gestire all'interno del ciclo principale il caso in cui il server è in +ascolto ma non ci sono client che effettuano richieste. Si ricordi infatti +che quando una \textit{fifo} è aperta solo dal capo in lettura, l'esecuzione di +\func{read} ritorna con zero byte (si ha cioè una condizione di end-of-file). Nel nostro caso la prima apertura si bloccherà fintanto che un qualunque -client non apre a sua volta la fifo nota in scrittura per effettuare la sua +client non apre a sua volta la \textit{fifo} nota in scrittura per effettuare la sua richiesta. Pertanto all'inizio non ci sono problemi, il client però, una volta -ricevuta la risposta, uscirà, chiudendo tutti i file aperti, compresa la fifo. -A questo punto il server resta (se non ci sono altri client che stanno -effettuando richieste) con la fifo chiusa sul lato in lettura, ed in questo -stato la funzione \func{read} non si bloccherà in attesa di input, ma -ritornerà in continuazione, restituendo un end-of-file.\footnote{si è usata - questa tecnica per compatibilità, Linux infatti supporta l'apertura delle - fifo in lettura/scrittura, per cui si sarebbe potuto effettuare una singola - apertura con \const{O\_RDWR}, la doppia apertura comunque ha il vantaggio - che non si può scrivere per errore sul capo aperto in sola lettura.} +ricevuta la risposta, uscirà, chiudendo tutti i file aperti, compresa la +\textit{fifo}. A questo punto il server resta (se non ci sono altri client +che stanno effettuando richieste) con la \textit{fifo} chiusa sul lato in +lettura, ed in questo stato la funzione \func{read} non si bloccherà in attesa +di dati in ingresso, ma ritornerà in continuazione, restituendo una condizione +di \textit{end-of-file}. + +Si è usata questa tecnica per compatibilità, Linux infatti supporta l'apertura +delle \textit{fifo} in lettura/scrittura, per cui si sarebbe potuto effettuare +una singola apertura con \const{O\_RDWR}; la doppia apertura comunque ha il +vantaggio che non si può scrivere per errore sul capo aperto in sola lettura. Per questo motivo, dopo aver eseguito l'apertura in lettura (\texttt{\small 24--28}),\footnote{di solito si effettua l'apertura del capo in lettura di - una fifo in modalità non bloccante, per evitare il rischio di uno stallo: se - infatti nessuno apre la fifo in scrittura il processo non ritornerà mai - dalla \func{open}. Nel nostro caso questo rischio non esiste, mentre è - necessario potersi bloccare in lettura in attesa di una richiesta.} si -esegue una seconda apertura in scrittura (\texttt{\small 29--32}), scartando -il relativo file descriptor, che non sarà mai usato, in questo modo però la -fifo resta comunque aperta anche in scrittura, cosicché le successive chiamate -a \func{read} possono bloccarsi. + una \textit{fifo} in modalità non bloccante, per evitare il rischio di uno + stallo: se infatti nessuno apre la \textit{fifo} in scrittura il processo + non ritornerà mai dalla \func{open}. Nel nostro caso questo rischio non + esiste, mentre è necessario potersi bloccare in lettura in attesa di una + richiesta.} si esegue una seconda apertura in scrittura (\texttt{\small + 29--32}), scartando il relativo file descriptor, che non sarà mai usato, in +questo modo però la \textit{fifo} resta comunque aperta anche in scrittura, +cosicché le successive chiamate a \func{read} possono bloccarsi. A questo punto si può entrare nel ciclo principale del programma che fornisce le risposte ai client (\texttt{\small 34--50}); questo viene eseguito indefinitamente (l'uscita del server viene effettuata inviando un segnale, in -modo da passare attraverso la funzione di chiusura che cancella la fifo). +modo da passare attraverso la funzione di chiusura che cancella la +\textit{fifo}). Il server è progettato per accettare come richieste dai client delle stringhe -che contengono il nome della fifo sulla quale deve essere inviata la risposta. -Per cui prima (\texttt{\small 35--39}) si esegue la lettura dalla stringa di -richiesta dalla fifo nota (che a questo punto si bloccherà tutte le volte che -non ci sono richieste). Dopo di che, una volta terminata la stringa -(\texttt{\small 40}) e selezionato (\texttt{\small 41}) un numero casuale per -ricavare la frase da inviare, si procederà (\texttt{\small 42--46}) -all'apertura della fifo per la risposta, che poi \texttt{\small 47--48}) vi -sarà scritta. Infine (\texttt{\small 49}) si chiude la fifo di risposta che -non serve più. +che contengono il nome della \textit{fifo} sulla quale deve essere inviata la +risposta. Per cui prima (\texttt{\small 35--39}) si esegue la lettura dalla +stringa di richiesta dalla \textit{fifo} nota (che a questo punto si bloccherà +tutte le volte che non ci sono richieste). Dopo di che, una volta terminata la +stringa (\texttt{\small 40}) e selezionato (\texttt{\small 41}) un numero +casuale per ricavare la frase da inviare, si procederà (\texttt{\small + 42--46}) all'apertura della \textit{fifo} per la risposta, che poi +\texttt{\small 47--48}) vi sarà scritta. Infine (\texttt{\small 49}) si chiude +la \textit{fifo} di risposta che non serve più. Il codice del client è invece riportato in fig.~\ref{fig:ipc_fifo_client}, anche in questo caso si è omessa la gestione delle opzioni e la funzione che @@ -703,31 +707,32 @@ principale del programma e le definizioni delle variabili. Il codice completo \end{minipage} \normalsize \caption{Sezione principale del codice del client di \textit{fortunes} - basato sulle fifo.} + basato sulle \textit{fifo}.} \label{fig:ipc_fifo_client} \end{figure} -La prima istruzione (\texttt{\small 12}) compone il nome della fifo che dovrà -essere utilizzata per ricevere la risposta dal server. Si usa il \ids{PID} -del processo per essere sicuri di avere un nome univoco; dopo di che +La prima istruzione (\texttt{\small 12}) compone il nome della \textit{fifo} +che dovrà essere utilizzata per ricevere la risposta dal server. Si usa il +\ids{PID} del processo per essere sicuri di avere un nome univoco; dopo di che (\texttt{\small 13-18}) si procede alla creazione del relativo file, uscendo in caso di errore (a meno che il file non sia già presente sul filesystem). A questo punto il client può effettuare l'interrogazione del server, per -questo prima si apre la fifo nota (\texttt{\small 19--23}), e poi ci si scrive -(\texttt{\small 24}) la stringa composta in precedenza, che contiene il nome -della fifo da utilizzare per la risposta. Infine si richiude la fifo del -server che a questo punto non serve più (\texttt{\small 25}). +questo prima si apre la \textit{fifo} nota (\texttt{\small 19--23}), e poi ci +si scrive (\texttt{\small 24}) la stringa composta in precedenza, che contiene +il nome della \textit{fifo} da utilizzare per la risposta. Infine si richiude +la \textit{fifo} del server che a questo punto non serve più (\texttt{\small + 25}). Inoltrata la richiesta si può passare alla lettura della risposta; anzitutto -si apre (\texttt{\small 26--30}) la fifo appena creata, da cui si deve -riceverla, dopo di che si effettua una lettura (\texttt{\small 31}) +si apre (\texttt{\small 26--30}) la \textit{fifo} appena creata, da cui si +deve riceverla, dopo di che si effettua una lettura (\texttt{\small 31}) nell'apposito buffer; si è supposto, come è ragionevole, che le frasi inviate dal server siano sempre di dimensioni inferiori a \const{PIPE\_BUF}, tralasciamo la gestione del caso in cui questo non è vero. Infine si stampa (\texttt{\small 32}) a video la risposta, si chiude (\texttt{\small 33}) la -fifo e si cancella (\texttt{\small 34}) il relativo file. -Si noti come la fifo per la risposta sia stata aperta solo dopo aver inviato +\textit{fifo} e si cancella (\texttt{\small 34}) il relativo file. Si noti +come la \textit{fifo} per la risposta sia stata aperta solo dopo aver inviato la richiesta, se non si fosse fatto così si avrebbe avuto uno stallo, in quanto senza la richiesta, il server non avrebbe potuto aprirne il capo in scrittura e l'apertura si sarebbe bloccata indefinitamente. @@ -744,33 +749,33 @@ facciano le prove direttamente nella directory dei sorgenti (dove di norma vengono creati sia i programmi che la libreria), il comando da dare sarà \code{export LD\_LIBRARY\_PATH=./}; a questo punto potremo lanciare il server, facendogli leggere una decina di frasi, con: -\begin{Verbatim} -[piccardi@gont sources]$ ./fortuned -n10 -\end{Verbatim} +\begin{Console} +[piccardi@gont sources]$ \textbf{./fortuned -n10} +\end{Console} %$ Avendo usato \func{daemon} per eseguire il server in background il comando ritornerà immediatamente, ma potremo verificare con \cmd{ps} che in effetti il programma resta un esecuzione in background, e senza avere associato un terminale di controllo (si ricordi quanto detto in sez.~\ref{sec:sess_daemon}): -\begin{Verbatim} -[piccardi@gont sources]$ ps aux +\begin{Console} +[piccardi@gont sources]$ \textbf{ps aux} ... piccardi 27489 0.0 0.0 1204 356 ? S 01:06 0:00 ./fortuned -n10 piccardi 27492 3.0 0.1 2492 764 pts/2 R 01:08 0:00 ps aux -\end{Verbatim} +\end{Console} %$ -e si potrà verificare anche che in \file{/tmp} è stata creata la fifo di -ascolto \file{fortune.fifo}. A questo punto potremo interrogare il server con -il programma client; otterremo così: -\begin{Verbatim} -[piccardi@gont sources]$ ./fortune +e si potrà verificare anche che in \file{/tmp} è stata creata la \textit{fifo} +di ascolto \file{fortune.fifo}. A questo punto potremo interrogare il server +con il programma client; otterremo così: +\begin{Console} +[piccardi@gont sources]$ \textbf{./fortune} Linux ext2fs has been stable for a long time, now it's time to break it -- Linuxkongreß '95 in Berlin -[piccardi@gont sources]$ ./fortune +[piccardi@gont sources]$ \textbf{./fortune} Let's call it an accidental feature. --Larry Wall -[piccardi@gont sources]$ ./fortune +[piccardi@gont sources]$ \textbf{./fortune} ......... Escape the 'Gates' of Hell `:::' ....... ...... ::: * `::. ::' @@ -782,14 +787,14 @@ Let's call it an accidental feature. [piccardi@gont sources]$ ./fortune Linux ext2fs has been stable for a long time, now it's time to break it -- Linuxkongreß '95 in Berlin -\end{Verbatim} +\end{Console} %$ e ripetendo varie volte il comando otterremo, in ordine casuale, le dieci frasi tenute in memoria dal server. Infine per chiudere il server basterà inviare un segnale di terminazione con \code{killall fortuned} e potremo verificare che il gestore del segnale ha -anche correttamente cancellato la fifo di ascolto da \file{/tmp}. +anche correttamente cancellato la \textit{fifo} di ascolto da \file{/tmp}. Benché il nostro sistema client-server funzioni, la sua struttura è piuttosto complessa e continua ad avere vari inconvenienti\footnote{lo stesso Stevens, diff --git a/listati/char_list.c b/listati/char_list.c index 0044b02..3cffdae 100644 --- a/listati/char_list.c +++ b/listati/char_list.c @@ -1 +1 @@ - char *arg0, char *arg1, ..., char *argn, NULL +char *arg0, char *arg1, ..., char *argn, NULL diff --git a/prochand.tex b/prochand.tex index c7186d5..fb6b233 100644 --- a/prochand.tex +++ b/prochand.tex @@ -516,24 +516,27 @@ Il comportamento delle varie funzioni di interfaccia con i file è analizzato in gran dettaglio in sez.~\ref{sec:file_unix_interface} per l'interfaccia nativa Unix ed in sez.~\ref{sec:files_std_interface} per la standardizzazione adottata nelle librerie del linguaggio C e valida per qualunque sistema -operativo. Qui basta accennare che si sono usate le funzioni standard della -libreria del C che prevedono l'output bufferizzato. Il punto è che questa -bufferizzazione (che tratteremo 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, in cui il buffer -viene scaricato ad ogni carattere di a capo. +operativo. + +Qui basta accennare che si sono usate le funzioni standard della libreria del +C che prevedono l'output bufferizzato. Il punto è che questa bufferizzazione +(che tratteremo 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, in cui il buffer viene scaricato ad +ogni carattere di a capo. Nel primo esempio allora avevamo che, essendovi un a capo nella stringa stampata, ad ogni chiamata a \func{printf} il buffer veniva scaricato, per cui le singole righe comparivano 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. 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. +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 @@ -544,17 +547,17 @@ avviene per le variabili in memoria, la posizione corrente sul file è condivisa fra il padre e tutti i processi figli. Quello che succede è che quando lo \textit{standard output}\footnote{si chiama - così il file su cui un programma scrive i suoi dati in uscita, tratteremo - l'argomento in dettaglio in sez.~\ref{sec:file_fd}.} del padre viene -rediretto come si è fatto nell'esempio, lo stesso avviene anche per tutti i -figli. La funzione \func{fork} infatti ha la caratteristica di duplicare nei -processi figli tutti i \textit{file descriptor} (vedi sez.~\ref{sec:file_fd}) -dei file aperti nel processo padre (allo stesso modo in cui lo fa la funzione -\func{dup}, trattata in sez.~\ref{sec:file_dup}), il che comporta che padre e -figli condividono le stesse voci della \itindex{file~table} \textit{file - table} (tratteremo in dettaglio questi termini in -sez.~\ref{sec:file_shared_access}) fra cui c'è anche la posizione corrente nel -file. + così il file su cui di default un programma scrive i suoi dati in uscita, + tratteremo l'argomento in dettaglio in sez.~\ref{sec:file_fd}.} del padre +viene rediretto come si è fatto nell'esempio, lo stesso avviene anche per +tutti i figli. La funzione \func{fork} infatti ha la caratteristica di +duplicare nei processi figli tutti i \textit{file descriptor} (vedi +sez.~\ref{sec:file_fd}) dei file aperti nel processo padre (allo stesso modo +in cui lo fa la funzione \func{dup}, trattata in sez.~\ref{sec:file_dup}), il +che comporta che padre e figli condividono le stesse voci della +\itindex{file~table} \textit{file table} (tratteremo in dettaglio questi +termini in sez.~\ref{sec:file_shared_access}) fra cui c'è anche la posizione +corrente nel file. In questo modo se un processo scrive su un file aggiornerà la posizione corrente sulla \itindex{file~table} \textit{file table}, e tutti gli altri @@ -841,18 +844,18 @@ sono terminati (la scritta \texttt{defunct}). La possibilità di avere degli \itindex{zombie} \textit{zombie} deve essere tenuta sempre 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 sez.~\ref{sec:sig_sigchld} e -sez.~\ref{sec:proc_wait}) di cui vedremo un esempio in -fig.~\ref{fig:sig_sigchld_handl}. - -Questa operazione è necessaria perché anche se gli \itindex{zombie} -\textit{zombie} non consumano risorse di memoria o processore, occupano -comunque una voce nella tabella dei processi e se li si lascia accumulare a -lungo quest'ultima potrebbe riempirsi, con l'impossibilità di lanciare nuovi -processi. +in esecuzione a lungo e creare molti processi figli. In questo caso si deve +sempre avere cura di far leggere al programma l'eventuale stato di uscita di +tutti i figli. Una modalità comune di farlo è attraverso l'utilizzo di un +apposito \textit{signal handler} che chiami la funzione \func{wait}, (vedi +sez.~\ref{sec:proc_wait}), ne esamineremo in dettaglio un esempio +(fig.~\ref{fig:sig_sigchld_handl}) in sez.~\ref{sec:sig_sigchld}. + +La lettura degli stati di uscita è necessaria perché anche se gli +\itindex{zombie} \textit{zombie} non consumano risorse di memoria o +processore, occupano comunque una voce nella tabella dei processi e se li si +lasciano accumulare a lungo quest'ultima potrebbe esaurirsi, con la +conseguente impossibilità di lanciare nuovi processi. Si noti tuttavia che quando un processo adottato da \cmd{init} termina, non diviene mai uno \itindex{zombie} \textit{zombie}. Questo perché una delle @@ -868,9 +871,16 @@ provvede a completarne la terminazione. Si tenga presente infine che siccome gli \itindex{zombie} \textit{zombie} sono processi già terminati, non c'è modo di eliminarli con il comando \cmd{kill} o inviandogli un qualunque segnale di terminazione (l'argomento è trattato in -sez.~\ref{sec:sig_termination}). 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 concluderne la terminazione. +sez.~\ref{sec:sig_termination}). Qualora ci si trovi in questa situazione +l'unica possibilità di cancellarli dalla tabella dei processi è quella di +terminare il processo che li ha generati e che non sta facendo il suo lavoro, +in modo che \cmd{init} possa adottarli e concluderne correttamente la +terminazione. + +Si tenga anche presente che la presenza di \textit{zombie} nella tabella dei +processi non è sempre indice di un qualche malfunzionamento, in una macchina +con molto carico infatti può esservi una presenza temporanea dovuta al fatto +che il processo padre ancora non ha avuto il tempo di gestirli. \subsection{Le funzioni di attesa e ricezione degli stati di uscita} \label{sec:proc_wait} @@ -1491,7 +1501,7 @@ convenzione che il primo argomento (\var{arg0} o \var{argv[0]}) viene usato per indicare il nome del file che contiene il programma che verrà eseguito. \begin{figure}[!htb] - \centering \includegraphics[width=10cm]{img/exec_rel} + \centering \includegraphics[width=9cm]{img/exec_rel} \caption{La interrelazione fra le sei funzioni della famiglia \func{exec}.} \label{fig:proc_exec_relat} \end{figure} @@ -1639,13 +1649,13 @@ file appartiene. Se il file da eseguire è in formato \emph{a.out} e necessita di librerie condivise, viene lanciato il \textit{linker} dinamico \cmd{/lib/ld.so} prima del programma per caricare le librerie necessarie ed effettuare il link -dell'eseguibile.\footnote{il formato è ormai in completo disuso, per cui è - molto probabile che non il relativo supporto non sia disponibile.} Se il -programma è in formato ELF per caricare le librerie dinamiche viene usato -l'interprete indicato nel segmento \const{PT\_INTERP} previsto dal formato -stesso, in genere questo è \sysfile{/lib/ld-linux.so.1} per programmi -collegati con la \acr{libc5}, e \sysfile{/lib/ld-linux.so.2} per programmi -collegati con la \acr{glibc}. +dell'eseguibile; il formato è ormai in completo disuso, per cui è molto +probabile che non il relativo supporto non sia disponibile. Se il programma è +in formato ELF per caricare le librerie dinamiche viene usato l'interprete +indicato nel segmento \const{PT\_INTERP} previsto dal formato stesso, in +genere questo è \sysfile{/lib/ld-linux.so.1} per programmi collegati con la +\acr{libc5}, e \sysfile{/lib/ld-linux.so.2} per programmi collegati con la +\acr{glibc}. Infine nel caso il programma che si vuole eseguire sia uno script e non un binario, questo deve essere un file di testo che deve iniziare con una linea @@ -1663,9 +1673,9 @@ lunghezza massima di 127 caratteri e se questa dimensione viene ecceduta la stringa viene troncata; altri Unix hanno dimensioni massime diverse, e diversi comportamenti, ad esempio FreeBSD esegue la scansione della riga e la divide nei vari argomenti e se è troppo lunga restituisce un errore di -\const{ENAMETOOLONG}.\footnote{una comparazione dei vari comportamenti sui - diversi sistemi unix-like si trova su - \url{http://www.in-ulm.de/~mascheck/various/shebang/}.} +\const{ENAMETOOLONG}; una comparazione dei vari comportamenti sui diversi +sistemi unix-like si trova su +\url{http://www.in-ulm.de/~mascheck/various/shebang/}. Con la famiglia delle \func{exec} si chiude il novero delle funzioni su cui è basata la gestione tradizionale dei processi in Unix: con \func{fork} si crea -- 2.30.2