Materiale dimenticato e la versione preliminare del server echo implementato
[gapil.git] / fileadv.tex
index 4415602bcce799513de037ee02f7867f09dfc093..a4f8229095c3ccb4dc5ab7a272330072dca3c446 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
@@ -162,20 +181,21 @@ deve corrispondere al valore massimo aumentato di uno.\footnote{i file
   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{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
-insiemi viene sovrascritto per indicare quale file descriptor è pronto per le
-operazioni ad esso relative, in modo da poterlo controllare con la macro
-\const{FD\_ISSET}. In caso di errore la funzione restituisce -1 e gli insiemi
-non vengono toccati.
+Infine l'argomento \param{timeout}, specifica un tempo massimo di attesa 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 numero di file descriptor pronti,\footnote{questo è
+  il comportamento previsto dallo standard, ma la standardizzazione della
+  funzione è recente, ed esistono ancora alcune versioni di Unix che non si
+  comportano in questo modo.}  e ciascun insieme viene sovrascritto per
+indicare i file descriptor pronti per le operazioni ad esso relative, in modo
+da poterli controllare con \const{FD\_ISSET}.  Se invece si ha un timeout
+viene restituito un valore nullo e gli insiemi non vengono modificati.  In
+caso di errore la funzione restituisce -1, ed i valori dei tre insiemi sono
+indefiniti e non si può fare nessun affidamento sul loro contenuto.
 
 In Linux \func{select} modifica anche il valore di \param{timeout},
 impostandolo al tempo restante in caso di interruzione prematura; questo è
@@ -189,35 +209,135 @@ rimanente.\footnote{questo pu
   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 è:
+Uno dei problemi che si presentano con l'uso di \func{select} è che il suo
+comportamento dipende dal valore del file descriptor che si vuole tenere sotto
+controllo.  Infatti il kernel riceve con \param{n} un valore massimo per tale
+valore, e per capire quali sono i file descriptor da tenere sotto controllo
+dovrà effettuare una scansione su tutto l'intervallo, che può anche essere
+anche molto ampio anche se i file descriptor sono solo poche unità; tutto ciò
+ha ovviamente delle conseguenze ampiamente negative per le prestazioni.
+
+Inoltre c'è anche il problema che il numero massimo dei file che si possono
+tenere sotto controllo, la funzione è nata quando il kernel consentiva un
+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. 
+
+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 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
@@ -231,36 +351,45 @@ negativo indica un'attesa indefinita).
 \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}.  Usando un valore negativo per \param{fd} la corrispondente
+struttura sarà ignorata da \func{poll}.
+
+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
   \footnotesize
-  \begin{tabular}[c]{|l|c|l|}
+  \begin{tabular}[c]{|l|l|}
+    \hline
+    \textbf{Flag}  & \textbf{Significato} \\
     \hline
-    \textbf{Flag} & \textbf{Valore} & \textbf{Significato} \\
     \hline
+    \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{POLLIN}    & 0x001 & È possibile la lettura immediata.\\
-    \const{POLLPRI}   & 0x002 & Sono presenti dati urgenti.\\
-    \const{POLLOUT}   & 0x004 & È possibile la scrittura immediata.\\
+    \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}   & 0x008 & C'è una condizione di errore.\\
-    \const{POLLHUP}   & 0x010 & Si è verificato un hung-up.\\
-    \const{POLLNVAL}  & 0x020 & Il file descriptor non è aperto.\\
+    \const{POLLERR}   & C'è una condizione di errore.\\
+    \const{POLLHUP}   & Si è verificato un hung-up.\\
+    \const{POLLNVAL}  & Il file descriptor non è aperto.\\
     \hline
-    \const{POLLRDNORM}& 0x040 & Sono disponibili in lettura dati normali.\\ 
-    \const{POLLRDBAND}& 0x080 & Sono disponibili in lettura dati ad alta 
-                                priorità. \\
-    \const{POLLWRNORM}& 0x100 & È possibile la scrittura di dati normali.  \\ 
-    \const{POLLWRBAND}& 0x200 & È possibile la scrittura di dati ad 
-                                alta priorità. \\
-    \const{POLLMSG}   & 0x400 & Un segnale \const{SIGPOLL} è arrivato alla
-                                cima dello stream.\\
+    \const{POLLMSG}   & Definito per compatobilità con SysV.\\
     \hline    
   \end{tabular}
   \caption{Costanti per l'identificazione dei vari bit dei campi
@@ -268,76 +397,46 @@ 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.
+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}, che è stata introdotto 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}
 \label{sec:file_asyncronous_io}
 
