\label{cha:file_advanced}
In questo capitolo affronteremo le tematiche relative alla gestione avanzata
-dei file, che non sono state trattate in \capref{cha:file_unix_interface},
-dove ci si è limitati ad una panoramica delle funzioni base. In particolare
-tratteremo delle funzioni di input/output avanzato e del \textit{file
- locking}.
+dei file. In particolare tratteremo delle funzioni di input/output avanzato,
+che permettono una gestione più sofisticata dell'I/O su file, a partire da
+quelle che permettono di gestire l'accesso contemporaneo a più file, per
+concludere con la gestione dell'I/O mappato in memoria. Dedicheremo poi la
+fine del capitolo alle problematiche del \textit{file locking}.
-\section{Le funzioni di I/O avanzato}
-\label{sec:file_advanced_io}
+\section{L'\textit{I/O multiplexing}}
+\label{sec:file_multiplexing}
-In questa sezione esamineremo le funzioni che permettono una gestione più
-sofisticata dell'I/O su file, a partire da quelle che permettono di gestire
-l'accesso contemporaneo a più file, per concludere con la gestione dell'I/O
-mappato in memoria.
+Uno dei problemi che si presentano quando si deve operare contemporaneamente
+su molti file usando le funzioni illustrate in
+\capref{cha:file_unix_interface} e \capref{cha:files_std_interface} è che si
+può essere bloccati nelle operazioni su un file mentre un altro potrebbe
+essere disponibile. L'\textit{I/O multiplexing} nasce risposta a questo
+problema. In questa sezione forniremo una introduzione a questa problematica
+ed analizzeremo le varie funzioni usate per implementare questa modalità di
+I/O.
-\subsection{La modalità di I/O \textsl{non-bloccante}}
+\subsection{La problematica dell'\textit{I/O multiplexing} e l'uso
+ dell'\textsl{I/O non-bloccante}}
\label{sec:file_noblocking}
Abbiamo visto in \secref{sec:sig_gen_beha}, affrontando la suddivisione fra
su cui si sta operando.
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 essi 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
-\textit{deadlock}\index{deadlock}.
+affrontare nelle operazioni di I/O, che si verifica quando si deve operare con
+più file descriptor eseguendo funzioni che possono bloccarsi senza che sia
+possibile prevedere quando questo può avvenire (il caso più classico è quello
+di un server in attesa di dati in ingresso da vari client). Quello che può
+accadere è di restare bloccati nell'eseguire una operazione su un file
+descriptor che non è ``\textsl{pronto}'', quando ce ne potrebbe essere
+un'altro disponibile. Questo comporta nel migliore dei casi una operazione
+ritardata inutilmente nell'attesa del completamento di quella bloccata, mentre
+nel peggiore dei casi (quando la conclusione della operazione bloccata dipende
+da quanto si otterrebbe dal file descriptor ``\textsl{disponibile}'') si
+potrebbe addirittura arrivare ad un \textit{deadlock}\index{deadlock}.
Abbiamo già accennato in \secref{sec:file_open} che è possibile prevenire
-questo tipo di comportamento aprendo un file in modalità
-\textsl{non-bloccante}, attraverso l'uso del flag \const{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 \errcode{EAGAIN}.
+questo tipo di comportamento delle funzioni di I/O aprendo un file in quella
+che viene chiamata \textsl{modalità non-bloccante}, attraverso l'uso del flag
+\const{O\_NONBLOCK} nella chiamata di \func{open}. In questo caso le funzioni
+di input/output eseguite sul file che si sarebbero bloccate, ritornano
+immediatamente, restituendo l'errore \errcode{EAGAIN}.
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}\index{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 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{L'I/O multiplexing}
-\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 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 è:
+call che nella gran parte dei casi falliranno.
+
+Per superare questo problema è stato introdotto il concetto di \textit{I/O
+ multiplexing}, una nuova modalità di operazioni che consenta di tenere sotto
+controllo più file descriptor in contemporanea, permettendo di bloccare un
+processo quando le operazioni volute non sono possibili, e di riprenderne
+l'esecuzione una volta che almeno una di quelle richieste sia disponibile, in
+modo da poterla eseguire con la sicurezza di non restare bloccati.
+
+Dato che, come abbiamo già accennato, per i normali file su disco non si ha
+mai un accesso bloccante, l'uso più comune delle funzioni che esamineremo nei
+prossimi paragrafi è per i server di rete, in cui esse vengono utilizzate per
+tenere sotto controllo dei socket; pertanto ritorneremo su di esse con
+ulteriori dettagli e qualche esempio in \secref{sec:TCP_sock_multiplexing}.
+
+
+\subsection{Le funzioni \func{select} e \func{pselect}}
+\label{sec:file_select}
+
+Il primo ad introdurre una interfaccia per l'\textit{I/O multiplexing} è stato
+BSD,\footnote{la funzione \func{select} è 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}
caso \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.
- \item[\errcode{EINVAL}] Si è specificato per \param{n} un valore negativo.
+ \item[\errcode{EINVAL}] Si è specificato per \param{n} un valore negativo o
+ un valore non valido per \param{timeout}.
\end{errlist}
ed inoltre \errval{ENOMEM}.
}
Per specificare quali file descriptor si intende \textsl{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
+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}
La funzione richiede di specificare tre insiemi distinti di file descriptor;
il primo, \param{readfds}, verrà osservato per rilevare la disponibilità di
-effettuare una lettura, il secondo, \param{writefds}, per verificare la
-possibilità effettuare una scrittura ed il terzo, \param{exceptfds}, per
-verificare l'esistenza di condizioni eccezionali (come i messaggi urgenti su
-un \textit{socket}\index{socket}, vedi \secref{sec:TCP_urgent_data}).
+effettuare una lettura,\footnote{per essere precisi la funzione ritornerà in
+ tutti i casi in cui la successiva esecuzione di \func{read} risulti non
+ bloccante, quindi anche in caso di \textit{end-of-file}.} il secondo,
+\param{writefds}, per verificare la possibilità effettuare una scrittura ed il
+terzo, \param{exceptfds}, per verificare l'esistenza di eccezioni (come i
+messaggi urgenti su un \textit{socket}\index{socket}, vedi
+\secref{sec:TCP_urgent_data}).
Dato che in genere non si tengono mai sotto controllo fino a
\const{FD\_SETSIZE} file contemporaneamente la funzione richiede di
essere arbitario si viene a creare una dipendenza del tutto artificiale dalle
dimensioni della struttura \type{fd\_set}, che può necessitare di essere
estesa, con ulteriori perdite di prestazioni.
-Per questo System V, invece di utilizzare l'interfaccia di \func{select}, che
-è una estensione creata nello sviluppo di BSD, ha introdotto una sua
-interfaccia per gestire l'\textit{I/O multiplexing}, basata sulla funzione
+
+Lo standard POSIX è rimasto a lungo senza primitive per l'\textit{I/O
+ multiplexing}, introdotto solo con le ultime revisioni dello standard (POSIX
+1003.1g-2000 e POSIX 1003.1-2001). La scelta è stata quella di seguire
+l'interfaccia creata da BSD, ma prevede che tutte le funzioni ad esso relative
+vengano dichiarate nell'header \file{sys/select.h}, che sostituisce i
+precedenti, ed inoltre aggiunge a \func{select} una nuova funzione
+\funcd{pselect},\footnote{il supporto per lo standard POSIX 1003.1-2001, ed
+ l'header \file{sys/select.h}, compaiono in Linux a partire dalle \acr{glibc}
+ 2.1. Le \acr{libc4} e \acr{libc5} non contengono questo header, le
+ \acr{glibc} 2.0 contengono una definizione sbagliata di \func{psignal},
+ senza l'argomento \param{sigmask}, la definizione corretta è presente dalle
+ \acr{glibc} 2.1-2.2.1 se si è definito \macro{\_GNU\_SOURCE} e nelle
+ \acr{glibc} 2.2.2-2.2.4 se si è definito \macro{\_XOPEN\_SOURCE} con valore
+ maggiore di 600.} il cui prototipo è:
+\begin{prototype}{sys/select.h}
+ {int pselect(int n, fd\_set *readfds, fd\_set *writefds, fd\_set *exceptfds,
+ struct timespec *timeout, sigset\_t *sigmask)}
+
+ Attende che uno dei file descriptor degli insiemi specificati diventi
+ attivo.
+
+ \bodydesc{La funzione in caso di successo restituisce il numero di file
+ descriptor (anche nullo) che sono attivi, e -1 in caso di errore, nel qual
+ caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EBADF}] Si è specificato un file descriptor sbagliato in uno
+ degli insiemi.
+ \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale.
+ \item[\errcode{EINVAL}] Si è specificato per \param{n} un valore negativo o
+ un valore non valido per \param{timeout}.
+ \end{errlist}
+ ed inoltre \errval{ENOMEM}.}
+\end{prototype}
+
+La funzione è sostanzialmente identica a \func{select}, solo che usa una
+struttura \struct{timespec} (vedi \figref{fig:sys_timeval_struct}) per
+indicare con maggiore precisione il timeout e non ne aggiorna il valore in
+caso di interruzione. Inoltre prende un argomento aggiuntivo \param{sigmask}
+che è il puntatore ad una maschera di segnali (si veda
+\secref{sec:sig_sigmask}). La maschera corrente viene sostituita da questa
+immediatamente prima di eseguire l'attesa, e ripristinata al ritorno della
+funzione.
+
+L'uso di \param{sigmask} è stato introdotto allo scopo di prevenire possibili
+race condition\index{race condition} quando ci si deve porre in attesa sia di
+un segnale che di dati.\footnote{in Linux però non è stata ancora introdotta
+ la relativa system call, pertanto la funzione è implementata nelle
+ \acr{glibc} attraverso \func{select} e la possibilità di race condition
+ permane.} La tecnica classica è quella di utilizzare il gestore per
+impostare una variabile globale e controllare questa nel corpo principale del
+programma; abbiamo visto in \secref{sec:sig_example} come questo lasci spazio
+a possibili race condition, per cui diventa essenziale utilizzare
+\func{sigprocmask} per disabilitare la ricezione del segnale prima di eseguire
+il controllo e riabilitarlo dopo l'esecuzione delle relative operazioni, onde
+evitare l'arrivo di un segnale immediatamente dopo il controllo, che andrebbe
+perso.
+
+Nel nostro caso il problema si pone quando oltre al segnale si devono tenere
+sotto controllo anche dei file descriptor con \func{select}, in questo caso si
+può fare conto sul fatto che all'arrivo di un segnale essa verrebbe interrotta
+e si potrebbero eseguire di conseguenza le operazioni relative al segnale e
+alla gestione dati con un ciclo del tipo:
+\includecodesnip{listati/select_race.c}
+qui però emerge una race condition, perché se il segnale arriva prima della
+chiamata a \func{select}, questa non verrà interrotta, e la ricezione del
+segnale non sarà rilevata.
+
+Per questo è stata introdotta \func{pselect}, che attraverso l'argomento
+\param{sigmask} permette di riabilitare la ricezione il segnale
+contestualmente all'esecuzione della funzione, e ribloccandolo non appena essa
+ritorna. In questo modo il precedente codice potrebbe essere essere modificato
+nel seguente modo:
+\includecodesnip{listati/pselect_norace.c}
+in questo caso utilizzando \var{oldmask} durante l'esecuzione di
+\func{pselect} la ricezione del segnale sarà abilitata, ed in caso di
+interruzione si potranno eseguire le relative operazioni.
+
+
+
+\subsection{La funzione \func{poll}}
+\label{sec:file_poll}
+
+System V, invece di utilizzare l'interfaccia di \func{select}, che è una
+estensione creata nello sviluppo di BSD, 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 è:
+ introdotta in Linux come system call a partire dal kernel 2.1.23 ed inserita
+ nelle \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 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:
+ \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.
\item[\errcode{EINTR}] La funzione è stata interrotta da un segnale.
+ \item[\errcode{EINVAL}] Il valore di \param{nfds} eccede il limite
+ \macro{RLIMIT\_NOFILE}.
\end{errlist}
ed inoltre \errval{EFAULT} e \errval{ENOMEM}.}
\end{prototype}
-La funzione tiene sotto controllo un numero \param{ndfs} di file descriptor
-specificati attraverso un vettore di puntatori a strutture \struct{pollfd}, la
-cui definizione è riportata in \figref{fig:file_pollfd}. Come \func{select}
-anche \func{poll} permette di interrompere l'attesa dopo un certo tempo, che
-va specificato attraverso \param{timeout} in numero di millisecondi (un valore
-negativo indica un'attesa indefinita).
+La funzione permette di tenere sotto controllo un certo numero \param{ndfs} di
+file descriptor, specificati attraverso un vettore di puntatori a strutture
+\struct{pollfd}. Come \func{select} anche \func{poll} permette di
+interrompere l'attesa dopo un certo tempo, che va specificato attraverso
+l'argomento \param{timeout} in numero di millisecondi: un valore negativo
+indica un'attesa indefinita mentre si può usare un valore nullo per eseguire
+la funzione in modalità \textsl{non-bloccante}.
\begin{figure}[!htb]
\footnotesize \centering
\end{figure}
Per ciascun file da controllare deve essere opportunamente predisposta una
-struttura \struct{pollfd}; nel campo \var{fd} deve essere specificato il file
-descriptor, mentre nel campo \var{events} il tipo di evento su cui si vuole
-attendere; quest'ultimo deve essere specificato come maschera binaria dei
-primi tre valori riportati in \tabref{tab:file_pollfd_flags} (gli altri
-vengono utilizzati solo per \var{revents} come valori in uscita).
+struttura \struct{pollfd}, la cui definizione è riportata in
+\figref{fig:file_pollfd}. La struttura prevede tre campi: il campo \var{fd}
+viene utilizzato per specificare il file descriptor relativo al file da
+controllare, mentre nel campo \var{events} deve essere specificata una
+maschera binaria data in ingresso che indichi il tipo di evento che si vuole
+controllare, il kernel restituirà il relativo risultato nel campo
+\var{revents}.
+
+Le costanti che definiscono i valori relativi ai bit usati nelle maschere
+binarie dei campi \var{events} e \var{revents} sono riportati in
+\tabref{tab:file_pollfd_flags}, insieme al loro significato. Le si sono
+suddivise in tre gruppi, nel primo gruppo si sono indicati i bit utilizzati
+per controllare l'attività in ingresso, nel secondo quelli per l'attività in
+uscita, mentre il terzo gruppo contiene dei valori che vengono utilizzati solo
+nel campo \var{revents} per notificare delle condizioni di errore.
\begin{table}[htb]
\centering
\textbf{Flag} & \textbf{Significato} \\
\hline
\hline
- \const{POLLIN} & È possibile la lettura immediata.\\
- \const{POLLPRI} & Sono presenti dati urgenti.\\
+ \const{POLLIN} & È possibile la lettura.\\
+ \const{POLLRDNORM}& Sono disponibili in lettura dati normali.\\
+ \const{POLLRDBAND}& Sono disponibili in lettura dati prioritari. \\
+ \const{POLLPRI} & È possibile la lettura di dati urgenti.\\
+ \hline
\const{POLLOUT} & È possibile la scrittura immediata.\\
+ \const{POLLWRNORM}& È possibile la scrittura di dati normali. \\
+ \const{POLLWRBAND}& È possibile la scrittura di dati prioritari. \\
\hline
\const{POLLERR} & C'è una condizione di errore.\\
\const{POLLHUP} & Si è verificato un hung-up.\\
\const{POLLNVAL} & Il file descriptor non è aperto.\\
\hline
- \const{POLLRDNORM}& Sono disponibili in lettura dati normali.\\
- \const{POLLRDBAND}& Sono disponibili in lettura dati ad alta
- priorità. \\
- \const{POLLWRNORM}& È possibile la scrittura di dati normali. \\
- \const{POLLWRBAND}& È possibile la scrittura di dati ad
- alta priorità. \\
- \const{POLLMSG} & Un segnale \const{SIGPOLL} è arrivato alla
- cima dello stream (non usato).\\
+ \const{POLLMSG} & Definito per compatobilità con SysV.\\
\hline
\end{tabular}
\caption{Costanti per l'identificazione dei vari bit dei campi
\label{tab:file_pollfd_flags}
\end{table}
-La funzione ritorna, restituendo il numero di file per i quali si è verificata
-una delle condizioni di attesa richieste od un errore. Lo stato dei file
-all'uscita della funzione viene restituito nel campo \var{revents} della
-relativa struttura \struct{pollfd}, che viene impostato alla maschera binaria
-dei valori riportati in \tabref{tab:file_pollfd_flags}, ed oltre alle tre
-condizioni specificate tramite \var{events} può riportare anche l'occorrere di
-una condizione di errore.
+Infine il valore \const{POLLMSG} non viene utilizzato ed è definito solo per
+compatibilità con l'implementazione di SysV, dove indica segnale
+\const{SIGPOLL} è arrivato alla cima dello \textit{stream}. Gli
+\textit{stream} sono una interfaccia specifica di SysV non presente in Linux,
+e non hanno nulla a che fare con i file \textit{stream} delle librerie
+standard del C, è da questi che derivano i nomi delle costanti, in quanto per
+essi sono definite tre classi di dati: \textsl{normali}, \textit{prioritari}
+ed \textit{urgenti}. Nel caso di Linux la distinzione ha senso solo nel caso
+per i dati \textit{out-of-band} dei socket (vedi
+\secref{sec:TCP_urgent_data}), ma su questo e su come \func{poll} reagisce
+alle varie condizioni dei socket torneremo in \secref{sec:TCP_serv_poll}, dove
+vedremo anche un esempio del suo utilizzo.
-Lo standard POSIX è rimasto a lungo senza primitive per l'\textit{I/O
- multiplexing}, introdotto solo con le ultime revisioni dello standard (POSIX
-1003.1g-2000 e POSIX 1003.1-2001). Esso prevede che tutte le funzioni ad esso
-relative vengano dichiarate nell'header \file{sys/select.h}, che sostituisce i
-precedenti, ed aggiunge a \func{select} una nuova funzione
-\funcd{pselect},\footnote{il supporto per lo standard POSIX 1003.1-2001, ed
- l'header \file{sys/select.h}, compaiono in Linux a partire dalle \acr{glibc}
- 2.1. Le \acr{libc4} e \acr{libc5} non contengono questo header, le
- \acr{glibc} 2.0 contengono una definizione sbagliata di \func{psignal},
- senza l'argomento \param{sigmask}, la definizione corretta è presente dalle
- \acr{glibc} 2.1-2.2.1 se si è definito \macro{\_GNU\_SOURCE} e nelle
- \acr{glibc} 2.2.2-2.2.4 se si è definito \macro{\_XOPEN\_SOURCE} con valore
- maggiore di 600.} il cui prototipo è:
-\begin{prototype}{sys/select.h}
- {int pselect(int n, fd\_set *readfds, fd\_set *writefds, fd\_set *exceptfds,
- struct timespec *timeout, sigset\_t *sigmask)}
-
- Attende che uno dei file descriptor degli insiemi specificati diventi
- attivo.
-
- \bodydesc{La funzione in caso di successo restituisce il numero di file
- descriptor (anche nullo) che sono attivi, e -1 in caso di errore, nel qual
- caso \var{errno} assumerà uno dei valori:
- \begin{errlist}
- \item[\errcode{EBADF}] Si è specificato un file descriptor sbagliato in uno
- degli insiemi.
- \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale.
- \item[\errcode{EINVAL}] Si è specificato per \param{n} un valore negativo.
- \end{errlist}
- ed inoltre \errval{ENOMEM}.}
-\end{prototype}
+In caso di successo funzione ritorna restituendo il numero di file (un valore
+positivo) per i quali si è verificata una delle condizioni di attesa richieste
+o per i quali si è verificato un errore (nel qual caso vengono utilizzati i
+valori di \tabref{tab:file_pollfd_flags} esclusivi di \var{revents}). Un
+valore nullo indica che si è raggiunto il timeout, mentre un valore negativo
+indica un errore nella chiamata, il cui codice viene riportato al solito
+tramite \var{errno}.
-La funzione è sostanzialmente identica a \func{select}, solo che usa una
-struttura \struct{timespec} per indicare con maggiore precisione il timeout e
-non ne aggiorna il valore in caso di interruzione, inoltre prende un argomento
-aggiuntivo \param{sigmask} che è il puntatore ad una maschera di segnali (si
-veda \secref{sec:sig_sigmask}). La maschera corrente viene sostituita da
-questa immediatamente prima di eseguire l'attesa, e ripristinata al ritorno
-della funzione.
-L'uso di \param{sigmask} è stato introdotto allo scopo di prevenire possibili
-race condition\footnote{in Linux però, non esistendo una system call apposita,
- la funzione è implementata nelle \acr{glibc} usando \func{select}, e la
- possibilità di una race condition\index{race condition} resta.} quando si
-deve eseguire un test su una variabile assegnata da un gestore sulla base
-dell'occorrenza di un segnale per decidere se lanciare \func{select}. Fra il
-test e l'esecuzione è presente una finestra in cui potrebbe arrivare il
-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'interfaccia di \textit{epoll}}
+%\label{sec:file_epoll}
+% placeholder ...
+
+
+
+
+\section{Altre modalità e funzioni di I/O avanzato}
+\label{sec:file_advanced_io}
+Benché l'\textit{I/O multiplexing} sia stata la prima, e sia tutt'ora una fra
+le più diffuse modalità di gestire l'I/O in situazioni complesse che
+coivolgono molti file, esistono altre modalità di gestione delle stesse
+problematiche, oltre che differenti interfacce per la gestione di altre
+problematiche avanzate riguardanti l'I/O su file, tratteremo tutto ciò in
+questa sezione.
\subsection{L'I/O asincrono}