Altre modifiche che mi ero dimenticato di buttar giu ieri
[gapil.git] / fileadv.tex
index 445d9c73fd613ef378ab181d1ed7924cc6d79a0e..f343a48fba02af45a22bec250db84cb6ed64b5c8 100644 (file)
 \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
@@ -40,45 +46,54 @@ lettura possono bloccarsi quando non ci sono dati disponibili sul descrittore
 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}
@@ -94,9 +109,10 @@ introdurre questa modalit
     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}.
 }
@@ -111,8 +127,8 @@ degli insiemi specificati (\param{readfds}, \param{writefds} e
 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}
@@ -146,10 +162,13 @@ 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
-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:xxx_urgent}).
+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
@@ -204,35 +223,122 @@ numero massimo di 1024 file descriptor per processo, adesso che il numero pu
 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
-\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 è:
+
+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}
+
+Nello sviluppo di System V, invece di utilizzare l'interfaccia di
+\func{select}, che è una estensione tipica di BSD, è stata introdotta un'altra
+interfaccia, 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 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 contemporaneamente \param{ndfs}
+file descriptor, specificati attraverso il puntatore \param{ufds} ad un
+vettore di strutture \struct{pollfd}.  Come con \func{select} si può
+interrompere l'attesa dopo un certo tempo, questo deve essere specificato con
+l'argomento \param{timeout} in numero di millisecondi: un valore negativo
+indica un'attesa indefinita, mentre un valore comporta il ritorno immediato (e
+può essere utilizzato per impiegare \func{poll} in modalità
+\textsl{non-bloccante}).
 
 \begin{figure}[!htb]
   \footnotesize \centering
@@ -245,12 +351,26 @@ negativo indica un'attesa indefinita).
   \label{fig:file_pollfd}
 \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).
+Per ciascun file da controllare deve essere inizializzata una struttura
+\struct{pollfd} nel vettore indicato dall'argomento \param{ufds}.  La
+struttura, la cui definizione è riportata in \figref{fig:file_pollfd}, prevede
+tre campi: in \var{fd} deve essere indicato il numero del file descriptor da
+controllare, in \var{events} deve essere specificata una maschera binaria di
+flag che indichino il tipo di evento che si vuole controllare, mentre in
+\var{revents} il kernel restituirà il relativo risultato.  Usando un valore
+negativo per \param{fd} la corrispondente struttura sarà ignorata da
+\func{poll}. Dato che i dati in ingresso sono del tutto indipendenti da quelli
+in uscita (che vengono restituiti in \var{revents}) non è necessario
+reinizializzare tutte le volte il valore delle strutture \struct{pollfd} a
+meno di non voler cambiare qualche condizione.
+
+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
@@ -260,22 +380,20 @@ vengono utilizzati solo per \var{revents} come valori in uscita).
     \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
@@ -283,86 +401,59 @@ vengono utilizzati solo per \var{revents} come valori in uscita).
   \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.
+Il valore \const{POLLMSG} non viene utilizzato ed è definito solo per
+compatibilità con l'implementazione di SysV che usa gli
+\textit{stream};\footnote{essi 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 di alcune
+costanti, in quanto per essi sono definite tre classi di dati:
+\textsl{normali}, \textit{prioritari} ed \textit{urgenti}.}  In Linux la
+distinzione ha senso solo 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. Si tenga conto comunque che le
+costanti relative ai diversi tipi di dati (come \macro{POLLRDNORM} e
+\macro{POLLRDBAND}) sono utilizzabili soltanto qualora si sia definito
+\macro{\_XOPEN\_SOURCE}.\footnote{e ci si ricordi di farlo sempre in testa al
+  file, definirla soltanto prima di includere \file{sys/poll.h} non è
+  sufficiente.}
+
+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}.
+
+
+%\subsection{L'interfaccia di \textit{epoll}}
+%\label{sec:file_epoll}
+% placeholder ...
+
+%da fare
+
+\section{Altre modalità e funzioni di I/O avanzato}
+\label{sec:file_advanced_io}
 
-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}
+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.
 
