anche con il fatto che sono stati restituiti meno dati di quelli richiesti.
Come le precedenti \func{select} e \func{poll}, le funzioni dell'interfaccia
-di \textit{epoll} vengono utiilizzate prevalentemente con i server di rete,
+di \textit{epoll} vengono utilizzate prevalentemente con i server di rete,
quando si devono tenere sotto osservazione un gran numero di socket; per
questo motivo rimandiamo di nuovo la trattazione di un esempio concreto a
quando avremo esaminato in dettaglio le caratteristiche dei socket, in
impostare la lunghezza della coda dei segnali real-time ad una dimensione
identica al valore massimo del numero di file descriptor
utilizzabili.\footnote{vale a dire impostare il contenuto di
- \texttt{/proc/sys/kernel/rtsig-max} allo stesso valore del contenuto di
- \texttt{/proc/sys/fs/file-max}.}
+ \procfile{/proc/sys/kernel/rtsig-max} allo stesso valore del contenuto di
+ \procfile{/proc/sys/fs/file-max}.}
% TODO fare esempio che usa O_ASYNC
Se il \textit{lease holder} non provvede a rilasciare il \textit{lease} entro
il numero di secondi specificato dal parametro di sistema mantenuto in
-\file{/proc/sys/fs/lease-break-time} sarà il kernel stesso a rimuoverlo (o
+\procfile{/proc/sys/fs/lease-break-time} sarà il kernel stesso a rimuoverlo (o
declassarlo) automaticamente.\footnote{questa è una misura di sicurezza per
evitare che un processo blocchi indefinitamente l'accesso ad un file
acquisendo un \textit{lease}.} Una volta che un \textit{lease} è stato
Per risolvere questo problema a partire dal kernel 2.4 è stata allora creata
un'altra interfaccia,\footnote{si ricordi che anche questa è una interfaccia
- specifica di Linux che deve essere evitata se si vogliono scrivere progammi
- portabili, e che le funzionalità illustrate sono disponibili soltato se è
+ specifica di Linux che deve essere evitata se si vogliono scrivere programmi
+ portabili, e che le funzionalità illustrate sono disponibili soltanto se è
stata definita la macro \macro{\_GNU\_SOURCE}.} chiamata \textit{dnotify},
che consente di richiedere una notifica quando una directory, o uno qualunque
dei file in essa contenuti, viene modificato. Come per i \textit{file lease}
\index{file!dnotify|)}
-Per risolvere i problemi appena illustrati, 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.} Anche 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 è:
+Per risolvere i problemi appena illustrati è stata introdotta una nuova
+interfaccia per l'osservazione delle modifiche a file o directory, chiamata
+\textit{inotify}.\footnote{l'interfaccia è disponibile a partire dal kernel
+ 2.6.13, le relative funzioni sono state introdotte nelle glibc 2.4.} Anche
+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, il che permette
+di risolvere 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)}
}
\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 su disco, 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 anche di evitare l'inconveniente di non
-poter smontare un filesystem i cui file sono tenuti sotto
-osservazione.\footnote{anzi, una delle capacità dell'interfaccia di
+La funzione non prende alcun argomento; inizializza una istanza di
+\textit{inotify} e restituisce un file descriptor attraverso il quale verranno
+effettuate le operazioni di notifica;\footnote{per evitare abusi delle risorse
+ di sistema è previsto che un utente possa utilizzare un numero limitato di
+ istanze di \textit{inotify}; il valore di default del limite è di 128, ma
+ questo valore può essere cambiato con \func{sysctl} o usando il file
+ \procfile{/proc/sys/fs/inotify/max\_user\_instances}.} si tratta di un file
+descriptor speciale che non è associato a nessun file su disco, e che viene
+utilizzato solo per notificare gli eventi che sono stati posti in
+osservazione. Dato che questo file descriptor non è associato a nessun file o
+directory reale, l'inconveniente di non poter smontare un filesystem i cui
+file sono tenuti sotto osservazione viene completamente
+eliminato.\footnote{anzi, una delle capacità 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
-con l'interfaccia di \textit{epoll}, e siccome gli eventi vengono notificati
+con l'interfaccia di \textit{epoll}; 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}.
+dover utilizzare i segnali,\footnote{considerati una pessima scelta dal punto
+ di vista dell'interfaccia utente.} si potrà gestire l'osservazione delle
+modifiche con una qualunque delle modalità di \textit{I/O multiplexing}
+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 è:
+osservazione, oltre che una directory anche singoli file. Una volta creata la
+coda di notifica si devono definire gli eventi da tenere sotto osservazione;
+questo viene fatto attraverso una \textsl{lista di osservazione} (o
+\textit{watch list}) che è 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)}
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.
+La funzione consente di creare un ``\textsl{osservatore}'' (il cosiddetto
+``\textit{watch}'') nella lista di osservazione di una coda di notifica, che
+deve essere indicata specificando il file descriptor ad essa associato
+nell'argomento \param{fd}.\footnote{questo ovviamente dovrà essere un file
+ descriptor creato con \func{inotify\_init}.} Il file o la directory da
+porre sotto osservazione vengono invece indicati per nome, da passare
+nell'argomento \param{pathname}. Infine il terzo argomento, \param{mask},
+indica che tipo di eventi devono essere tenuti sotto osservazione e le
+modalità della stessa. L'operazione può essere ripetuta per tutti i file e le
+directory che si vogliono tenere sotto osservazione,\footnote{anche in questo
+ caso c'è un limite massimo che di default è pari a 8192, ed anche questo
+ valore può essere cambiato con \func{sysctl} o usando il file
+ \procfile{/proc/sys/fs/inotify/max\_user\_watches}.} e si utilizzerà sempre
+un solo file descriptor.
+
+Il tipo di evento che si vuole osservare deve essere specificato
+nell'argomento \param{mask} come maschera binaria, combinando i valori delle
+costanti riportate in tab.~\ref{tab:inotify_event_watch} che identificano i
+singoli bit della maschera ed il relativo significato. 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. Nella seconda
+parte della tabella si sono poi indicate alcune combinazioni predefinite dei
+flag della prima parte.
\begin{table}[htb]
\centering
\footnotesize
\begin{tabular}[c]{|l|c|p{10cm}|}
\hline
- \textbf{Valore} & & \textbf{Significato} \\
+ \textbf{Flag} & & \textbf{Significato} \\
\hline
\hline
\const{IN\_ACCESS} &$\bullet$& C'è stato accesso al file in
\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.\\
+ sola lettura.\\
\const{IN\_CREATE} &$\bullet$& È stato creato un file o una
directory in una directory sotto
osservazione.\\
directory sotto osservazione.\\
\const{IN\_OPEN} &$\bullet$& Un file è stato aperto.\\
\hline
+ \const{IN\_CLOSE} & -- & Combinazione di
+ \const{IN\_CLOSE\_WRITE} e
+ \const{IN\_CLOSE\_NOWRITE}.\\
+ \const{IN\_MOVE} & -- & Combinazione di
+ \const{IN\_MOVED\_FROM} e
+ \const{IN\_MOVED\_TO}.\\
+ \const{IN\_ALL\_EVENTS} & -- & Combinazione di tutti i flag
+ possibili.\\
+ \hline
\end{tabular}
\caption{Le costanti che identificano i valori per la maschera binaria
- dell'argomento \param{mask} di \func{inotify\_add\_watch}.}
+ dell'argomento \param{mask} di \func{inotify\_add\_watch} che indicano il
+ tipo di evento da tenere sotto osservazione.}
\label{tab:inotify_event_watch}
\end{table}
+Oltre ai flag di tab.~\ref{tab:inotify_event_watch}, che indicano il tipo di
+evento da osservare e che vengono utilizzati anche in uscita per indicare il
+tipo di evento avvenuto, \func{inotify\_add\_watch} supporta ulteriori
+flag,\footnote{i flag \const{IN\_DONT\_FOLLOW}, \const{IN\_MASK\_ADD} e
+ \const{IN\_ONLYDIR} sono stati introdotti a partire dalle glibc 2.5, se si
+ usa la versione 2.4 è necessario definirli a mano.} riportati in
+tab.~\ref{tab:inotify_add_watch_flag}, che indicano le modalità di
+osservazione (da passare sempre nell'argomento \param{mask}) e che al
+contrario dei precedenti non vengono mai impostati nei risultati in uscita.
+
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|p{10cm}|}
+ \hline
+ \textbf{Flag} & \textbf{Significato} \\
+ \hline
+ \hline
+ \const{IN\_DONT\_FOLLOW}& Non dereferenzia \param{pathname} se questo è un
+ link simbolico.\\
+ \const{IN\_MASK\_ADD} & Aggiunge a quelli già impostati i flag indicati
+ nell'argomento \param{mask}, invece di
+ sovrascriverli.\\
+ \const{IN\_ONESHOT} & Esegue l'osservazione su \param{pathname} per una
+ sola volta, rimuovendolo poi dalla \textit{watch
+ list}.\\
+ \const{IN\_ONLYDIR} & Se \param{pathname} è una directory riporta
+ soltanto gli eventi ad essa relativi e non
+ quelli per i file che contiene.\\
+ \hline
+ \end{tabular}
+ \caption{Le costanti che identificano i valori per la maschera binaria
+ dell'argomento \param{mask} di \func{inotify\_add\_watch} che indicano le
+ modalità di osservazione.}
+ \label{tab:inotify_add_watch_flag}
+\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 è:
+altrimenti la funzione sovrascriverà le impostazioni precedenti, a meno che
+non si sia usato il flag \const{IN\_MASK\_ADD}, nel qual caso gli eventi
+specificati saranno aggiunti a quelli già presenti.
+
+Come accennato quando si tiene sotto osservazione una directory vengono
+restituite le informazioni sia riguardo alla directory stessa che ai file che
+essa contiene; questo comportamento può essere disabilitato utilizzando il
+flag \const{IN\_ONLYDIR}, che richiede di riportare soltanto gli eventi
+relativi alla directory stessa. Si tenga presente inoltre che quando si
+osserva una directory vengono riportati solo gli eventi sui file che essa
+contiene direttamente, non quelli relativi a file contenuti in eventuali
+sottodirectory; se si vogliono osservare anche questi sarà necessario creare
+ulteriori \textit{watch} per ciascuna sottodirectory.
+
+Infine usando il flag \const{IN\_ONESHOT} è possibile richiedere una notifica
+singola;\footnote{questa funzionalità però è disponibile soltato a partire dal
+ kernel 2.6.16.} una volta verificatosi uno qualunque fra gli eventi
+richiesti con \func{inotify\_add\_watch} l'\textsl{osservatore} verrà
+automaticamente rimosso dalla lista di osservazione e nessun ulteriore evento
+sarà più notificato.
+
+In caso di successo \func{inotify\_add\_watch} ritorna un intero positivo,
+detto \textit{watch descriptor}; è tramite questo valore che si identifica
+univocamente un \textsl{osservatore} su una coda di notifica, sia per quanto
+riguarda i risultati restituiti da \textit{inotify}, che per quanto riguarda
+la eventuale rimozione dello stesso; la seconda funzione per la gestione delle
+liste di osservazione è infatti \funcd{inotify\_rm\_watch}, che permette di
+rimuovere un \textsl{osservatore}; il suo prototipo è:
\begin{prototype}{sys/inotify.h}
{int inotify\_rm\_watch(int fd, uint32\_t wd)}
- Rimuove un evento di osservazione.
+ Rimuove un \textsl{osservatore} da una coda di notifica.
\bodydesc{La funzione restituisce 0 in caso di successo, o $-1$ in caso di
errore, nel qual caso \var{errno} assumerà uno dei valori:
}
\end{prototype}
+La funzione rimuove dalla coda di notifica identificata dall'argomento
+\param{fd} l'osservatore identificato dal \textit{watch descriptor}
+\param{wd};\footnote{ovviamente deve essere usato per questo argomento un
+ valore ritornato da \func{inotify\_add\_watch}, altrimenti si avrà un errore
+ di \errval{EINVAL}.} inoltre, contemporaneamente alla rimozione
+dell'osservatore, sulla coda di notifica verrà generato un evento di tipo
+\const{IN\_IGNORED} (vedi tab.~\ref{tab:inotify_read_event_flag}).
+
+
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}
+restituiti da \textit{inotify}; questi ultimi infatti vengono notificati alle
+applicazioni che usano l'interfaccia di \textit{inotify} come dati presenti in
+lettura su file descriptor creato con \func{inotify\_init}.
\begin{figure}[!htb]
+
+
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|p{10cm}|}
+ \hline
+ \textbf{Flag} & \textbf{Significato} \\
+ \hline
+ \hline
+ \const{IN\_IGNORED} & .\\
+ \const{IN\_ISDIR} & .\\
+ \const{IN\_Q\_OVERFLOW}& .\\
+ \const{IN\_UNMOUNT} & .\\
+ \hline
+ \end{tabular}
+ \caption{Le costanti che identificano i flag aggiuntivi usati nella maschera
+ binaria del campo \var{mask} di \structd{inotify\_event}.}
+ \label{tab:inotify_read_event_flag}
+\end{table}
+
+
+
% TODO inserire anche inotify, vedi http://www.linuxjournal.com/article/8478
% TODO e man inotify
Uno dei problemi che si presenta nella gestione dell'I/O è quello in cui si
devono trasferire grandi quantità di dati da un file descriptor ed un altro;
questo usualmente comporta la lettura dei dati dal primo file descriptor in un
-buffer in menoria, da cui essi vengono poi scritti sul secondo.
+buffer in memoria, da cui essi vengono poi scritti sul secondo.
Benché il kernel ottimizzi la gestione di questo processo quando si ha a che
fare con file normali, in generale quando i dati da trasferire sono molti si
tutte le operazioni (e a gestire il \textit{caching} dei dati) per portarle a
termine in quello che ritiene essere il modo più efficiente.
-Il problema è che il concetto di migliore efficienza inpiegato dal kernel è
+Il problema è che il concetto di migliore efficienza impiegato dal kernel è
relativo all'uso generico, mentre esistono molti casi in cui ci sono esigenze
specifiche dei singoli programmi, che avendo una conoscenza diretta di come
verranno usati i file, possono necessitare di effettuare delle ottimizzazioni
% LocalWords: attribute Universe epoll Solaris kqueue level triggered Jonathan
% LocalWords: Lemon BSDCON edge Libenzi kevent backporting epfd EEXIST ENOENT
% LocalWords: MOD wait EPOLLIN EPOLLOUT EPOLLRDHUP SOCK EPOLLPRI EPOLLERR one
-% LocalWords: EPOLLHUP EPOLLET EPOLLONESHOT shot maxevents
+% LocalWords: EPOLLHUP EPOLLET EPOLLONESHOT shot maxevents ctlv ALL DONT HPUX
%%% Local Variables:
%%% mode: latex
%%% TeX-master: "gapil"
%%% End:
+% LocalWords: FOLLOW ONESHOT ONLYDIR FreeBSD EIO caching