@@ -415,15 +514,11 @@ rispetto a quelle usate normalmente.
 
 In generale questa interfaccia è completamente astratta e può essere
 implementata sia direttamente nel kernel, che in user space attraverso l'uso
-di thread. Al momento\footnote{fino ai kernel della serie 2.4.x, nella serie
-  2.5.x è però iniziato un lavoro completo di riscrittura di tutto il sistema
-  di I/O, che prevede anche l'introduzione di un nuovo layer per l'I/O
-  asincrono (effettuato a partire dal 2.5.32).} esiste una sola versione
-stabile di questa interfaccia, quella delle \acr{glibc}, che è realizzata
-completamente in user space, ed accessibile linkando i programmi con la
-libreria \file{librt}.  Esistono comunque vari progetti sperimentali (come il
-KAIO della SGI, o i patch di Benjamin La Haise) che prevedono un supporto
-diretto da parte del kernel.
+di thread. Al momento esiste una sola versione stabile di questa interfaccia,
+quella delle \acr{glibc}, che è realizzata completamente in user space, ed
+accessibile linkando i programmi con la libreria \file{librt}. Nei kernel
+della nuova serie è stato anche introdotta (a partire dal 2.5.32) un nuovo
+layer per l'I/O asincrono.
 
 Lo standard prevede che tutte le operazioni di I/O asincrono siano controllate
 attraverso l'uso di una apposita struttura \struct{aiocb} (il cui nome sta per
@@ -445,18 +540,17 @@ disponibilit
 \end{figure}
 
 Le operazioni di I/O asincrono possono essere effettuate solo su un file già
