falliranno.
Per superare questo problema è stato introdotto il concetto di \textit{I/O
- multiplexing}, una nuova modalità di operazioni che consenta di tenere sotto
+ multiplexing}, una nuova modalità di operazioni che consente 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
+l'esecuzione una volta che almeno una di quelle richieste sia effettuabile, 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 sez.~\ref{sec:TCP_sock_multiplexing}.
+ulteriori dettagli e qualche esempio di utilizzo concreto in
+sez.~\ref{sec:TCP_sock_multiplexing}.
\subsection{Le funzioni \func{select} e \func{pselect}}
\headdecl{sys/time.h}
\headdecl{sys/types.h}
\headdecl{unistd.h}
- \funcdecl{int select(int n, fd\_set *readfds, fd\_set *writefds, fd\_set
+ \funcdecl{int select(int ndfs, fd\_set *readfds, fd\_set *writefds, fd\_set
*exceptfds, struct timeval *timeout)}
Attende che uno dei file descriptor degli insiemi specificati diventi
\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}.
+ \item[\errcode{EINVAL}] Si è specificato per \param{ndfs} un valore negativo
+ o un valore non valido per \param{timeout}.
\end{errlist}
ed inoltre \errval{ENOMEM}.
}
Inserisce il file descriptor \param{fd} nell'insieme.
\funcdecl{void \macro{FD\_CLR}(int fd, fd\_set *set)}
- Rimuove il file descriptor \param{fd} nell'insieme.
+ Rimuove il file descriptor \param{fd} dall'insieme.
\funcdecl{int \macro{FD\_ISSET}(int fd, fd\_set *set)}
Controlla se il file descriptor \param{fd} è nell'insieme.
1003.1-2001, è definito in \file{sys/select.h}, ed è pari a 1024.} Si tenga
presente che i \textit{file descriptor set} devono sempre essere inizializzati
con \macro{FD\_ZERO}; passare a \func{select} un valore non inizializzato può
-dar luogo a comportamenti non prevedibili.
+dar luogo a comportamenti non prevedibili; allo stesso modo usare
+\macro{FD\_SET} o \macro{FD\_CLR} con un file descriptor il cui valore eccede
+\const{FD\_SETSIZE} può dare luogo ad un comportamento indefinito.
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,\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,
+ bloccante, quindi anche in caso di \textit{end-of-file}; inoltre con Linux
+ possono verificarsi casi particolari, ad esempio quando arrivano dati su un
+ socket dalla rete che poi risultano corrotti e vengono scartati, può
+ accadere che \func{select} riporti il relativo file descriptor come
+ leggibile, ma una successiva \func{read} si blocchi.} il secondo,
\param{writefds}, per verificare la possibilità effettuare una scrittura ed il
terzo, \param{exceptfds}, per verificare l'esistenza di eccezioni (come i dati
urgenti \itindex{out-of-band} su un socket, vedi
Dato che in genere non si tengono mai sotto controllo fino a
\const{FD\_SETSIZE} file contemporaneamente la funzione richiede di
-specificare qual è il numero massimo dei file descriptor indicati nei tre
+specificare qual è il valore più alto fra i file descriptor indicati nei tre
insiemi precedenti. Questo viene fatto per efficienza, per evitare di passare
e far controllare al kernel una quantità di memoria superiore a quella
-necessaria. Questo limite viene indicato tramite l'argomento \param{n}, che
-deve corrispondere al valore massimo aumentato di uno.\footnote{i file
- descriptor infatti sono contati a partire da zero, ed il valore indica il
- numero di quelli da tenere sotto controllo; dimenticarsi di aumentare di uno
- il valore di \param{n} è un errore comune.} Infine l'argomento
-\param{timeout}, specifica un tempo massimo di attesa 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.
+necessaria. Questo limite viene indicato tramite l'argomento \param{ndfs}, che
+deve corrispondere al valore massimo aumentato di uno.\footnote{si ricordi che
+ i file descriptor sono numerati progressivamente a partire da zero, ed il
+ valore indica il numero più alto fra quelli da tenere sotto controllo;
+ dimenticarsi di aumentare di uno il valore di \param{ndfs} è un errore
+ comune.} 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
\itindend{file~descriptor~set}
+Una volta ritornata la funzione si potrà controllare quali sono i file
+descriptor pronti ed operare su di essi, si tenga presente però che si tratta
+solo di un suggerimento, esistono infatti condizioni\footnote{ad esempio
+ quando su un socket arrivano dei dati che poi vengono scartati perché
+ corrotti.} in cui \func{select} può riportare in maniera spuria che un file
+descriptor è pronto in lettura, quando una successiva lettura si bloccherebbe.
+Per questo quando si usa \textit{I/O multiplexing} è sempre raccomandato l'uso
+delle funzioni di lettura e scrittura in modalità non bloccante.
+
In Linux \func{select} modifica anche il valore di \param{timeout},
impostandolo al tempo restante in caso di interruzione prematura; questo è
utile quando la funzione viene interrotta da un segnale, in tal caso infatti
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ò
+controllo. Infatti il kernel riceve con \param{ndfs} un limite 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 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
\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}.
+ \item[\errcode{EINVAL}] Si è specificato per \param{ndfs} 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 fig.~\ref{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
-sez.~\ref{sec:sig_sigmask}). La maschera corrente viene sostituita da questa
+caso di interruzione.\footnote{in realtà la system call di Linux aggiorna il
+ valore al tempo rimanente, ma la funzione fornita dalle \acr{glibc} modifica
+ questo comportamento passando alla system call una variabile locale, in modo
+ da mantenere l'aderenza allo standard POSIX che richiede che il valore di
+ \param{timeout} non sia modificato.} Inoltre prende un argomento aggiuntivo
+\param{sigmask} che è il puntatore ad una maschera di segnali (si veda
+sez.~\ref{sec:sig_sigmask}). La maschera corrente viene sostituita da questa
immediatamente prima di eseguire l'attesa, e ripristinata al ritorno della
funzione.
Per questo è stata introdotta \func{pselect} che attraverso l'argomento
\param{sigmask} permette di riabilitare la ricezione il segnale
contestualmente all'esecuzione della funzione,\footnote{in Linux però, fino al
- kernel 2.6.16, non è presente la relativa system call, e la funzione è
+ kernel 2.6.16, non era presente la relativa system call, e la funzione era
implementata nelle \acr{glibc} attraverso \func{select} (vedi \texttt{man
select\_tut}) per cui la possibilità di \itindex{race~condition}
- \textit{race condition} permane; esiste però una soluzione, chiamata
- \itindex{self-pipe trick} \textit{self-pipe trick}, che consiste nell'aprire
- una pipe (vedi sez.~\ref{sec:ipc_pipes}) ed usare \func{select} sul capo in
- lettura della stessa, e indicare l'arrivo di un segnale scrivendo sul capo
- in scrittura all'interno del gestore dello stesso; in questo modo anche se
- il segnale va perso prima della chiamata di \func{select} questa lo
- riconoscerà comunque dalla presenza di dati sulla pipe.} ribloccandolo non
-appena essa ritorna, così che il precedente codice potrebbe essere riscritto
-nel seguente modo:
+ \textit{race condition} permaneva; in tale situazione si può ricorrere ad una
+ soluzione alternativa, chiamata \itindex{self-pipe trick} \textit{self-pipe
+ trick}, che consiste nell'aprire una pipe (vedi sez.~\ref{sec:ipc_pipes})
+ ed usare \func{select} sul capo in lettura della stessa; si può indicare
+ l'arrivo di un segnale scrivendo sul capo in scrittura all'interno del
+ gestore dello stesso; in questo modo anche se il segnale va perso prima
+ della chiamata di \func{select} questa lo riconoscerà comunque dalla
+ presenza di dati sulla pipe.} ribloccandolo non appena essa ritorna, così
+che il precedente codice potrebbe essere riscritto 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.
-% TODO pselect è stata introdotta nel kernel 2.6.16 (o 15 o 17?) insieme a
-% ppoll mettere e verificare, vedi articolo LWN http://lwn.net/Articles/176750/
-
-\subsection{La funzione \func{poll}}
+\subsection{Le funzioni \func{poll} e \func{ppoll}}
\label{sec:file_poll}
Nello sviluppo di System V, invece di utilizzare l'interfaccia di
immediato (e può essere utilizzato per impiegare \func{poll} in modalità
\textsl{non-bloccante}).
-\begin{figure}[!htb]
- \footnotesize \centering
- \begin{minipage}[c]{15cm}
- \includestruct{listati/pollfd.h}
- \end{minipage}
- \normalsize
- \caption{La struttura \structd{pollfd}, utilizzata per specificare le
- modalità di controllo di un file descriptor alla funzione \func{poll}.}
- \label{fig:file_pollfd}
-\end{figure}
-
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 fig.~\ref{fig:file_pollfd},
\var{revents}) non è necessario reinizializzare tutte le volte il valore delle
strutture \struct{pollfd} a meno di non voler cambiare qualche condizione.
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \includestruct{listati/pollfd.h}
+ \end{minipage}
+ \normalsize
+ \caption{La struttura \structd{pollfd}, utilizzata per specificare le
+ modalità di controllo di un file descriptor alla funzione \func{poll}.}
+ \label{fig:file_pollfd}
+\end{figure}
+
Le costanti che definiscono i valori relativi ai bit usati nelle maschere
binarie dei campi \var{events} e \var{revents} sono riportati in
tab.~\ref{tab:file_pollfd_flags}, insieme al loro significato. Le si sono
indica un errore nella chiamata, il cui codice viene riportato al solito
tramite \var{errno}.
+L'uso di \func{poll} consente di superare alcuni dei problemi illustrati in
+precedenza per \func{select}; anzitutto, dato che in questo caso si usa un
+vettore di strutture \struct{pollfd} di dimensione arbitraria, non esiste il
+limite introdotto dalle dimensioni massime di un \itindex{file~descriptor~set}
+\textit{file descriptor set} e la dimensione dei dati passati al kernel
+dipende solo dal numero dei file descriptor che si vogliono controllare, non
+dal loro valore.\footnote{anche se usando dei bit un \textit{file descriptor
+ set} può essere più efficiente di un vettore di strutture \struct{pollfd},
+ qualora si debba osservare un solo file descriptor con un valore molto alto
+ ci si troverà ad utilizzare inutilmente un maggiore quantitativo di
+ memoria.}
+
+Inoltre con \func{select} lo stesso \itindex{file~descriptor~set} \textit{file
+ descriptor set} è usato sia in ingresso che in uscita, e questo significa
+che tutte le volte che si vuole ripetere l'operazione occorre reinizializzarlo
+da capo. Questa operazione, che può essere molto onerosa se i file descriptor
+da tenere sotto osservazione sono molti, non è invece necessaria con
+\func{poll}.
+
+Abbiamo visto in sez.~\ref{sec:file_select} come lo standard POSIX preveda una
+variante di \func{select} che consente di gestire correttamente la ricezione
+dei segnali nell'attesa su un file descriptor. Con l'introduzione di una
+implementazione reale di \func{pselect} nel kernel 2.6.16, è stata aggiunta
+anche una analoga funzione che svolga lo stesso ruolo per \func{poll}.
+
+In questo caso si tratta di una estensione che è specifica di Linux e non è
+prevista da nessuno standard; essa può essere utilizzata esclusivamente se si
+definisce la macro \macro{\_GNU\_SOURCE} ed ovviamente non deve essere usata
+se si ha a cuore la portabilità. La funzione è \funcd{ppoll}, ed il suo
+prototipo è:
+\begin{prototype}{sys/poll.h}
+ {int ppoll(struct pollfd *fds, nfds\_t nfds, const struct timespec *timeout,
+ const sigset\_t *sigmask)}
+
+ La funzione attende un cambiamento di stato su un insieme di file
+ descriptor.
+
+ \bodydesc{La funzione restituisce il numero di file descriptor con attività
+ in caso di successo, o 0 se c'è stato un timeout e -1 in caso di errore,
+ ed in quest'ultimo 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}] Il valore di \param{nfds} eccede il limite
+ \macro{RLIMIT\_NOFILE}.
+ \end{errlist}
+ ed inoltre \errval{EFAULT} e \errval{ENOMEM}.}
+\end{prototype}
+
+La funzione ha lo stesso comportamento di \func{poll}, solo che si può
+specificare, con l'argomento \param{sigmask}, il puntatore ad una maschera di
+segnali; questa sarà la maschera utilizzata per tutto il tempo che la funzione
+resterà in attesa, all'uscita viene ripristinata la maschera originale. L'uso
+di questa funzione è cioè equivalente, come illustrato nella pagina di
+manuale, all'esecuzione atomica del seguente codice:
+\includecodesnip{listati/ppoll_means.c}
+
+Eccetto per \param{timeout}, che come per \func{pselect} deve essere un
+puntatore ad una struttura \struct{timespec}, gli altri argomenti comuni con
+\func{poll} hanno lo stesso significato, e la funzione restituisce gli stessi
+risultati illustrati in precedenza.
+
+
+\subsection{L'interfaccia di \textit{epoll}}
+\label{sec:file_epoll}
+
+\itindbeg{epoll}
+
+Nonostante \func{poll} presenti alcuni vantaggi rispetto a \func{select},
+anche questa funzione non è molto efficiente quando deve essere utilizzata con
+un gran numero di file descriptor,\footnote{in casi del genere \func{select}
+ viene scartata a priori, perché può avvenire che il numero di file
+ descriptor ecceda le dimensioni massime di un \itindex{file~descriptor~set}
+ \textit{file descriptor set}.} in particolare nel caso in cui solo pochi di
+questi diventano attivi. Il problema in questo caso è che il tempo impiegato
+da \func{poll} a trasferire i dati da e verso il kernel è proporzionale al
+numero di file descriptor osservati, non a quelli che presentano attività.
+
+Quando ci sono decine di migliaia di file descriptor osservati e migliaia di
+eventi al secondo,\footnote{il caso classico è quello di un server web di un
+ sito con molti accessi.} l'uso di \func{poll} comporta la necessità di
+trasferire avanti ed indietro da user space a kernel space la lunga lista
+delle strutture \struct{pollfd} migliaia di volte al secondo. A questo poi si
+aggiunge il fatto che la maggior parte del tempo di esecuzione sarà 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. In una situazione come questa l'uso delle funzioni classiche
+dell'interfaccia dell'\textit{I/O multiplexing} viene a costituire un collo di
+bottiglia che degrada irrimediabilmente le prestazioni.
+
+Per risolvere questo tipo di situazioni sono state ideate delle interfacce
+specialistiche\footnote{come \texttt{/dev/poll} in Solaris, o \texttt{kqueue}
+ in BSD.} il cui scopo fondamentale è quello di restituire solamente le
+informazioni relative ai file descriptor osservati che presentano una
+attività, evitando così le problematiche appena illustrate. In genere queste
+prevedono che si registrino una sola volta i file descriptor da tenere sotto
+osservazione, e forniscono un meccanismo che notifica quali di questi
+presentano attività.
+
+Le modalità con cui avviene la notifica sono due, la prima è quella classica
+(quella usata da \func{poll} e \func{select}) che viene chiamata \textit{level
+ triggered}.\footnote{la nomenclatura è stata introdotta da Jonathan Lemon in
+ un articolo su \texttt{kqueue} al BSDCON 2000, e deriva da quella usata
+ nell'elettronica digitale.} In questa modalità vengono notificati i file
+descriptor che sono \textsl{pronti} per l'operazione richiesta, e questo
+avviene indipendentemente dalle operazioni che possono essere state fatte su
+di essi a partire dalla precedente notifica. Per chiarire meglio il concetto
+ricorriamo ad un esempio: se su un file descriptor sono diventati disponibili
+in lettura 2000 byte ma dopo la notifica ne sono letti solo 1000 (ed è quindi
+possibile eseguire una ulteriore lettura dei restanti 1000), in modalità
+\textit{level triggered} questo sarà nuovamente notificato come
+\textsl{pronto}.
+
+La seconda modalità, è detta \textit{edge triggered}, e prevede che invece
+vengano notificati solo i file descriptor che hanno subito una transizione da
+\textsl{non pronti} a \textsl{pronti}. Questo significa che in modalità
+\textit{edge triggered} nel caso del precedente esempio il file descriptor
+diventato pronto da cui si sono letti solo 1000 byte non verrà nuovamente
+notificato come pronto, nonostante siano ancora disponibili in lettura 1000
+byte. Solo una volta che si saranno esauriti tutti i byte disponibili, e che
+il file descriptor sia tornato non essere pronto, si potrà ricevere una
+ulteriore notifica qualora ritornasse pronto.
+
+Nel caso di Linux al momento la sola interfaccia che fornisce questo tipo di
+servizio è \textit{epoll},\footnote{l'interfaccia è stata creata da Davide
+ Libenzi, ed è stata introdotta per la prima volta nel kernel 2.5.44, ma la
+ sua forma definitiva è stata raggiunta nel kernel 2.5.66.} anche se sono in
+discussione altre interfacce con le quali si potranno effettuare lo stesso
+tipo di operazioni;\footnote{al momento della stesura di queste note (Giugno
+ 2007) un'altra interfaccia proposta è quella di \textit{kevent}, che
+ fornisce un sistema di notifica di eventi generico in grado di fornire le
+ stesse funzionalità di \textit{epoll}, esiste però una forte discussione
+ intorno a tutto ciò e niente di definito.} \textit{epoll} è in grado di
+operare sia in modalità \textit{level triggered} che \textit{edge triggered}.
+
+La prima versione \textit{epoll} prevedeva l'apertura di uno speciale file di
+dispositivo, \texttt{/dev/epoll}, per ottenere un file descriptor da
+utilizzare con le funzioni dell'interfaccia,\footnote{il backporting
+ dell'interfaccia per il kernel 2.4, non ufficiale, utilizza sempre questo
+ file.} ma poi si è passati all'uso una apposita \textit{system call}. Il
+primo passo per usare l'interfaccia di \textit{epoll} è pertanto quello di
+chiamare la funzione \funcd{epoll\_create}, il cui prototipo è:
+\begin{prototype}{sys/epoll.h}
+ {int epoll\_create(int size)}
+
+ Apre un file descriptor per \textit{epoll}.
+
+ \bodydesc{La funzione restituisce un file descriptor in caso di successo, o
+ $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EINVAL}] si è specificato un valore di \param{size} non
+ positivo.
+ \item[\errcode{ENFILE}] si è raggiunto il massimo di file descriptor aperti
+ nel sistema.
+ \item[\errcode{ENOMEM}] non c'è sufficiente memoria nel kernel per creare
+ l'istanza.
+ \end{errlist}
+}
+\end{prototype}
+
+La funzione restituisce un file descriptor speciale, detto anche \textit{epoll
+ descriptor} che viene associato alla infrastruttura utilizzata dal kernel
+per gestire la notifica degli eventi; l'argomento \param{size} serve a dare
+l'indicazione del numero di file descriptor che si vorranno tenere sotto
+controllo, ma costituisce solo un suggerimento per semplificare l'allocazione
+di risorse sufficienti, non un valore massimo.
+
+Una volta ottenuto un file descriptor per \textit{epoll} il passo successivo è
+indicare quali file descriptor mettere sotto osservazione e quali operazioni
+controllare, per questo si deve usare la seconda funzione dell'interfaccia,
+\funcd{epoll\_ctl}, il cui prototipo è:
+\begin{prototype}{sys/epoll.h}
+ {int epoll\_ctl(int epfd, int op, int fd, struct epoll\_event *event)}
+
+ Esegue le operazioni di controllo di \textit{epoll}.
+
+ \bodydesc{La funzione restituisce $0$ in caso di successo o $-1$ in caso di
+ errore, nel qual caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EBADF}] il file descriptor \param{epfd} o \param{fd} non sono
+ validi.
+ \item[\errcode{EEXIST}] l'operazione richiesta è \const{EPOLL\_CTL\_ADD} ma
+ \param{fd} è già stato inserito in \param{epfd}.
+ \item[\errcode{EINVAL}] il file descriptor \param{epfd} non è stato ottenuto
+ con \func{epoll\_create}, o \param{fd} è lo stesso \param{epfd} o
+ l'operazione richiesta con \param{op} non è supportata.
+ \item[\errcode{ENOENT}] l'operazione richiesta è \const{EPOLL\_CTL\_MOD} o
+ \const{EPOLL\_CTL\_DEL} ma \param{fd} non è inserito in \param{epfd}.
+ \item[\errcode{ENOMEM}] non c'è sufficiente memoria nel kernel gestire
+ l'operazione richiesta.
+ \item[\errcode{EPERM}] il file \param{fd} non supporta \textit{epoll}.
+ \end{errlist}
+}
+\end{prototype}
+
+Il comportamento della funzione viene controllato dal valore dall'argomento
+\param{op} che consente di specificare quale operazione deve essere eseguita.
+Le costanti che definiscono i valori utilizzabili per l'argomento \param{op}
+sono riportate in tab.~\ref{tab:epoll_ctl_operation}, assieme al significato
+delle operazioni cui fanno riferimento.
+
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|p{8cm}|}
+ \hline
+ \textbf{Valore} & \textbf{Significato} \\
+ \hline
+ \hline
+ \const{EPOLL\_CTL\_ADD}& aggiunge un nuovo file descriptor da osservare
+ \param{fd} alla lista dei file descriptor
+ controllati tramite \param{epfd}, in
+ \param{event} devono essere specificate le
+ modalità di osservazione.\\
+ \const{EPOLL\_CTL\_MOD}& modifica le modalità di osservazione del file
+ descriptor \param{fd} secondo il contenuto di
+ \param{event}.\\
+ \const{EPOLL\_CTL\_DEL}& rimuove il file descriptor \param{fd} dalla lista
+ dei file controllati tramite \param{epfd}.\\
+ \hline
+ \end{tabular}
+ \caption{Valori dell'argomento \param{op} che consentono di scegliere quale
+ operazione di controllo effettuare con la funzione \func{epoll\_ctl}.}
+ \label{tab:epoll_ctl_operation}
+\end{table}
+
+La funzione prende sempre come primo argomento un file descriptor di
+\textit{epoll}, \param{epfd}, che deve essere stato ottenuto in precedenza con
+una chiamata a \func{epoll\_create}. L'argomento \param{fd} indica invece il
+file descriptor che si vuole tenere sotto controllo, quest'ultimo può essere
+un qualunque file descriptor utilizzabile con \func{poll}, ed anche un altro
+file descriptor di \textit{epoll}, ma non lo stesso \param{epfd}.
+
+L'ultimo argomento, \param{event}, deve essere un puntatore ad una struttura
+di tipo \struct{epoll\_event}, ed ha significato solo con le operazioni
+\const{EPOLL\_CTL\_MOD} e \const{EPOLL\_CTL\_ADD} per le quali serve ad
+indicare quale tipo di evento relativo ad \param{fd} si vuole che sia tenuto
+sotto controllo. L'argomento viene ignorato con
+\const{EPOLL\_CTL\_DEL}.\footnote{fino al kernel 2.6.9 era comunque richiesto
+ che questo fosse un puntatore valido, anche se poi veniva ignorato, a
+ partire dal 2.6.9 si può specificare anche anche un valore \texttt{NULL}.}
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \includestruct{listati/epoll_event.h}
+ \end{minipage}
+ \normalsize
+ \caption{La struttura \structd{epoll\_event}, che consente di specificare
+ gli eventi associati ad un file descriptor controllato con
+ \textit{epoll}.}
+ \label{fig:epoll_event}
+\end{figure}
+
+
+La struttura \struct{epoll\_event} è l'analoga di \struct{pollfd} e serve da
+una parte ad impostare quali eventi osservare, dall'altra a ricevere le
+notifiche degli eventi avvenuti. La sua definizione è riportata in
+fig.~\ref{fig:epoll_event}; il primo campo, \var{events}, è una maschera
+binaria in cui ciascun bit corrisponde o ad un tipo di evento, o una modalità
+di notifica. Detto campo deve essere specificato come OR aritmetico delle
+costanti riportate in tab.~\ref{tab:epoll_events}. Il secondo campo,
+\var{data}, serve ad indicare a quale file descriptor si intende fare
+riferimento, ed in astratto può contenere un valore qualsiasi che permetta di
+identificarlo, di norma comunque si usa come valore lo stesso \param{fd}.
+
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|p{8cm}|}
+ \hline
+ \textbf{Valore} & \textbf{Significato} \\
+ \hline
+ \hline
+ \const{EPOLLIN} & Il file è pronto per le operazioni di lettura
+ (analogo di \const{POLLIN}).\\
+ \const{EPOLLOUT} & Il file è pronto per le operazioni di scrittura
+ (analogo di \const{POLLOUT}).\\
+ \const{EPOLLRDHUP} & .\\
+ \const{EPOLLPRI} & Ci sono \itindex{out-of-band} dati urgenti
+ disponibili in lettura (analogo di
+ \const{POLLPRI}).\\
+ \const{EPOLLERR} & Si è verificata una condizione di errore
+ (analogo di \const{POLLERR}).\\
+ \const{EPOLLHUP} & Si è verificata una condizione di hung-up.\\
+ \const{EPOLLET} & .\\
+ \const{EPOLLONESHOT}& .\\
+ \hline
+ \end{tabular}
+ \caption{Valori del campo \param{events} di \struct{epoll\_event}.}
+ \label{tab:epoll_events}
+\end{table}
+
+
+
+
+
+
-% TODO accennare a ppoll
+La funzione che consente di attendere è \funcd{epoll\_wait}, il cui prototipo
+è:
+\begin{prototype}{sys/epoll.h}
+ {int epoll\_wait(int epfd, struct epoll\_event * events, int maxevents, int
+ timeout)}
+
+ Attende che uno dei file descriptor osservati sia pronto.
+
+ \bodydesc{La funzione restituisce il numero di file descriptor pronti in
+ caso di successo o $-1$ in caso di errore, nel qual caso \var{errno}
+ assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EBADF}] il file descriptor \param{epfd} non è valido.
+ \item[\errcode{EFAULT}] il puntatore \param{events} non è valido.
+ \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale prima
+ della scadenza di \param{timeout}.
+ \item[\errcode{EINVAL}] il file descriptor \param{epfd} non è stato ottenuto
+ con \func{epoll\_create}, o \param{fd} è lo stesso \param{epfd} o
+ l'operazione richiesta con \param{op} non è supportata.
+ \end{errlist}
+}
+\end{prototype}
-%\subsection{L'interfaccia di \textit{epoll}}
-%\label{sec:file_epoll}
-% placeholder ...
-% TODO epoll
+\itindend{epoll}
+% TODO epoll
+%
\section{L'accesso \textsl{asincrono} ai file}
\label{sec:file_asyncronous_access}
accesso ai file; per questo motivo Stevens chiama questa modalità
\textit{signal driven I/O}.
-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. % 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.
+Questa è un'altra modalità di gestione I/O, alternativa all'uso di
+\itindex{epoll} \textit{epoll}, che consente di evitare l'uso delle funzioni
+\func{poll} o \func{select} che, come illustrato in sez.~\ref{sec:file_epoll},
+quando vengono usate con un numero molto grande di file descriptor, non hanno
+buone prestazioni.
Tuttavia con l'implementazione classica dei segnali questa modalità di I/O
presenta notevoli problemi, dato che non è possibile determinare, quando i
segnale. Inoltre dato che i segnali normali non si accodano (si ricordi quanto
illustrato in sez.~\ref{sec:sig_notification}), in presenza di più file
descriptor attivi contemporaneamente, più segnali emessi nello stesso momento
-verrebbero notificati una volta sola. Linux però supporta le estensioni
-POSIX.1b dei segnali real-time, che vengono accodati e che permettono di
-riconoscere il file descriptor che li ha emessi. In questo caso infatti si può
-fare ricorso alle informazioni aggiuntive restituite attraverso la struttura
-\struct{siginfo\_t}, utilizzando la forma estesa \var{sa\_sigaction} del
-gestore installata con il flag \const{SA\_SIGINFO} (si riveda quanto
-illustrato in sez.~\ref{sec:sig_sigaction}).
+verrebbero notificati una volta sola.
+
+Linux però supporta le estensioni POSIX.1b dei segnali real-time, che vengono
+accodati e che permettono di riconoscere il file descriptor che li ha emessi.
+In questo caso infatti si può fare ricorso alle informazioni aggiuntive
+restituite attraverso la struttura \struct{siginfo\_t}, utilizzando la forma
+estesa \var{sa\_sigaction} del gestore installata con il flag
+\const{SA\_SIGINFO} (si riveda quanto illustrato in
+sez.~\ref{sec:sig_sigaction}).
Per far questo però occorre utilizzare le funzionalità dei segnali real-time
(vedi sez.~\ref{sec:sig_real_time}) impostando esplicitamente con il comando
anche questa funzionalità. In questo modo si può identificare immediatamente
un file su cui l'accesso è diventato possibile evitando completamente l'uso di
funzioni come \func{poll} e \func{select}, almeno fintanto che non si satura
-la coda. Se infatti si eccedono le dimensioni di quest'ultima, il kernel, non
-potendo più assicurare il comportamento corretto per un segnale real-time,
-invierà al suo posto un solo \const{SIGIO}, su cui si saranno accumulati tutti
-i segnali in eccesso, e si dovrà allora determinare con un ciclo quali sono i
-file diventati attivi.
+la coda.
+
+Se infatti si eccedono le dimensioni di quest'ultima, il kernel, non potendo
+più assicurare il comportamento corretto per un segnale real-time, invierà al
+suo posto un solo \const{SIGIO}, su cui si saranno accumulati tutti i segnali
+in eccesso, e si dovrà allora determinare con un ciclo quali sono i file
+diventati attivi.
% TODO fare esempio che usa O_ASYNC
Queste nuove funzionalità sono delle estensioni specifiche, non
standardizzate, che sono disponibili soltanto su Linux (anche se altri kernel
-supportano meccanismi simili). Esse sono realizzate, e solo a partire dalla
-versione 2.4 del kernel, attraverso l'uso di alcuni \textsl{comandi}
-aggiuntivi per la funzione \func{fcntl} (vedi sez.~\ref{sec:file_fcntl}), che
-divengono disponibili soltanto se si è definita la macro \macro{\_GNU\_SOURCE}
-prima di includere \file{fcntl.h}.
+supportano meccanismi simili). Alcune di esse sono realizzate, e solo a
+partire dalla versione 2.4 del kernel, attraverso l'uso di alcuni
+\textsl{comandi} aggiuntivi per la funzione \func{fcntl} (vedi
+sez.~\ref{sec:file_fcntl}), che divengono disponibili soltanto se si è
+definita la macro \macro{\_GNU\_SOURCE} prima di includere \file{fcntl.h}.
\index{file!lease|(}
può ottenere un \textit{lease} soltanto per un file appartenente ad un
\acr{uid} corrispondente a quello del processo. Soltanto un processo con
privilegi di amministratore (cioè con la \itindex{capabilities} capability
-\const{CAP\_LEASE}) può acquisire \textit{lease} su qualunque file.
+\const{CAP\_LEASE}, vedi sez.~\ref{sec:proc_capabilities}) può acquisire
+\textit{lease} su qualunque file.
Se su un file è presente un \textit{lease} quando il \textit{lease breaker}
esegue una \func{truncate} o una \func{open} che confligge con
Benché possa risultare utile per sincronizzare l'accesso ad uno stesso file da
parte di più processi, l'uso dei \textit{file lease} non consente comunque di
-risolvere il problema di rilevare automaticamente quando un file viene
-modificato, che è quanto necessario ad esempio ai programma di gestione dei
-file dei vari desktop grafici.
+risolvere il problema di rilevare automaticamente quando un file o una
+directory vengono modificati, che è quanto necessario ad esempio ai programma
+di gestione dei file dei vari desktop grafici.
Per risolvere questo problema è stata allora creata un'altra interfaccia,
chiamata \textit{dnotify}, che consente di richiedere una notifica quando una
directory, o di uno qualunque dei file in essa contenuti, viene modificato.
Come per i \textit{file lease} la notifica avviene di default attraverso il
-segnale \const{SIGIO}, ma questo può essere modificato e si può ottenere nel
-gestore il file descriptor che è stato modificato dal contenuto della
-struttura \struct{siginfo\_t}.
+segnale \const{SIGIO}, ma se ne può utilizzare un altro. Inoltre si potrà
+ottenere nel gestore del segnale il file descriptor che è stato modificato
+tramite il contenuto della struttura \struct{siginfo\_t}.
\index{file!lease|)}
-Ci si può registrare per le notifiche dei cambiamenti al contenuto di una
-certa directory eseguendo \func{fcntl} su un file descriptor \param{fd}
-associato alla stessa con il comando \const{F\_NOTIFY}. In questo caso
-l'argomento \param{arg} serve ad indicare per quali classi eventi si vuole
-ricevere la notifica, e prende come valore una maschera binaria composta
-dall'OR aritmetico di una o più delle costanti riportate in
-tab.~\ref{tab:file_notify}.
-
\begin{table}[htb]
\centering
\footnotesize
\label{tab:file_notify}
\end{table}
-A meno di non impostare in maniera esplicita una notifica permanente usando
-\const{DN\_MULTISHOT}, la notifica è singola: viene cioè inviata una sola
-volta quando si verifica uno qualunque fra gli eventi per i quali la si è
-richiesta. Questo significa che un programma deve registrarsi un'altra volta se
-desidera essere notificato di ulteriori cambiamenti. Se si eseguono diverse
+Ci si può registrare per le notifiche dei cambiamenti al contenuto di una
+certa directory eseguendo la funzione \func{fcntl} su un file descriptor
+associato alla stessa con il comando \const{F\_NOTIFY}. In questo caso
+l'argomento \param{arg} di \func{fcntl} serve ad indicare per quali classi
+eventi si vuole ricevere la notifica, e prende come valore una maschera
+binaria composta dall'OR aritmetico di una o più delle costanti riportate in
+tab.~\ref{tab:file_notify}.
+
+A meno di non impostare in maniera esplicita una notifica permanente usando il
+valore \const{DN\_MULTISHOT}, la notifica è singola: viene cioè inviata una
+sola volta quando si verifica uno qualunque fra gli eventi per i quali la si è
+richiesta. Questo significa che un programma deve registrarsi un'altra volta
+se desidera essere notificato di ulteriori cambiamenti. Se si eseguono diverse
chiamate con \const{F\_NOTIFY} e con valori diversi per \param{arg} questi
ultimi si \textsl{accumulano}; cioè eventuali nuovi classi di eventi
specificate in chiamate successive vengono aggiunte a quelle già impostate
nelle precedenti. Se si vuole rimuovere la notifica si deve invece
specificare un valore nullo.
+
+\index{file!inotify|(}
+
+Il maggiore problema di \textit{dnotify} è quello della scalabilità: si deve
+usare un file descriptor per ciascuna directory che si vuole tenere sotto
+controllo, il che porta facilmente ad un eccesso di file aperti. Inoltre
+quando la directory è su un dispositivo rimovibile, mantenere un file
+descriptor aperto comporta l'impossibilità di smontare il dispositivo e
+rimuoverlo, complicando la gestione.
+
+Un secondo problema è che l'interfaccia consente solo di tenere sotto
+controllo il contenuto di una directory; la modifica di un file viene
+segnalata, ma poi devo verificare quale è. Infine l'uso dei segnali come
+interfaccia di notifica comporta tutti i problemi di gestione visti in
+sez.~\ref{sec:sig_management} e sez.~\ref{sec:sig_control}, e per questo in
+generale quella di \textit{dnotify} viene considerata una interfaccia di
+usabilità problematica.
+
\index{file!dnotify|)}
+Per questa serie di motivi, a partire dal kernel 2.6.13, è stata introdotta
+una nuova interfaccia per l'osservazione delle modifiche a file o directory,
+chiamata \textit{inotify}.\footnote{le corrispondenti funzioni di interfaccia
+ sono state introdotte nelle glibc 2.4.} Questa è una interfaccia specifica
+di Linux (pertanto non deve essere usata se si devono scrivere programmi
+portabili), ed è basata sull'uso di una coda di notifica degli eventi
+associata ad un singolo file descriptor, risolvendo così il principale
+problema di \itindex{dnotify} \textit{dnotify}. La coda viene creata
+attraverso la funzione \funcd{inotify\_init}, il cui prototipo è:
+\begin{prototype}{sys/inotify.h}
+ {int inotify\_init(void)}
+
+ Inizializza una istanza di \textit{inotify}.
+
+ \bodydesc{La funzione restituisce un file descriptor in caso di successo, o
+ $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EMFILE}] si è raggiunto il numero massimo di istanze di
+ \textit{inotify} consentite all'utente.
+ \item[\errcode{ENFILE}] si è raggiunto il massimo di file descriptor aperti
+ nel sistema.
+ \item[\errcode{ENOMEM}] non c'è sufficiente memoria nel kernel per creare
+ l'istanza.
+ \end{errlist}
+}
+\end{prototype}
+
+La funzione non prende alcun argomento, e restituisce un file descriptor
+associato alla coda, attraverso il quale verranno effettuate le operazioni di
+notifica. Si tratta di un file descriptor speciale, che non è associato a
+nessun file, ma che viene utilizzato per notificare gli eventi che si sono
+posti in osservazione all'applicazione che usa l'interfaccia di
+\textit{inotify}. Dato che questo file descriptor non è associato a nessun
+file o directory, questo consente di evitare l'inconveniente di non poter
+smontare un filesystem i cui file sono tenuti sotto osservazione.\footnote{ed
+ una delle caratteristiche dell'interfaccia di \textit{inotify} è proprio
+ quella di notificare il fatto che il filesystem su cui si trova il file o la
+ directory osservata è stato smontato.}
+
+Inoltre trattandosi di un file descriptor a tutti gli effetti, esso potrà
+essere utilizzato come argomento per le funzioni \func{select} e \func{poll},
+e siccome gli eventi vengono notificati come dati disponibili in lettura sul
+file descriptor, dette funzioni ritorneranno tutte le volte che si avrà un
+evento di notifica. Così, invece di dover utilizzare i segnali, si potrà
+gestire l'osservazione delle modifiche con l'\textit{I/O multiplexing},
+utilizzando secondo le modalità illustrate in
+sez.~\ref{sec:file_multiplexing}.
+
+Infine l'interfaccia di \textit{inotify} consente di mettere sotto
+osservazione sia singoli file, che intere directory; in quest'ultimo caso
+l'interfaccia restituirà informazioni sia riguardo alla directory che ai file
+che essa contiene. Una volta creata la coda di notifica si devono definire
+gli eventi da tenere sotto osservazione; questo viene fatto tramite una
+\textsl{lista di osservazione} (o \textit{watch list}) associata alla coda.
+Per gestire la lista di osservazione l'interfaccia fornisce due funzioni, la
+prima di queste è \funcd{inotify\_add\_watch}, il cui prototipo è:
+\begin{prototype}{sys/inotify.h}
+ {int inotify\_add\_watch(int fd, const char *pathname, uint32\_t mask)}
+
+ Aggiunge un evento di osservazione alla lista di osservazione di \param{fd}.
+
+ \bodydesc{La funzione restituisce un valore positivo in caso di successo, o
+ $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EACCESS}] non si ha accesso in lettura al file indicato.
+ \item[\errcode{EINVAL}] \param{mask} non contiene eventi legali o \param{fd}
+ non è un filesystem di \textit{inotify}.
+ \item[\errcode{ENOSPC}] si è raggiunto il numero massimo di voci di
+ osservazione o il kernel non ha potuto allocare una risorsa necessaria.
+ \end{errlist}
+ ed inoltre \errval{EFAULT}, \errval{ENOMEM} e \errval{EBADF}.}
+\end{prototype}
+
+La funzione consente di creare un \textsl{evento di osservazione} (un
+cosiddetto ``\textit{watch}'') nella lista di una coda di notifica, indicata
+specificando il file descriptor ad essa associato nell'argomento \param{fd}.
+Il file o la directory da porre sotto osservazione viene invece indicato per
+nome, che viene passato nell'argomento \param{pathname}. Infine il terzo
+argomento, \param{mask}, indica che tipo di eventi devono essere tenuti sotto
+osservazione. Questo deve essere specificato come maschera binaria combinando
+i valori delle costanti riportate in tab.~\ref{tab:inotify_event_watch}. In
+essa si sono marcati con un ``$\bullet$'' gli eventi che, quando specificati
+per una directory, vengono osservati anche su tutti i file che essa contiene.
+
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|c|p{10cm}|}
+ \hline
+ \textbf{Valore} & & \textbf{Significato} \\
+ \hline
+ \hline
+ \const{IN\_ACCESS} &$\bullet$& c'è stato accesso al file in
+ lettura.\\
+ \const{IN\_ATTRIB} &$\bullet$& ci sono stati cambiamenti sui dati
+ dell'inode.\\
+ \const{IN\_CLOSE\_WRITE} &$\bullet$& è stato chiuso un file aperto in
+ scrittura.\\
+ \const{IN\_CLOSE\_NOWRITE}&$\bullet$& è stato chiuso un file aperto in
+ sola lettura.\\
+ \const{IN\_CREATE} &$\bullet$& è stato creato un file o una
+ directory in una directory sotto
+ osservazione.\\
+ \const{IN\_DELETE} &$\bullet$& è stato cancellato un file o una
+ directory in una directory sotto
+ osservazione.\\
+ \const{IN\_DELETE\_SELF} & & è stato cancellato il file (o la
+ directory) sotto osservazione.\\
+ \const{IN\_MODIFY} &$\bullet$& è stato modificato il file.\\
+ \const{IN\_MOVE\_SELF} & & è stato rinominato il file (o la
+ directory) sotto osservazione.\\
+ \const{IN\_MOVED\_FROM} &$\bullet$& un file è stato spostato fuori dalla
+ directory sotto osservazione.\\
+ \const{IN\_MOVED\_TO} &$\bullet$& un file è stato spostato nella
+ directory sotto osservazione.\\
+ \const{IN\_OPEN} &$\bullet$& un file è stato aperto.\\
+ \hline
+ \end{tabular}
+ \caption{Le costanti che identificano i valori per la maschera binaria
+ dell'argomento \param{mask} di \func{inotify\_add\_watch}.}
+ \label{tab:inotify_event_watch}
+\end{table}
+
+Se non esiste nessun \textit{watch} per il file (o la directory) specificata
+questo verrà creato per gli eventi specificati dall'argomento \param{mask},
+altrimenti la funzione sovrascriverà le impostazioni precedenti. In caso di
+successo la funzione ritorna un intero positivo, detto \textit{watch
+ descriptor} che identifica univocamente l'evento di osservazione. Questo
+valore è importante perché è soltanto con esso che si può rimuovere un evento
+di osservazione, usando la seconda funzione dell'interfaccia di gestione,
+\funcd{inotify\_rm\_watch}, il cui prototipo è:
+\begin{prototype}{sys/inotify.h}
+ {int inotify\_rm\_watch(int fd, uint32\_t wd)}
+
+ Rimuove un evento di osservazione.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo, o $-1$ in caso di
+ errore, nel qual caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EBADF}] non si è specificato in \param{fd} un file descriptor
+ valido.
+ \item[\errcode{EINVAL}] il valore di \param{wd} non è corretto, o \param{fd}
+ non è associato ad una coda di notifica.
+ \end{errlist}
+}
+\end{prototype}
+
+Oltre che per la rimozione, il \textit{watch descriptor} viene usato anche per
+identificare l'evento a cui si fa riferimento nella lista dei risultati
+restituiti da \textit{inotify}
+
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \includestruct{listati/inotify_event.h}
+ \end{minipage}
+ \normalsize
+ \caption{La struttura \structd{inotify\_event}.}
+ \label{fig:inotify_event}
+\end{figure}
+
+
+Inoltre l'interfaccia di \textit{inotify} permette di conoscere, come avviene
+per i file descriptor associati ai socket (si veda al proposito quanto
+trattato in sez.~\ref{sec:sock_ioctl_IP}) il numero di byte disponibili in
+lettura sul nostro file descriptor, utilizzando su di esso l'operazione
+\const{FIONREAD} con \func{ioctl}.\footnote{questa è una delle operazioni
+ speciali (che abbiamo visto in sez.~\ref{sec:file_ioctl}) che nel caso è
+ disponibile solo per i socket e per i file descriptor creati con
+ \func{inotify\_init}.} Questo consente anche di ottenere rapidamente il
+numero di file che sono cambiati.
+
-\index{file!inotify|)}
% TODO inserire anche inotify, vedi http://www.linuxjournal.com/article/8478
-\index{file!inotify|(}
+% TODO e man inotify
+
+\index{file!inotify|)}
+
+
+% TODO inserire anche eventfd (vedi http://lwn.net/Articles/233462/)
\textsl{paginazione} \index{paginazione} usato dalla memoria virtuale (vedi
sez.~\ref{sec:proc_mem_gen}), permette di \textsl{mappare} il contenuto di un
file in una sezione dello spazio di indirizzi del processo.
-
+ che lo ha allocato
\begin{figure}[htb]
\centering
- \includegraphics[width=12cm]{img/mmap_layout}
+ \includegraphics[width=10cm]{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}
\begin{table}[htb]
\centering
\footnotesize
- \begin{tabular}[c]{|l|p{10cm}|}
+ \begin{tabular}[c]{|l|p{11cm}|}
\hline
\textbf{Valore} & \textbf{Significato} \\
\hline
\footnotetext[20]{Dato che tutti faranno riferimento alle stesse pagine di
memoria.}
-\footnotetext[21]{L'uso di questo flag con \const{MAP\_SHARED} è
- stato implementato in Linux a partire dai kernel della serie 2.4.x.}
+
+\footnotetext[21]{L'uso di questo flag con \const{MAP\_SHARED} è stato
+ implementato in Linux a partire dai kernel della serie 2.4.x; esso consente
+ di creare segmenti di memoria condivisa e torneremo sul suo utilizzo in
+ sez.~\ref{sec:ipc_mmap_anonymous}.}
\footnotetext{questo flag ed il precedente \const{MAP\_POPULATE} sono stati
introdotti nel kernel 2.5.46 insieme alla mappatura non lineare di cui
\itindend{memory~mapping}
-\subsection{L'I/O diretto fra file descriptor con \func{sendfile}}
-\label{sec:file_sendfile}
+\subsection{L'I/O diretto fra file descriptor}
+\label{sec:file_sendfile_splice}
Uno dei problemi
\href{http://www.cs.helsinki.fi/linux/linux-kernel/2001-03/0200.html}
{\texttt{http://www.cs.helsinki.fi/linux/linux-kernel/2001-03/0200.html}}
-% TODO documentare la funzione sendfile
-
-
-% i raw device
-%\subsection{I \textit{raw} device}
-%\label{sec:file_raw_device}
-%
-% TODO i raw device
+% TODO documentare la funzione sendfile
+% TODO documentare le funzioni tee e splice
+% http://kerneltrap.org/node/6505 e http://lwn.net/Articles/178199/ e
+% http://lwn.net/Articles/179492/
+% e http://en.wikipedia.org/wiki/Splice_(system_call)
%\subsection{L'utilizzo delle porte di I/O}
% LocalWords: flock shared exclusive operation dup inode linked NFS cmd ENOLCK
% LocalWords: EDEADLK whence SEEK CUR type pid GETLK SETLK SETLKW all'inode HP
% LocalWords: switch bsd lockf mandatory SVr sgid group root mount mand TRUNC
-% LocalWords: SVID UX Documentation sendfile dnotify inotify NdA
+% LocalWords: SVID UX Documentation sendfile dnotify inotify NdA ppoll fds add
+% LocalWords: init EMFILE FIONREAD ioctl watch char pathname uint mask ENOSPC
+% LocalWords: dell'inode CLOSE NOWRITE MOVE MOVED FROM TO rm wd event page ctl
+% LocalWords: attribute Universe epoll Solaris kqueue level triggered Jonathan
+% LocalWords: Lemon BSDCON edge Libenzi kevent backporting epfd EEXIST ENOENT
+% LocalWords: MOD
%%% Local Variables: