Iniziato a rivedere il multiplexing I/O.
[gapil.git] / fileadv.tex
index 9c09c7ee38319591aa3eb6db6a0412e0eda33c7d..4415602bcce799513de037ee02f7867f09dfc093 100644 (file)
@@ -70,15 +70,15 @@ I/O non bloccante.
 \label{sec:file_multiplexing}
 
 Per superare il problema di dover usare il \textit{polling}\index{polling} per
-controllare la possibilità di effettuare operazioni su un file aperto in
-modalità non bloccante, sia BSD che System V hanno introdotto delle nuove
-funzioni in grado di sospendere l'esecuzione di un processo in attesa che
-l'accesso diventi possibile.  Il primo ad introdurre questa modalità di
-operazione, chiamata usualmente \textit{I/O multiplexing}, è stato
-BSD,\footnote{la funzione è apparsa in BSD4.2 e standardizzata in BSD4.4, ma è
-  stata portata su tutti i sistemi che supportano i
-  \textit{socket}\index{socket}, compreso le varianti di System V.}  con la
-funzione \funcd{select}, il cui prototipo è:
+controllare la possibilità di effettuare operazioni su un gruppo di file
+aperti in modalità non bloccante, sia BSD che System V hanno introdotto delle
+nuove funzioni in grado di sospendere l'esecuzione di un processo fin quando
+l'accesso ad un dato insieme di file diventi possibile.  Il primo ad
+introdurre questa modalità di operazione, chiamata usualmente \textit{I/O
+  multiplexing}, è stato BSD,\footnote{la funzione è apparsa in BSD4.2 e
+  standardizzata in BSD4.4, ma è stata portata su tutti i sistemi che
+  supportano i \textit{socket}\index{socket}, compreso le varianti di System
+  V.}  con la funzione \funcd{select}, il cui prototipo è:
 \begin{functions}
   \headdecl{sys/time.h}
   \headdecl{sys/types.h}
@@ -135,10 +135,14 @@ opportune macro di preprocessore:
 In genere un \textit{file descriptor set} può contenere fino ad un massimo di
 \const{FD\_SETSIZE} file descriptor.  Questo valore in origine corrispondeva
 al limite per il numero massimo di file aperti\footnote{ad esempio in Linux,
-  fino alla serie 2.0.x, c'era un limite di 256 file per processo.}, ma
+  fino alla serie 2.0.x, c'era un limite di 256 file per processo.}, ma da
 quando, come nelle versioni più recenti del kernel, non c'è più un limite
 massimo, esso indica le dimensioni massime dei numeri usati nei \textit{file
-  descriptor set}.
+  descriptor set}.\footnote{il suo valore, secondo lo standard POSIX
+  1003.1-2001, è definito in \file{sys/select.h}, ed è pari a 1024.} Si tenga
+presente che i \textit{file descriptor set} devono sempre essere inizializzati
+con \macro{FD\_ZERO}; passare a \func{select} un valore non inizializzato può
+dar luogo a comportamenti non prevedibili.
 
 La funzione richiede di specificare tre insiemi distinti di file descriptor;
 il primo, \param{readfds}, verrà osservato per rilevare la disponibilità di
@@ -147,17 +151,24 @@ possibilit
 verificare l'esistenza di condizioni eccezionali (come i messaggi urgenti su
 un \textit{socket}\index{socket}, vedi \secref{sec:xxx_urgent}).
 
-La funzione inoltre richiede anche di specificare, tramite l'argomento
-\param{n}, un valore massimo del numero dei file descriptor usati
-nell'insieme; si può usare il già citato \const{FD\_SETSIZE}, oppure il numero
-più alto dei file descriptor usati nei tre insiemi, aumentato di uno.
+Dato che in genere non si tengono mai sotto controllo fino a
+\const{FD\_SETSIZE} file contemporaneamente la funzione richiede di
+specificare qual'è il numero massimo dei file descriptor indicati nei tre
+insiemi precedenti. Questo viene fatto per efficienza, per evitare di passare
+e far controllare al kernel una quantità di memoria superiore a quella
+necessaria. Questo limite viene indicato tramite l'argomento \param{n}, che
+deve corrispondere al valore massimo aumentato di uno.\footnote{i file
+  descriptor infatti sono contati a partire da zero, ed il valore indica il
+  numero di quelli da tenere sotto controllo; dimenticarsi di aumentare di uno
+  il valore di \param{n} è un errore comune.}
 
 Infine l'argomento \param{timeout}, specifica un tempo massimo di
-attesa\footnote{il tempo è valutato come \textit{elapsed time}.} prima che la
-funzione ritorni; se impostato a \val{NULL} la funzione attende
-indefinitamente. Si può specificare anche un tempo nullo (cioè una struttura
-\struct{timeval} con i campi impostati a zero), qualora si voglia
-semplicemente controllare lo stato corrente dei file descriptor.
+attesa\footnote{il tempo è valutato come \textit{clock time} (vedi
+  \secref{sec:sys_unix_time}).} prima che la funzione ritorni; se impostato a
+\val{NULL} la funzione attende indefinitamente. Si può specificare anche un
+tempo nullo (cioè una struttura \struct{timeval} con i campi impostati a
+zero), qualora si voglia semplicemente controllare lo stato corrente dei file
+descriptor.
 
 La funzione restituisce il totale dei file descriptor pronti nei tre insiemi,
 il valore zero indica sempre che si è raggiunto un timeout. Ciascuno dei tre