-aperto; il file deve inoltre supportare la funzione \func{lseek},
-pertanto terminali e pipe sono esclusi. Non c'è limite al numero di operazioni
-contemporanee effettuabili su un singolo file.
-
-Ogni operazione deve inizializzare opportunamente un \textit{control block}.
-Il file descriptor su cui operare deve essere specificato tramite il campo
-\var{aio\_fildes}; dato che più operazioni possono essere eseguita in maniera
-asincrona, il concetto di posizione corrente sul file viene a mancare;
-pertanto si deve sempre specificare nel campo \var{aio\_offset} la posizione
-sul file da cui i dati saranno letti o scritti.  Nel campo \var{aio\_buf} deve
-essere specificato l'indirizzo del buffer usato per l'I/O, ed in
-\var{aio\_nbytes} la lunghezza del blocco di dati da trasferire.
+aperto; il file deve inoltre supportare la funzione \func{lseek}, pertanto
+terminali e pipe sono esclusi. Non c'è limite al numero di operazioni
+contemporanee effettuabili su un singolo file.  Ogni operazione deve
+inizializzare opportunamente un \textit{control block}.  Il file descriptor su
+cui operare deve essere specificato tramite il campo \var{aio\_fildes}; dato
+che più operazioni possono essere eseguita in maniera asincrona, il concetto
+di posizione corrente sul file viene a mancare; pertanto si deve sempre
+specificare nel campo \var{aio\_offset} la posizione sul file da cui i dati
+saranno letti o scritti.  Nel campo \var{aio\_buf} deve essere specificato
+l'indirizzo del buffer usato per l'I/O, ed in \var{aio\_nbytes} la lunghezza
+del blocco di dati da trasferire.
 
 Il campo \var{aio\_reqprio} permette di impostare la priorità delle operazioni
 di I/O.\footnote{in generale perché ciò sia possibile occorre che la
@@ -464,13 +558,11 @@ di I/O.\footnote{in generale perch
   le macro \macro{\_POSIX\_PRIORITIZED\_IO}, e
   \macro{\_POSIX\_PRIORITY\_SCHEDULING}.} La priorità viene impostata a
 partire da quella del processo chiamante (vedi \secref{sec:proc_priority}),
-cui viene sottratto il valore di questo campo.
-
-Il campo \var{aio\_lio\_opcode} è usato soltanto dalla funzione
-\func{lio\_listio}, che, come vedremo più avanti, permette di eseguire con una
-sola chiamata una serie di operazioni, usando un vettore di \textit{control
-  block}. Tramite questo campo si specifica quale è la natura di ciascuna di
-esse.
+cui viene sottratto il valore di questo campo.  Il campo
+\var{aio\_lio\_opcode} è usato solo dalla funzione \func{lio\_listio}, che,
+come vedremo, permette di eseguire con una sola chiamata una serie di
+operazioni, usando un vettore di \textit{control block}. Tramite questo campo
+si specifica quale è la natura di ciascuna di esse.
 
 \begin{figure}[!htb]
   \footnotesize \centering
@@ -541,11 +633,11 @@ Si tenga inoltre presente che deallocare la memoria indirizzata da
 \param{aiocbp} o modificarne i valori prima della conclusione di una
 operazione può dar luogo a risultati impredicibili, perché l'accesso ai vari
 campi per eseguire l'operazione può avvenire in un momento qualsiasi dopo la
-richiesta.  Questo comporta che occorre evitare di usare per \param{aiocbp}
+richiesta.  Questo comporta che non si devono usare per \param{aiocbp}
 variabili automatiche e che non si deve riutilizzare la stessa struttura per
-un ulteriore operazione fintanto che la precedente non sia stata ultimata. In
-generale per ogni operazione di I/O asincrono si deve utilizzare una diversa
-struttura \struct{aiocb}.
+un'altra operazione fintanto che la precedente non sia stata ultimata. In
+generale per ogni operazione si deve utilizzare una diversa struttura
+\struct{aiocb}.
 
 Dato che si opera in modalità asincrona, il successo di \func{aio\_read} o
 \func{aio\_write} non implica che le operazioni siano state effettivamente
@@ -575,8 +667,8 @@ del caso, i codici di errore delle system call \func{read}, \func{write} e
 \func{fsync}.
 
 Una volta che si sia certi che le operazioni siano state concluse (cioè dopo
-che una chiamata ad \func{aio\_error} non ha restituito \errcode{EINPROGRESS},
-si potrà usare la seconda funzione dell'interfaccia, \funcd{aio\_return}, che
+che una chiamata ad \func{aio\_error} non ha restituito
+\errcode{EINPROGRESS}), si potrà usare la funzione \funcd{aio\_return}, che
 permette di verificare il completamento delle operazioni di I/O asincrono; il
 suo prototipo è:
 \begin{prototype}{aio.h}
@@ -603,7 +695,7 @@ asincrono non verrebbero liberate, rischiando di arrivare ad un loro
 esaurimento.
 
 Oltre alle operazioni di lettura e scrittura l'interfaccia POSIX.1b mette a
-disposizione un'altra operazione, quella di sincronizzazione dell'I/O, essa è
+disposizione un'altra operazione, quella di sincronizzazione dell'I/O,
 compiuta dalla funzione \func{aio\_fsync}, che ha lo stesso effetto della
 analoga \func{fsync}, ma viene eseguita in maniera asincrona; il suo prototipo
 è:
@@ -724,6 +816,9 @@ lettura o scrittura; il suo prototipo 
     \begin{errlist}
     \item[\errcode{EAGAIN}] Nessuna operazione è stata completata entro
       \param{timeout}.
+    \item[\errcode{EINVAL}] Si è passato un valore di \param{mode} non valido
+      o un numero di operazioni \param{nent} maggiore di
+      \const{AIO\_LISTIO\_MAX}.
     \item[\errcode{ENOSYS}] La funzione non è implementata.
     \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale.
     \end{errlist}
@@ -847,7 +942,7 @@ memoria, quanto di memoria mappata su file.
 
 \begin{figure}[htb]
   \centering
-  \includegraphics[width=9.5cm]{img/mmap_layout}
+  \includegraphics[width=7.cm]{img/mmap_layout}
   \caption{Disposizione della memoria di un processo quando si esegue la
   mappatura in memoria di un file.}
   \label{fig:file_mmap_layout}
@@ -866,13 +961,12 @@ virtuale, la sezione di memoria mappata su cui si opera sar
 o scritta sul file una pagina alla volta e solo per le parti effettivamente
 usate, il tutto in maniera completamente trasparente al processo; l'accesso
 alle pagine non ancora caricate avverrà allo stesso modo con cui vengono
-caricate in memoria le pagine che sono state salvate sullo swap.
-
-Infine in situazioni in cui la memoria è scarsa, le pagine che mappano un
-file vengono salvate automaticamente, così come le pagine dei programmi
-vengono scritte sulla swap; questo consente di accedere ai file su dimensioni
-il cui solo limite è quello dello spazio di indirizzi disponibile, e non della
-memoria su cui possono esserne lette delle porzioni.
+caricate in memoria le pagine che sono state salvate sullo swap.  Infine in
+situazioni in cui la memoria è scarsa, le pagine che mappano un file vengono
+salvate automaticamente, così come le pagine dei programmi vengono scritte
+sulla swap; questo consente di accedere ai file su dimensioni il cui solo
+limite è quello dello spazio di indirizzi disponibile, e non della memoria su
+cui possono esserne lette delle porzioni.
 
 L'interfaccia prevede varie funzioni per la gestione del \textit{memory mapped
   I/O}, la prima di queste è \funcd{mmap}, che serve ad eseguire la mappatura