-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'I/O asincrono}
-\label{sec:file_asyncronous_io}
+\subsection{L'apertura asincrona dei file}
+\label{sec:file_asyncronous_open}
 
-Una modalità alternativa all'uso dell'\textit{I/O multiplexing} è quella di
-fare ricorso al cosiddetto \textsl{I/O asincrono}. Il concetto base
-dell'\textsl{I/O asincrono} è che le funzioni di I/O non attendono il
-completamento delle operazioni prima di ritornare, così che il processo non
-viene bloccato.  In questo modo diventa ad esempio possibile effettuare una
-richiesta preventiva di dati, in modo da poter effettuare in contemporanea le
-operazioni di calcolo e quelle di I/O.
+Una modalità alternativa all'uso dell'\textit{I/O multiplexing} per gestione
+dell'I/O simultaneo su molti file, è costituita dal cosiddetto \textsl{I/O
+  asincrono}. Il concetto base dell'\textsl{I/O asincrono} è che le funzioni
+di I/O non attendono il completamento delle operazioni prima di ritornare,
+così che il processo non viene bloccato.  In questo modo diventa ad esempio
+possibile effettuare una richiesta preventiva di dati, in modo da poter
+effettuare in contemporanea le operazioni di calcolo e quelle di I/O.
 
 Abbiamo accennato in \secref{sec:file_open} che è possibile, attraverso l'uso
 del flag \const{O\_ASYNC},\footnote{l'uso del flag di \const{O\_ASYNC} e dei
@@ -370,19 +461,23 @@ del flag \const{O\_ASYNC},\footnote{l'uso del flag di \const{O\_ASYNC} e dei
   di Linux e BSD.} aprire un file in modalità asincrona, così come è possibile
 attivare in un secondo tempo questa modalità impostando questo flag attraverso
 l'uso di \func{fcntl} con il comando \const{F\_SETFL} (vedi
-\secref{sec:file_fcntl}).
-
-In realtà in questo caso non si tratta di I/O asincrono vero e proprio, quanto
-di un meccanismo asincrono di notifica delle variazione dello stato del file
-descriptor; quello che succede è che il sistema genera un segnale (normalmente
-\const{SIGIO}, ma è possibile usarne altri) tutte le volte che diventa
-possibile leggere o scrivere dal file descriptor che si è posto in questa
-modalità. Si può inoltre selezionare, con il comando \const{F\_SETOWN} di
-\func{fcntl}, quale processo (o gruppo di processi) riceverà il segnale. 
+\secref{sec:file_fcntl}). 
+
+In realtà in questo caso non si tratta di I/O asincrono vero e proprio (che
+vedremo in \secref{sec:file_asyncronous_io}), quanto di un meccanismo
+asincrono di notifica delle variazione dello stato del file descriptor; quello
+che succede è che il sistema genera un segnale (normalmente \const{SIGIO}, ma
+è possibile usarne altri) tutte le volte che diventa possibile leggere o
+scrivere dal file descriptor che si è posto in questa modalità. Si può inoltre
+selezionare, con il comando \const{F\_SETOWN} di \func{fcntl}, quale processo
+(o gruppo di processi) riceverà il segnale. Se pertanto si effettuano le
+operazioni in risposta alla ricezione del segnale non ci sarà più la necessità
+di restare bloccati in attesa della disponibilità di accesso ai file.
 
 In questo modo si può evitare l'uso delle funzioni \func{poll} o \func{select}
 che, quando vengono usate con un numero molto grande di file descriptor, non
-hanno buone prestazioni. In tal caso infatti la maggior parte del loro tempo
+hanno buone prestazioni. % aggiungere cenno a epoll quando l'avrò scritta
+ In tal caso infatti la maggior parte del loro tempo
 di esecuzione è impegnato ad eseguire una scansione su tutti i file descriptor
 tenuti sotto controllo per determinare quali di essi (in genere una piccola
 percentuale) sono diventati attivi.
@@ -419,6 +514,9 @@ invier
 in eccesso, e si dovrà determinare al solito modo quali sono i file diventati
 attivi.
 
+\subsection{L'interfaccia POSIX per l'I/O asincrono}
+\label{sec:file_asyncronous_io}
+
 Benché la modalità di apertura asincrona di un file possa risultare utile in
 varie occasioni (in particolar modo con i socket\index{socket} e gli altri
 file per i quali le funzioni di I/O sono system call lente), essa è comunque
@@ -496,7 +594,7 @@ che serve a specificare il modo in cui si vuole che venga effettuata la
 notifica del completamento delle operazioni richieste. La struttura è
 riportata in \secref{fig:file_sigevent}; il campo \var{sigev\_notify} è quello
 che indica le modalità della notifica, esso può assumere i tre valori:
-\begin{basedescript}{\desclabelwidth{3.0cm}}
+\begin{basedescript}{\desclabelwidth{2.6cm}}
 \item[\const{SIGEV\_NONE}]  Non viene inviata nessuna notifica.
 \item[\const{SIGEV\_SIGNAL}] La notifica viene effettuata inviando al processo
   chiamante il segnale specificato da \var{sigev\_signo}; se il gestore di
@@ -1041,6 +1139,14 @@ l'emissione di un segnale di violazione di accesso (\const{SIGSEGV}), dato che
 i permessi sul segmento di memoria relativo non consentono questo tipo di
 accesso.
 
+\begin{figure}[!htb]
+  \centering
+  \includegraphics[width=10cm]{img/mmap_boundary}
+  \caption{Schema della mappatura in memoria di una sezione di file di
+    dimensioni non corrispondenti al bordo di una pagina.}
+  \label{fig:file_mmap_boundary}
+\end{figure}
+
 È invece assai diversa la questione relativa agli accessi al di fuori della
 regione di cui si è richiesta la mappatura. A prima vista infatti si potrebbe
 ritenere che anch'essi debbano generare un segnale di violazione di accesso;
@@ -1054,15 +1160,6 @@ file non rientra nei confini di una pagina: in tal caso verr
 mappato su un segmento di memoria che si estende fino al bordo della pagina
 successiva.
 
-\begin{figure}[htb]
-  \centering
-  \includegraphics[width=10cm]{img/mmap_boundary}
-  \caption{Schema della mappatura in memoria di una sezione di file di
-    dimensioni non corrispondenti al bordo di una pagina.}
-  \label{fig:file_mmap_boundary}
-\end{figure}
-
-
 In questo caso è possibile accedere a quella zona di memoria che eccede le
 dimensioni specificate da \param{lenght}, senza ottenere un \const{SIGSEGV}
 poiché essa è presente nello spazio di indirizzi del processo, anche se non è