@@ -167,35 +178,35 @@ operazioni ad esso relative, in modo da poterlo controllare con la macro
 non vengono toccati.
 
 In Linux \func{select} modifica anche il valore di \param{timeout},
-impostandolo al tempo restante; questo è utile quando la funzione viene
-interrotta da un segnale, in tal caso infatti si ha un errore di
-\errcode{EINTR}, ed occorre rilanciare la funzione; in questo modo non è
-necessario ricalcolare tutte le volte il tempo rimanente.\footnote{questo può
-  causare problemi di portabilità sia quando si trasporta codice scritto su
-  Linux che legge questo valore, sia quando si usano programmi scritti per
-  altri sistemi che non dispongono di questa caratteristica e ricalcolano
-  \param{timeout} tutte le volte. In genere la caratteristica è disponibile
-  nei sistemi che derivano da System V e non disponibile per quelli che
-  derivano da BSD.}
-
-Come accennato l'interfaccia di \func{select} è una estensione di BSD; anche
-System V ha introdotto una sua interfaccia per gestire l'\textit{I/O
-  multiplexing}, basata sulla funzione \funcd{poll},\footnote{la funzione è
-  prevista dallo standard XPG4, ed è stata introdotta in Linux come system
-  call a partire dal kernel 2.1.23 e dalle \acr{libc} 5.4.28.} il cui
+impostandolo al tempo restante in caso di interruzione prematura; questo è
+utile quando la funzione viene interrotta da un segnale, in tal caso infatti
+si ha un errore di \errcode{EINTR}, ed occorre rilanciare la funzione; in
+questo modo non è necessario ricalcolare tutte le volte il tempo
+rimanente.\footnote{questo può causare problemi di portabilità sia quando si
+  trasporta codice scritto su Linux che legge questo valore, sia quando si
+  usano programmi scritti per altri sistemi che non dispongono di questa
+  caratteristica e ricalcolano \param{timeout} tutte le volte. In genere la
+  caratteristica è disponibile nei sistemi che derivano da System V e non
+  disponibile per quelli che derivano da BSD.}
+
+Come accennato l'interfaccia di \func{select} è una estensione creata nello
+sviluppo di BSD; anche System V ha introdotto una sua interfaccia per gestire
+l'\textit{I/O multiplexing}, basata sulla funzione \funcd{poll},\footnote{la
+  funzione è prevista dallo standard XPG4, ed è stata introdotta in Linux come
+  system call a partire dal kernel 2.1.23 e dalle \acr{libc} 5.4.28.} il cui
 prototipo è:
 \begin{prototype}{sys/poll.h}
   {int poll(struct pollfd *ufds, unsigned int nfds, int timeout)}
-
-La funzione attente un cambiamento di stato per uno dei file descriptor
-specificati da \param{ufds}.
+  
+  La funzione attende un cambiamento di stato per uno dei file descriptor
+  specificati da \param{ufds}.
   
 \bodydesc{La funzione restituisce il numero di file descriptor con attività in
   caso di successo, o 0 se c'è stato un timeout; in caso di errore viene
   restituito  -1 ed \var{errno} assumerà uno dei valori:
   \begin{errlist}
   \item[\errcode{EBADF}] Si è specificato un file descriptor sbagliato in uno
-  degli insiemi.
+    degli insiemi.
   \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale.
   \end{errlist}
   ed inoltre \errval{EFAULT} e \errval{ENOMEM}.}
@@ -248,7 +259,8 @@ vengono utilizzati solo per \var{revents} come valori in uscita).
     \const{POLLWRNORM}& 0x100 & È possibile la scrittura di dati normali.  \\ 
     \const{POLLWRBAND}& 0x200 & È possibile la scrittura di dati ad 
                                 alta priorità. \\
-    \const{POLLMSG}   & 0x400 & Estensione propria di Linux.\\
+    \const{POLLMSG}   & 0x400 & Un segnale \const{SIGPOLL} è arrivato alla
+                                cima dello stream.\\
     \hline    
   \end{tabular}
   \caption{Costanti per l'identificazione dei vari bit dei campi
@@ -315,6 +327,15 @@ segnale che non sarebbe rilevato; la race condition\index{race condition}
 diventa superabile disabilitando il segnale prima del test e riabilitandolo
 poi grazie all'uso di \param{sigmask}.
 
+Dato che l'I/O multiplexing serve a risolvere il problema di dover attendere
+la disponibilità di accesso ad un insieme di file, esso viene utilizzato
+prevalentemente per programmi in cui l'accesso ad un file descriptor può
+essere bloccante. Abbiamo già accennato come questo non avvenga mai per i
+normali file su disco; l'uso più comune di queste funzioni infatti è nei
+server di rete, in cui esse vengono utilizzate per tenere sotto controllo vari
+socket; pertanto ritorneremo su di esse con maggiori dettagli e con qualche
+esempio in \secref{sec:TCP_sock_multiplexing}.
+
 
 
 \subsection{L'I/O asincrono}