@@ -893,12 +987,11 @@ in memoria di un file; il suo prototipo 
     \begin{errlist}
     \item[\errcode{EBADF}] Il file descriptor non è valido, e non si è usato
       \const{MAP\_ANONYMOUS}.
-    \item[\errcode{EACCES}] Il file descriptor non si riferisce ad un file
-      regolare, o si è richiesto \const{MAP\_PRIVATE} ma \param{fd} non è
-      aperto in lettura, o si è richiesto \const{MAP\_SHARED} e impostato
-      \const{PROT\_WRITE} ed \param{fd} non è aperto in lettura/scrittura, o
-      si è impostato \const{PROT\_WRITE} ed \param{fd} è in
-      \textit{append-only}.
+    \item[\errcode{EACCES}] o \param{fd} non si riferisce ad un file regolare,
+      o si è usato \const{MAP\_PRIVATE} ma \param{fd} non è aperto in lettura,
+      o si è usato \const{MAP\_SHARED} e impostato \const{PROT\_WRITE} ed
+      \param{fd} non è aperto in lettura/scrittura, o si è impostato
+      \const{PROT\_WRITE} ed \param{fd} è in \textit{append-only}.
     \item[\errcode{EINVAL}] I valori di \param{start}, \param{length} o
       \param{offset} non sono validi (o troppo grandi o non allineati sulla
       dimensione delle pagine).
@@ -1032,6 +1125,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;
@@ -1045,15 +1146,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 è
@@ -1068,7 +1160,7 @@ quella della mappatura in memoria.
 
 \begin{figure}[htb]
   \centering
-  \includegraphics[width=13cm]{img/mmap_exceed}
+  \includegraphics[width=10cm]{img/mmap_exceed}
   \caption{Schema della mappatura in memoria di file di dimensioni inferiori
     alla lunghezza richiesta.}
   \label{fig:file_mmap_exceed}
@@ -1257,10 +1349,11 @@ sistemi unix-like 
   mantenere il nome \textit{advisory locking}.} in quanto sono i singoli
 processi, e non il sistema, che si incaricano di asserire e verificare se
 esistono delle condizioni di blocco per l'accesso ai file.  Questo significa
-che le funzioni \func{read} o \func{write} non risentono affatto della
-presenza di un eventuale \textit{lock}, e che sta ai vari processi controllare
-esplicitamente lo stato dei file condivisi prima di accedervi, implementando
-un opportuno protocollo.
+che le funzioni \func{read} o \func{write} vengono eseguite comunque e non
+risentono affatto della presenza di un eventuale \textit{lock}; pertanto è
+sempre compito dei vari processi che intendono usare il file locking,
+controllare esplicitamente lo stato dei file condivisi prima di accedervi,
+utilizzando le relative funzioni.
 
 In generale si distinguono due tipologie di \textit{file lock}:\footnote{di
   seguito ci riferiremo sempre ai blocchi di accesso ai file con la
@@ -1269,17 +1362,17 @@ In generale si distinguono due tipologie di \textit{file lock}:\footnote{di
   processo (cioè la condizione in cui il processo viene posto in stato di
   \textit{sleep}).} la prima è il cosiddetto \textit{shared lock}, detto anche
 \textit{read lock} in quanto serve a bloccare l'accesso in scrittura su un
-file affinché non venga modificato mentre lo si legge. Si parla appunto di
-\textsl{blocco condiviso} in quanto più processi possono richiedere
-contemporaneamente uno \textit{shared lock} su un file per proteggere il loro
-accesso in lettura.
+file affinché il suo contenuto non venga modificato mentre lo si legge. Si
+parla appunto di \textsl{blocco condiviso} in quanto più processi possono
+richiedere contemporaneamente uno \textit{shared lock} su un file per
+proteggere il loro accesso in lettura.
 
 La seconda tipologia è il cosiddetto \textit{exclusive lock}, detto anche
 \textit{write lock} in quanto serve a bloccare l'accesso su un file (sia in
 lettura che in scrittura) da parte di altri processi mentre lo si sta
 scrivendo. Si parla di \textsl{blocco esclusivo} appunto perché un solo
 processo alla volta può richiedere un \textit{exclusive lock} su un file per
