X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=fileadv.tex;h=4415602bcce799513de037ee02f7867f09dfc093;hp=9c09c7ee38319591aa3eb6db6a0412e0eda33c7d;hb=c48d3a056c974898ca18c27a918f2296c18e2c6e;hpb=ab2e702bd899e2d99c70a90de1bb45ad62561e4e diff --git a/fileadv.tex b/fileadv.tex index 9c09c7e..4415602 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -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}