Ancora pipe e correzioni per l'uso della macro Console.
authorSimone Piccardi <piccardi@gnulinux.it>
Wed, 1 May 2013 12:47:23 +0000 (12:47 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Wed, 1 May 2013 12:47:23 +0000 (12:47 +0000)
gapil.tex
ipc.tex
process.tex
prochand.tex

index 16626ef4e96a1189e20b3ddb3bfee1a404f31bd3..6f6bff9c3db116ef41dd8db3b8d43e65e48da402 100644 (file)
--- a/gapil.tex
+++ b/gapil.tex
@@ -60,6 +60,10 @@ inner=2.5cm,outer=1.8cm,bottom=3.3cm,top=2.3cm]{geometry}
 {xleftmargin=\parindent,xrightmargin=\parindent,fontseries=b,
 fontfamily=courier,fontsize=\footnotesize}
 
+\DefineVerbatimEnvironment{Console}{Verbatim}
+{commandchars=\\\{\},xleftmargin=\parindent,xrightmargin=\parindent,fontfamily=courier,fontsize=\footnotesize}
+
+
 \usepackage[bookmarks=true,plainpages=false,pdfpagelabels,
 hyperfootnotes=false]{hyperref}
 
diff --git a/ipc.tex b/ipc.tex
index 550b323eca806729ecb7c4dd869b433afc51fc64..45917ebbbcd0505757b571501488b615e99ab410 100644 (file)
--- a/ipc.tex
+++ b/ipc.tex
@@ -401,7 +401,7 @@ precedente: il programma mostrato in fig.~\ref{fig:ipc_barcodepage_code} per
 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.
@@ -495,32 +495,34 @@ create in precedenza.
 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à
@@ -529,56 +531,59 @@ successo solo quando anche l'altro capo è aperto, mentre l'apertura del capo
 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
index 0ad45f78eb246c474a3df77e8f770b1970cea91f..2376ec7d8617289e9c3d35f7a05d2d1faf4bec9a 100644 (file)
@@ -2698,30 +2698,26 @@ una variabile per poi ristamparne il contenuto leggendolo un byte alla volta.
 Il codice di detto programma, \file{endtest.c}, è nei sorgenti allegati,
 allora se lo eseguiamo su un normale PC compatibile, che è \textit{little
   endian} otterremo qualcosa del tipo:
-\begin{Command}
-[piccardi@gont sources]$ ./endtest
-\end{Command}
-%$
-\begin{Terminal}
+\begin{Console}
+[piccardi@gont sources]$ \textbf{./endtest}
 Using value ABCDEF01
 val[0]= 1
 val[1]=EF
 val[2]=CD
 val[3]=AB
-\end{Terminal}
+\end{Console}
+%$
 mentre su un vecchio Macintosh con PowerPC, che è \textit{big endian} avremo
 qualcosa del tipo:
-\begin{Command}
-piccardi@anarres:~/gapil/sources$ ./endtest
-\end{Command}
-%$
-\begin{Terminal}
+\begin{Console}
+piccardi@anarres:~/gapil/sources$ \textbf{./endtest}
 Using value ABCDEF01
 val[0]=AB
 val[1]=CD
 val[2]=EF
 val[3]= 1
-\end{Terminal}
+\end{Console}
+%$
 
 L'attenzione alla \textit{endianness} nella programmazione è importante, perché
 se si fanno assunzioni relative alla propria architettura non è detto che
index 5b063ee8d31c0bc7f63353ff8be0980198a31d7f..c7186d530391897d2d8b052d2d90a09ec37d9fd6 100644 (file)
@@ -80,10 +80,8 @@ posto.\footnote{la cosa si fa passando la riga \cmd{init=/bin/sh} come
 
 \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
@@ -115,7 +113,7 @@ init-+-keventd
      |-5*[getty]
      |-snort
      `-wwwoffled
-\end{Terminal}
+\end{Console}
 %$
   \caption{L'albero dei processi, così come riportato dal comando
     \cmd{pstree}.}
@@ -400,11 +398,8 @@ Se eseguiamo il comando, che è preceduto dall'istruzione \code{export
 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
@@ -418,7 +413,8 @@ Child 3 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
@@ -488,11 +484,9 @@ se buona parte dei concetti relativi ai file verranno trattati più avanti
 (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
@@ -515,7 +509,7 @@ Spawned 2 child, pid 1969
 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
@@ -782,10 +776,8 @@ 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 è:
-\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
@@ -797,10 +789,10 @@ Child 3 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
@@ -831,11 +823,8 @@ condizione: lanciamo il comando \cmd{forktest} in \textit{background} (vedi
 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
@@ -843,7 +832,8 @@ terminale (prima dello scadere dei 10 secondi) otterremo:
   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
@@ -1376,7 +1366,7 @@ 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 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}{ 
@@ -1665,14 +1655,16 @@ nella forma:
 \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 è