quanto funzionante, è volutamente codificato in maniera piuttosto complessa,
inoltre doveva scontare un problema di \cmd{gs} che non era in grado di
riconoscere correttamente l'Encapsulated PostScript,\footnote{si fa
- riferimento alla versione di GNU Ghostscript 6.53 del 2002-02-13, quando
+ riferimento alla versione di GNU Ghostscript 6.53 (2002-02-13), usata quando
l'esempio venne scritto per la prima volta.} per cui si era utilizzato il
PostScript semplice, generando una pagina intera invece che una immagine delle
dimensioni corrispondenti al codice a barre.
Come accennato in sez.~\ref{sec:ipc_pipes} il problema delle \textit{pipe} è
che esse possono essere utilizzate solo da processi con un progenitore comune
o nella relazione padre/figlio. Per superare questo problema lo standard
-POSIX.1 ha definito dei nuovi oggetti, le \textit{fifo}, che hanno le stesse
-caratteristiche delle \textit{pipe}, ma che invece di essere strutture interne
-del kernel, visibili solo attraverso un file descriptor, sono accessibili
-attraverso un \itindex{inode} \textit{inode} che risiede sul filesystem, così
-che i processi le possono usare senza dovere per forza essere in una relazione
-di \textsl{parentela}.
+POSIX.1 ha introdotto le \textit{fifo}, che hanno le stesse caratteristiche
+delle \textit{pipe}, ma che invece di essere visibili solo attraverso un file
+descriptor creato all'interno di un processo da una \textit{system call}
+apposita, costituiscono un oggetto che risiede sul filesystem (si rammenti
+quanto detto in sez.~\ref{sec:file_file_types}) che può essere aperto come un
+qualunque file, così che i processi le possono usare senza dovere per forza
+essere in una relazione di \textsl{parentela}.
Utilizzando una \textit{fifo} tutti i dati passeranno, come per le
-\textit{pipe}, attraverso un apposito buffer nel kernel, senza transitare dal
-filesystem; \itindex{inode} l'\textit{inode} allocato sul filesystem serve
-infatti solo a fornire un punto di riferimento per i processi, che permetta
-loro di accedere alla stessa fifo; il comportamento delle funzioni di lettura
-e scrittura è identico a quello illustrato per le \textit{pipe} in
-sez.~\ref{sec:ipc_pipes}.
-
-Abbiamo già visto in sez.~\ref{sec:file_mknod} le funzioni \func{mknod} e
-\func{mkfifo} che permettono di creare una \textit{fifo}; per utilizzarne una
+\textit{pipe}, attraverso un buffer nel kernel, senza transitare dal
+filesystem. Il fatto che siano associate ad un \itindex{inode}
+\textit{inode} presente sul filesystem serve infatti solo a fornire un punto
+di accesso per i processi, che permetta a questi ultimi di accedere alla
+stessa \textit{fifo} senza avere nessuna relazione, con una semplice
+\func{open}. Il comportamento delle funzioni di lettura e scrittura è identico
+a quello illustrato per le \textit{pipe} in sez.~\ref{sec:ipc_pipes}.
+
+Abbiamo già trattato in sez.~\ref{sec:file_mknod} le funzioni \func{mknod} e
+\func{mkfifo} che permettono di creare una \textit{fifo}. Per utilizzarne una
un processo non avrà che da aprire il relativo \index{file!speciali} file
-speciale o in lettura o scrittura; nel primo caso sarà collegato al capo di
-uscita della \textit{fifo}, e dovrà leggere, nel secondo al capo di ingresso,
-e dovrà scrivere.
+speciale o in lettura o scrittura; nel primo caso il processo sarà collegato
+al capo di uscita della \textit{fifo}, e dovrà leggere, nel secondo al capo di
+ingresso, e dovrà scrivere.
-Il kernel crea una singola \textit{pipe} per ciascuna \textit{fifo} che sia
-stata aperta, che può essere acceduta contemporaneamente da più processi, sia
+Il kernel alloca un singolo buffer per ciascuna \textit{fifo} che sia stata
+aperta, e questa potrà essere acceduta contemporaneamente da più processi, sia
in lettura che in scrittura. Dato che per funzionare deve essere aperta in
-entrambe le direzioni, per una \textit{fifo} di norma la funzione \func{open}
+entrambe le direzioni, per una \textit{fifo} la funzione \func{open} di norma
si blocca se viene eseguita quando l'altro capo non è aperto.
Le \textit{fifo} però possono essere anche aperte in modalità
in scrittura restituirà l'errore di \errcode{ENXIO} fintanto che non verrà
aperto il capo in lettura.
-In Linux è possibile aprire le \textit{fifo} anche in
-lettura/scrittura,\footnote{lo standard POSIX lascia indefinito il
- comportamento in questo caso.} operazione che avrà sempre successo
-immediato qualunque sia la modalità di apertura (bloccante e non bloccante);
-questo può essere utilizzato per aprire comunque una fifo in scrittura anche
-se non ci sono ancora processi il lettura; è possibile anche usare la fifo
-all'interno di un solo processo, nel qual caso però occorre stare molto
-attenti alla possibili situazioni di stallo.\footnote{se si cerca di leggere
- da una fifo che non contiene dati si avrà un \itindex{deadlock}
- \textit{deadlock} immediato, dato che il processo si blocca e non potrà
- quindi mai eseguire le funzioni di scrittura.}
+In Linux è possibile aprire le \textit{fifo} anche in lettura/scrittura (lo
+standard POSIX lascia indefinito il comportamento in questo caso) operazione
+che avrà sempre successo immediato qualunque sia la modalità di apertura,
+bloccante e non bloccante. Questo può essere utilizzato per aprire comunque
+una \textit{fifo} in scrittura anche se non ci sono ancora processi il
+lettura. Infine è possibile anche usare la \textit{fifo} all'interno di un
+solo processo, nel qual caso però occorre stare molto attenti alla possibili
+situazioni di stallo: se si cerca di leggere da una \textit{fifo} che non
+contiene dati si avrà infatti un \itindex{deadlock} \textit{deadlock}
+immediato, dato che il processo si blocca e quindi non potrà mai eseguire le
+funzioni di scrittura.
Per la loro caratteristica di essere accessibili attraverso il filesystem, è
-piuttosto frequente l'utilizzo di una fifo come canale di comunicazione nelle
-situazioni un processo deve ricevere informazioni da altri. In questo caso è
-fondamentale che le operazioni di scrittura siano atomiche; per questo si deve
-sempre tenere presente che questo è vero soltanto fintanto che non si supera
-il limite delle dimensioni di \const{PIPE\_BUF} (si ricordi quanto detto in
-sez.~\ref{sec:ipc_pipes}).
+piuttosto frequente l'utilizzo di una \textit{fifo} come canale di
+comunicazione nelle situazioni un processo deve ricevere informazioni da
+altri. In questo caso è fondamentale che le operazioni di scrittura siano
+atomiche; per questo si deve sempre tenere presente che questo è vero soltanto
+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:
\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 client ed server (il modello
- \textit{client-server} è illustrato in sez.~\ref{sec:net_cliserv}).
+ 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
+ sez.~\ref{sec:net_cliserv}).
\end{itemize*}
-Nel primo caso quello che si fa è creare tante fifo, da usare come standard
-input, quanti sono i processi a cui i vogliono inviare i dati, questi ultimi
-saranno stati posti in esecuzione ridirigendo lo standard input dalle fifo, si
-potrà poi eseguire il processo che fornisce l'output replicando quest'ultimo,
-con il comando \cmd{tee}, sulle varie fifo.
+Nel primo caso quello che si fa è creare tante \textit{fifo} da usare come
+\textit{standard input} quanti sono i processi a cui i vogliono inviare i
+dati; questi ultimi saranno stati posti in esecuzione ridirigendo lo
+\textit{standard input} dalle \textit{fifo}, si potrà poi eseguire il processo
+che fornisce l'output replicando quest'ultimo, con il comando \cmd{tee}, sulle
+varie \textit{fifo}.
Il secondo caso è relativamente semplice qualora si debba comunicare con un
-processo alla volta (nel qual caso basta usare due fifo, una per leggere ed
-una per scrivere), le cose diventano invece molto più complesse quando si
-vuole effettuare una comunicazione fra il server ed un numero imprecisato di
-client; se il primo infatti può ricevere le richieste attraverso una fifo
-``\textsl{nota}'', per le risposte non si può fare altrettanto, dato che, per
-la struttura sequenziale delle fifo, i client dovrebbero sapere, prima di
-leggerli, quando i dati inviati sono destinati a loro.
+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ò
+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.
Per risolvere questo problema, si può usare un'architettura come quella
-illustrata in fig.~\ref{fig:ipc_fifo_server_arch} in cui i client inviano le
-richieste al server su una fifo nota mentre le risposte vengono reinviate dal
-server a ciascuno di essi su una fifo temporanea creata per l'occasione.
+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
+\textit{fifo} temporanea creata per l'occasione.
\begin{figure}[!htb]
\centering
\begin{figure}[!htb]
\footnotesize
-\begin{Command}
-[piccardi@gont piccardi]$ pstree -n
-\end{Command}
-\begin{Terminal}
+\begin{Console}
+[piccardi@gont piccardi]$ \textbf{pstree -n}
init-+-keventd
|-kapm-idled
|-kreiserfsd
|-5*[getty]
|-snort
`-wwwoffled
-\end{Terminal}
+\end{Console}
%$
\caption{L'albero dei processi, così come riportato dal comando
\cmd{pstree}.}
specificare attese (come si può notare in (\texttt{\small 17--19}) i valori
predefiniti specificano di non attendere), otterremo come risultato sul
terminale:
-\begin{Command}
-[piccardi@selidor sources]$ export LD_LIBRARY_PATH=./; ./forktest 3
-\end{Command}
-%$
-\begin{Terminal}
+\begin{Console}
+[piccardi@selidor sources]$ \textbf{export LD_LIBRARY_PATH=./; ./forktest 3}
Process 1963: forking 3 child
Spawned 1 child, pid 1964
Child 1 successfully executing
Child 3, parent 1963, exiting
Spawned 3 child, pid 1966
Go to next child
-\end{Terminal}
+\end{Console}
+%$
Esaminiamo questo risultato: una prima conclusione che si può trarre è che non
si può dire quale processo fra il padre ed il figlio venga eseguito per primo
(principalmente in sez.~\ref{sec:file_unix_interface}). Per illustrare meglio
quello che avviene si può redirigere su un file l'output del programma di
test, quello che otterremo è:
-\begin{Command}
-[piccardi@selidor sources]$ ./forktest 3 > output
-[piccardi@selidor sources]$ cat output
-\end{Command}
-\begin{Terminal}
+\begin{Console}
+[piccardi@selidor sources]$ \textbf{./forktest 3 > output}
+[piccardi@selidor sources]$ \textbf{cat output}
Process 1967: forking 3 child
Child 1 successfully executing
Child 1, parent 1967, exiting
Go to next child
Spawned 3 child, pid 1970
Go to next child
-\end{Terminal}
+\end{Console}
che come si vede è completamente diverso da quanto ottenevamo sul terminale.
Il comportamento delle varie funzioni di interfaccia con i file è analizzato
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 è:
-\begin{Command}
-[piccardi@selidor sources]$ ./forktest -c2 3
-\end{Command}
-\begin{Terminal}[commandchars=\\\{\}]
+\begin{Console}
+[piccardi@selidor sources]$ \textbf{./forktest -c2 3}
Process 1972: forking 3 child
Spawned 1 child, pid 1973
Child 1 successfully executing
Spawned 3 child, pid 1975
Go to next child
-\textbf{[piccardi@selidor sources]$} Child 3, parent 1, exiting
+[piccardi@selidor sources]$ Child 3, parent 1, exiting
Child 2, parent 1, exiting
Child 1, parent 1, exiting
-\end{Terminal}
+\end{Console}
come si può notare in questo caso il processo padre si conclude prima dei
figli, tornando alla shell, che stampa il prompt sul terminale: circa due
secondi dopo viene stampato a video anche l'output dei tre figli che
sez.~\ref{sec:sess_job_control}), indicando al processo padre di aspettare 10
secondi prima di uscire. In questo caso, usando \cmd{ps} sullo stesso
terminale (prima dello scadere dei 10 secondi) otterremo:
-\begin{Command}
-[piccardi@selidor sources]$ ps T
-\end{Command}
-%$
-\begin{Terminal}
+\begin{Console}
+[piccardi@selidor sources]$ \textbf{ps T}
PID TTY STAT TIME COMMAND
419 pts/0 S 0:00 bash
568 pts/0 S 0:00 ./forktest -e10 3
570 pts/0 Z 0:00 [forktest <defunct>]
571 pts/0 Z 0:00 [forktest <defunct>]
572 pts/0 R 0:00 ps T
-\end{Terminal}
+\end{Console}
+%$
e come si vede, dato che non si è fatto nulla per riceverne lo stato di
terminazione, i tre processi figli sono ancora presenti pur essendosi
conclusi, con lo stato di \itindex{zombie} \textit{zombie} e l'indicazione che
famiglia di funzioni) che possono essere usate per questo compito, in realtà
(come mostrato in fig.~\ref{fig:proc_exec_relat}), tutte queste funzioni sono
tutte varianti che consentono di invocare in modi diversi, semplificando il
-passaggio degli argomenti, la \textit{system call} \funcd{execve}, il cui
+passaggio degli argomenti, la funzione di sistema \funcd{execve}, il cui
prototipo è:
\begin{funcproto}{
\end{Example}
dove l'interprete indicato deve essere un eseguibile binario e non un altro
script, che verrà chiamato come se si fosse eseguito il comando
-\cmd{interpreter [argomenti] filename}.\footnote{si tenga presente che con
- Linux quanto viene scritto come \texttt{argomenti} viene passato
- all'interprete come un unico argomento con una unica stringa di 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}, una comparazione dei vari comportamenti si trova su
+\cmd{interpreter [argomenti] filename}.
+
+Si tenga presente che con Linux quanto viene scritto come \texttt{argomenti}
+viene passato all'interprete come un unico argomento con una unica stringa di
+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/}.}
Con la famiglia delle \func{exec} si chiude il novero delle funzioni su cui è