Correzioni varie e aggiunte sulle fifo
[gapil.git] / fileadv.tex
index 21dc922ac683c4fe499ff8d417a41bd0a91bb84c..b376483c6c301882c1bb1698522287ff365fa29e 100644 (file)
@@ -28,37 +28,124 @@ I/O possono bloccarsi indefinitamente.\footnote{si ricordi per
 esempio le operazioni di lettura possono bloccarsi quando non ci sono dati
 disponibili sul descrittore su cui si sta operando.
 
 esempio le operazioni di lettura possono bloccarsi quando non ci sono dati
 disponibili sul descrittore su cui si sta operando.
 
-Uno dei problemi più comuni che ci si trova ad affrontare, che non può essere
-risolto con le funzioni di base trattate in \capref{cha:file_unix_interface},
-è quello in cui si devono eseguire operazioni che possono bloccarsi su più
-file descriptor: il problema è che mentre si è bloccati su uno di questi file
-su di un'altro potrebbero essere presenti dei dati, così che nel migliore dei
-casi si avrebbe una lettura inutilmente ritardata, e nel peggiore si potrebbe
-addirittura arrivare ad un deadlock.
-
-Abbiamo già accennato in \secref{sec:file_open} che è possibile prevenire
+Questo comportamento causa uno dei problemi più comuni che ci si trova ad
+affrontare nelle operazioni di I/O, che è quello che si verifica quando si
+devono eseguire operazioni che possono bloccarsi su più file descriptor:
+mentre si è bloccati su uno di questi file su di un'altro potrebbero essere
+presenti dei dati, così che nel migliore dei casi si avrebbe una lettura
+ritardata inutilmente, e nel peggiore si potrebbe addirittura arrivare ad un
+deadlock.
+
+Abbiamo già accennato in \secref{sec:file_open} che però è possibile prevenire
 questo tipo di comportamento aprendo un file in modalità
 questo tipo di comportamento aprendo un file in modalità
-\textsl{non-bloccante}, specificando il flag \macro{O\_NONBLOCK} alla chiamata
-di \func{open}. In questo caso le funzioni di input/output che altrimenti si
-sarebbero bloccate ritornano immediatamente, restituendo l'errore
-\macro{EAGAIN}.
+\textsl{non-bloccante}, attraverso l'uso del flag \macro{O\_NONBLOCK} nella
+chiamata di \func{open}. In questo caso le funzioni di input/output che
+altrimenti si sarebbero bloccate ritornano immediatamente, restituendo
+l'errore \macro{EAGAIN}.
 
 
-L'utilizzo di questa modalità di I/O permette allora di risolvere il problema
+L'utilizzo di questa modalità di I/O permette di risolvere il problema
 controllando a turno i vari file descriptor, in un ciclo in cui si ripete
 l'accesso fintanto che esso non viene garantito.  Ovviamente questa tecnica,
 detta \textit{polling}, è estremamente inefficiente: si tiene costantemente
 impiegata la CPU solo per eseguire in continuazione delle system call che
 controllando a turno i vari file descriptor, in un ciclo in cui si ripete
 l'accesso fintanto che esso non viene garantito.  Ovviamente questa tecnica,
 detta \textit{polling}, è estremamente inefficiente: si tiene costantemente
 impiegata la CPU solo per eseguire in continuazione delle system call che
-nella gran parte dei casi falliranno.
-
-Per questo motivo, quando come vedremo in dettaglio in
-\secref{sec:file_multiplexing}, il sistema fornisce delle funzioni apposite
-che permettono di aggirare questo problema, permettendo di attendere fino alla
-disponibilità di un accesso; per poterle usare però è comunque comunque
-necessario utilizzare la modalità di I/O non bloccante all'apertura del file.
+nella gran parte dei casi falliranno. Per evitare questo, come vedremo in
+\secref{sec:file_multiplexing}, è stata introdotta una nuova interfaccia di
+programmazione, che comporta comunque l'uso della modalità di I/O non
+bloccante.
 
 \subsection{Le funzioni \func{poll} e \func{select}}
 \label{sec:file_multiplexing}
 
 
 \subsection{Le funzioni \func{poll} e \func{select}}
 \label{sec:file_multiplexing}
 
+Per superare il problema di dover usare il \textit{polling} controllare la
+disponibilità di accesso ad 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 fino a che l'accesso diventi possibile; il primo
+ad introdurre questa nuova interfaccia, chiamata usualmente \textit{I/O
+  multiplexing}, è stato BSD, con l'introduzione della funzione \func{select},
+il cui prototipo è:
+\begin{prototype}{sys/select.h}
+  {int select(int n, fd\_set *readfds, fd\_set *writefds, fd\_set *exceptfds,
+    struct timeval *timeout)}
+
+Attende che un certo insieme di file descriptor cambi stato.
+  
+\bodydesc{La funzione restituisce il numero di file descriptor, anche nullo,
+  che hanno cambiato stato in caso di successo e -1 in caso di errore, nel
+  qual caso \var{errno} viene settata ai valori:
+  \begin{errlist}
+  \item[\macro{EBADF}] Si è specificato un file descriptor sbagliato in uno
+  degli insiemi.
+  \item[\macro{EINTR}] La funzione è stata interrotta da un segnale.
+  \item[\macro{EINVAL}] Si è specificato per \param{n} un valore negativo.
+  \end{errlist}
+  ed inoltre \macro{ENOMEM}.
+}
+\end{prototype}
+
+La funzione mette il processo in stato di \textit{sleep} (vedi
+\tabref{tab:proc_proc_states}) fintanto che non viene rilevate dell'attività
+sull'insieme dei file descriptor specificati (\param{readfds},
+\param{writefds} e \param{exceptfds}), per un tempo massimo specificato da
+\param{timeout}. 
+
+Per specificare quali file descriptor si intende selezionare, la funzione usa
+un particolare oggetto, il \textit{file descriptor set}, identificato dal tipo
+\type{fd\_set}, che serve ad identificare un insieme di file descriptor, in
+maniera analoga a come un \textit{signal set} (vedi \secref{sec:sig_sigset})
+identifica un insieme di segnali. Per la manipolazione di questi \textit{file
+  descriptor set} si possono usare delle opportune macro di preprocessore:
+\begin{functions}
+  \headdecl{sys/select.h}
+  \funcdecl{FD\_ZERO(fd\_set *set)}
+  Inizializza l'insieme (vuoto).
+
+  \funcdecl{FD\_SET(int fd, fd\_set *set)}
+  Inserisce il file descriptor \param{fd} nell'insieme.
+
+  \funcdecl{FD\_CLR(int fd, fd\_set *set)}
+  Rimuove il file descriptor \param{fd} nell'insieme.
+  
+  \funcdecl{FD\_ISSET(int fd, fd\_set *set)}
+  Controlla se il file descriptor \param{fd} è nell'insieme.
+\end{functions}
+
+In genere un \textit{file descriptor set} può contenere fino ad un massimo di
+\macro{FD\_SETSIZE} file descriptor.  Questo a seconda del sistema può essere
+il limite del 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 quando,
+come nelle versioni più recenti del kernel, questo limite non c'è un massimo,
+esso indica le dimensioni in numero di bit utilizzabili per l'insieme.
+
+La funzione richiede di specificare tre insiemi distinti di file descriptor;
+il primo, \param{readfds}, verrà osservato per rilevare la disponibilità di
+input in lettura, il secondo, \param{writefds} per verificare la possibilità
+di scrivere ed il terzo, \param{exceptfds}, per verificare l'esistenza di
+eccezioni. I corrispondenti valori dei \textit{file descriptor set} saranno
+modificati di conseguenza per mostrare quale dei file descriptor ha cambiato
+stato.
+
+
+
+
+
+Come accennato l'interfaccia di \func{select} è una estensione aggiunta BSD, e
+poi entrata a far parte di POSIX; allo stesso tempo System V aveva introdotto
+una interfaccia alternativa, basata sulla funzione \func{poll}, 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}.
+  
+\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} viene settata ai valori:
+
+.}
+\end{prototype}
+
+
 
 
 \subsection{L'I/O asincrono}
 
 
 \subsection{L'I/O asincrono}
@@ -97,17 +184,18 @@ riporta il file descriptor che ha generato il segnale.
 \section{Il file locking}
 \label{sec:file_locking}
 
 \section{Il file locking}
 \label{sec:file_locking}
 
-In \secref{sec:file_sharing} abbiamo preso in esame le mosalità in cui un
+In \secref{sec:file_sharing} abbiamo preso in esame le modalità in cui un
 sistema unix-like gestisce la condivisione dei file da parte di processi
 diversi. In quell'occasione si è visto come, con l'eccezione dei file aperti
 in \textit{append mode}, quando più processi scrivono contemporaneamente sullo
 stesso file non è possibile determinare la sequenza in cui essi opereranno.
 
 sistema unix-like gestisce la condivisione dei file da parte di processi
 diversi. In quell'occasione si è visto come, con l'eccezione dei file aperti
 in \textit{append mode}, quando più processi scrivono contemporaneamente sullo
 stesso file non è possibile determinare la sequenza in cui essi opereranno.
 
-Questo causa la possibilità di race condition; in generale le situazioni più
-comuni sono due: l'interazione fra un processo che scrive e altri che leggono,
-in cui questi ultimi possono leggere informazioni scritte solo in maniera
-parziale o incompleta; o quella in cui diversi processi scrivono, mescolando
-in maniera imprevedebile il loro output sul file.
+Questo causa la possibilità di race condition\index{race condition}; in
+generale le situazioni più comuni sono due: l'interazione fra un processo che
+scrive e altri che leggono, in cui questi ultimi possono leggere informazioni
+scritte solo in maniera parziale o incompleta; o quella in cui diversi
+processi scrivono, mescolando in maniera imprevedibile il loro output sul
+file.
 
 In tutti questi casi il \textit{file locking} è la tecnica che permette di
 evitare le race condition, attraverso una serie di funzioni che permettono di
 
 In tutti questi casi il \textit{file locking} è la tecnica che permette di
 evitare le race condition, attraverso una serie di funzioni che permettono di