-proteggere il suo accesso in scrittura. 
+proteggere il suo accesso in scrittura.
 
 \begin{table}[htb]
   \centering
@@ -1313,12 +1406,17 @@ lettura) prima di eseguire l'accesso ad un file.  Se il lock viene acquisito
 il processo prosegue l'esecuzione, altrimenti (a meno di non aver richiesto un
 comportamento non bloccante) viene posto in stato di sleep. Una volta finite
 le operazioni sul file si deve provvedere a rimuovere il lock. La situazione
-delle varie possibilità è riassunta in \tabref{tab:file_file_lock}.
-
-Si tenga presente infine che il controllo di accesso è effettuato quando si
-apre un file, l'unico controllo residuo è che il tipo di lock che si vuole
-ottenere deve essere compatibile con le modalità di apertura dello stesso (di
-lettura per un read lock e di scrittura per un write lock).
+delle varie possibilità è riassunta in \tabref{tab:file_file_lock}, dove si
+sono riportati, per le varie tipologie di lock presenti su un file, il
+risultato che si ha in corrispondenza alle due tipologie di \textit{file lock}
+menzionate, nel successo della richiesta.
+
+Si tenga presente infine che il controllo di accesso e la gestione dei
+permessi viene effettuata quando si apre un file, l'unico controllo residuo
+che si può avere riguardo il \textit{file locking} è che il tipo di lock che
+si vuole ottenere su un file deve essere compatibile con le modalità di
+apertura dello stesso (in lettura per un read lock e in scrittura per un write
+lock).
 
 %%  Si ricordi che
 %% la condizione per acquisire uno \textit{shared lock} è che il file non abbia
@@ -1326,7 +1424,7 @@ lettura per un read lock e di scrittura per un write lock).
 %% \textit{exclusive lock} non deve essere presente nessun tipo di blocco.
 
 
-\subsection{La funzione \func{flock}}
+\subsection{La funzione \func{flock}} 
 \label{sec:file_flock}
 
 La prima interfaccia per il file locking, quella derivata da BSD, permette di
@@ -1401,7 +1499,7 @@ diversi che aprono lo stesso file.
 
 \begin{figure}[htb]
   \centering
-  \includegraphics[width=12.5cm]{img/file_flock}
+  \includegraphics[width=14cm]{img/file_flock}
   \caption{Schema dell'architettura del file locking, nel caso particolare  
     del suo utilizzo da parte dalla funzione \func{flock}.}
   \label{fig:file_flock_struct}
@@ -1528,14 +1626,6 @@ file; in questo modo 
 un certo punto fino alla fine del file, coprendo automaticamente quanto
 eventualmente aggiunto in coda allo stesso.
 
-Il tipo di file lock richiesto viene specificato dal campo \var{l\_type}, esso
-può assumere i tre valori definiti dalle costanti riportate in
-\tabref{tab:file_flock_type}, che permettono di richiedere rispettivamente uno
-\textit{shared lock}, un \textit{esclusive lock}, e la rimozione di un lock
-precedentemente acquisito. Infine il campo \var{l\_pid} viene usato solo in
-caso di lettura, quando si chiama \func{fcntl} con \const{F\_GETLK}, e riporta
-il \acr{pid} del processo che detiene il lock.
-
 \begin{table}[htb]
   \centering
   \footnotesize
@@ -1553,6 +1643,14 @@ il \acr{pid} del processo che detiene il lock.
   \label{tab:file_flock_type}
 \end{table}
 
+Il tipo di file lock richiesto viene specificato dal campo \var{l\_type}, esso
+può assumere i tre valori definiti dalle costanti riportate in
+\tabref{tab:file_flock_type}, che permettono di richiedere rispettivamente uno
+\textit{shared lock}, un \textit{esclusive lock}, e la rimozione di un lock
+precedentemente acquisito. Infine il campo \var{l\_pid} viene usato solo in
+caso di lettura, quando si chiama \func{fcntl} con \const{F\_GETLK}, e riporta
+il \acr{pid} del processo che detiene il lock.
+
 Oltre a quanto richiesto tramite i campi di \struct{flock}, l'operazione
 effettivamente svolta dalla funzione è stabilita dal valore dall'argomento
 \param{cmd} che, come già riportato in \secref{sec:file_fcntl}, specifica