\hline
\const{POLLIN} & È possibile la lettura.\\
\const{POLLRDNORM}& Sono disponibili in lettura dati normali.\\
- \const{POLLRDBAND}& Sono disponibili in lettura dati prioritari. \\
+ \const{POLLRDBAND}& Sono disponibili in lettura dati prioritari.\\
\const{POLLPRI} & È possibile la lettura di \itindex{out-of-band} dati
urgenti.\\
\hline
\const{POLLOUT} & È possibile la scrittura immediata.\\
- \const{POLLWRNORM}& È possibile la scrittura di dati normali. \\
- \const{POLLWRBAND}& È possibile la scrittura di dati prioritari. \\
+ \const{POLLWRNORM}& È possibile la scrittura di dati normali.\\
+ \const{POLLWRBAND}& È possibile la scrittura di dati prioritari.\\
\hline
\const{POLLERR} & C'è una condizione di errore.\\
\const{POLLHUP} & Si è verificato un hung-up.\\
\textbf{Valore} & \textbf{Significato} \\
\hline
\hline
- \const{EPOLL\_CTL\_ADD}& aggiunge un nuovo file descriptor da osservare
+ \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
+ \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
+ \const{EPOLL\_CTL\_DEL}& Rimuove il file descriptor \param{fd} dalla lista
dei file controllati tramite \param{epfd}.\\
\hline
\end{tabular}
descriptor associato.\footnotemark\\
\hline
\end{tabular}
- \caption{Valori del campo \param{events} di \struct{epoll\_event}.}
+ \caption{Costanti che identificano i bit del campo \param{events} di
+ \struct{epoll\_event}.}
\label{tab:epoll_events}
\end{table}
sia scaduto il tempo massimo impostato con \param{timeout}. Per quest'ultimo,
oltre ad un numero di millisecondi, si può utilizzare il valore nullo, che
indica di non attendere e ritornare immediatamente,\footnote{anche in questo
- caso il valore di ritorno sarà nullo.} o $-1$, che indica un'attesa
-indefinita. L'argomento \param{maxevents} dovrà invece essere sempre un intero
-positivo.
+ caso il valore di ritorno sarà nullo.} o il valore $-1$, che indica
+un'attesa indefinita. L'argomento \param{maxevents} dovrà invece essere sempre
+un intero positivo.
Come accennato la funzione restituisce i suoi risultati nel vettore di
strutture \struct{epoll\_event} puntato da \param{events}; in tal caso nel
campo \param{events} di ciascuna di esse saranno attivi i flag relativi agli
eventi accaduti, mentre nel campo \var{data} sarà restituito il valore che era
-stato impostato (per il file descriptor per cui si è verificato l'evento)
-quando questo era stato registrato con le operazioni \const{EPOLL\_CTL\_MOD} o
-\const{EPOLL\_CTL\_ADD}.
+stato impostato per il file descriptor per cui si è verificato l'evento quando
+questo era stato registrato con le operazioni \const{EPOLL\_CTL\_MOD} o
+\const{EPOLL\_CTL\_ADD}, in questo modo il campo \var{data} consente di
+identificare il file descriptor.\footnote{ed è per questo che, come accennato,
+ è consuetudine usare per \var{data} il valore del file descriptor stesso.}
Si ricordi che le occasioni per cui \func{epoll\_wait} ritorna dipendono da
come si è impostata la modalità di osservazione (se \textit{level triggered} o
\textit{edge triggered}) del singolo file descriptor. L'interfaccia assicura
che se arrivano più eventi fra due chiamate successive ad \func{epoll\_wait}
-questi vengano combinati. Inoltre qualora su di esso fossero presenti eventi
-non ancora notificati, e si effettuasse una modifica dell'osservazione con
-\const{EPOLL\_CTL\_MOD} questi verrebbero riletti alla luce delle modifiche.
+questi vengano combinati. Inoltre qualora su un file descriptor fossero
+presenti eventi non ancora notificati, e si effettuasse una modifica
+dell'osservazione con \const{EPOLL\_CTL\_MOD} questi verrebbero riletti alla
+luce delle modifiche.
Si tenga presente infine che con l'uso della modalità \textit{edge triggered}
il ritorno di \func{epoll\_wait} indica un file descriptor è pronto e resterà
-tale fintanto che non si sono completamente esaurite le operazioni su di esso,
-questo può essere rilevato con un errore di \errcode{EAGAIN} in una
-\func{read} o una \func{write},\footnote{è opportuno ricordare ancora una
- volta che l'uso dell'I/O multiplexing richiede di operare sui file in
- modalità non bloccante.} ma anche con il fatto che sono stati restituiti
-meno dati di quelli richiesti.
-
-Come per le precedenti \func{select} e \func{poll}, essendo queste funzioni
-utiilizzate prevalentemente con i server di rete, tratteremo degli esempi del
-loro più avanti, nella trattazione dei socket, ed in particolare in
+tale fintanto che non si sono completamente esaurite le operazioni su di esso.
+Questa condizione viene generalmente rilevata dall'occorrere di un errore di
+\errcode{EAGAIN} al ritorno di una \func{read} o una \func{write},\footnote{è
+ opportuno ricordare ancora una volta che l'uso dell'I/O multiplexing
+ richiede di operare sui file in modalità non bloccante.} ma questa non è la
+sola modalità possibile, ad esempio la condizione può essere riconosciuta
+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 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
+particolare si potrà trovare un programma che utilizza questa interfaccia in
sez.~\ref{sec:TCP_sock_multiplexing}.
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 di quello 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
\cite{UnixFAQ} viene anche chiamata una \textit{Frequently Unanswered
Question}.} è che nell'architettura classica di Unix questo non è
possibile. Al contrario di altri sistemi operativi infatti un kernel unix-like
-non prevede alcun meccanismo per cui un processo possa essere
+classico non prevedeva alcun meccanismo per cui un processo possa essere
\textsl{notificato} di eventuali modifiche avvenute su un file. Questo è il
motivo per cui i demoni devono essere \textsl{avvisati} in qualche
modo\footnote{in genere questo vien fatto inviandogli un segnale di
- \const{SIGHUP} che, per convenzione adottata dalla gran parte di detti
+ \const{SIGHUP} che, per una convenzione adottata dalla gran parte di detti
programmi, causa la rilettura della configurazione.} se il loro file di
configurazione è stato modificato, perché possano rileggerlo e riconoscere le
modifiche.
Questa scelta è stata fatta perché provvedere un simile meccanismo a livello
-generale comporterebbe un notevole aumento di complessità dell'architettura
-della gestione dei file, per fornire una funzionalità necessaria soltanto in
-casi particolari. Dato che all'origine di Unix i soli programmi che potevano
-avere una tale esigenza erano i demoni, attenendosi a uno dei criteri base
-della progettazione, che era di far fare al kernel solo le operazioni
-strettamente necessarie e lasciare tutto il resto a processi in user space,
-non era stata prevista nessuna funzionalità di notifica.
+generico per qualunque file comporterebbe un notevole aumento di complessità
+dell'architettura della gestione dei file, il tutto per fornire una
+funzionalità che serve soltanto in alcuni casi particolari. Dato che
+all'origine di Unix i soli programmi che potevano avere una tale esigenza
+erano i demoni, attenendosi a uno dei criteri base della progettazione, che
+era di far fare al kernel solo le operazioni strettamente necessarie e
+lasciare tutto il resto a processi in user space, non era stata prevista
+nessuna funzionalità di notifica.
Visto però il crescente interesse nei confronti di una funzionalità di questo
-tipo (molto richiesta specialmente nello sviluppo dei programmi ad interfaccia
-grafica) sono state successivamente introdotte delle estensioni che
+tipo, che è molto richiesta specialmente nello sviluppo dei programmi ad
+interfaccia grafica, quando si deve presentare all'utente lo stato del
+filesystem, sono state successivamente introdotte delle estensioni che
permettessero la creazione di meccanismi di notifica più efficienti dell'unica
soluzione disponibile con l'interfaccia tradizionale, che è quella del
\itindex{polling} \textit{polling}.
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
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 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}.
+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 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}
+la notifica avviene di default attraverso il segnale \const{SIGIO}, ma se ne
+può utilizzare un altro.\footnote{e di nuovo, per le ragioni già esposte in
+ precedenza, è opportuno che si utilizzino dei segnali real-time.} Inoltre,
+come in precedenza, si potrà ottenere nel gestore del segnale il file
+descriptor che è stato modificato tramite il contenuto della struttura
+\struct{siginfo\_t}.
\index{file!lease|)}
\const{DN\_ATTRIB} & È stato modificato un attributo di un file con
l'esecuzione di una fra \func{chown}, \func{chmod},
\func{utime}.\\
- \const{DN\_MULTISHOT}& richiede una notifica permanente di tutti gli
+ \const{DN\_MULTISHOT}& Richiede una notifica permanente di tutti gli
eventi.\\
\hline
\end{tabular}
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.
+controllo, il che porta facilmente ad avere un eccesso di file aperti. Inoltre
+quando la directory che si controlla è all'interno di un dispositivo
+rimovibile, mantenere il relativo file descriptor aperto comporta
+l'impossibilità di smontare il dispositivo e di rimuoverlo, il che in genere
+complica notevolmente la gestione dell'uso di questi dispositivi.
+
+Un altro problema è che l'interfaccia di \textit{dnotify} consente solo di
+tenere sotto controllo il contenuto di una directory; la modifica di un file
+viene segnalata, ma poi è necessario verificare di quale file si tratta
+(operazione che può essere molto onerosa quando una directory contiene un gran
+numero di file). 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}. Per tutta questa serie di motivi 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 è:
+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, 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.}
+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 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}.
+essere utilizzato come argomento per le funzioni \func{select} e \func{poll} e
+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,\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)}
\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}.
+ non è un file descriptor 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.
+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\_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
+ \const{IN\_ATTRIB} &$\bullet$& Ci sono stati cambiamenti sui dati
+ dell'inode (o sugli attributi
+ estesi, vedi
+ sez.~\ref{sec:file_xattr}).\\
+ \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
+ \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
+ \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
+ \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
+ \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
+ \const{IN\_MOVED\_FROM} &$\bullet$& Un file è stato spostato fuori dalla
directory sotto osservazione.\\
- \const{IN\_MOVED\_TO} &$\bullet$& un file è stato spostato nella
+ \const{IN\_MOVED\_TO} &$\bullet$& Un file è stato spostato nella
directory sotto osservazione.\\
- \const{IN\_OPEN} &$\bullet$& un file è stato aperto.\\
+ \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}
-Se non esiste nessun \textit{watch} per il file (o la directory) specificata
+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}, che identifica univocamente un
+\textsl{osservatore} su una coda di notifica; esso viene usato per farvi
+riferimento sia riguardo i risultati restituiti da \textit{inotify}, che per
+la eventuale rimozione dello stesso.
+
+La seconda funzione per la gestione delle code di notifica, che permette di
+rimuovere un \textsl{osservatore}, è \funcd{inotify\_rm\_watch}, ed 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}
-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}
-
+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}.} in caso di successo della rimozione, contemporaneamente
+alla cancellazione dell'osservatore, sulla coda di notifica verrà generato un
+evento di tipo \const{IN\_IGNORED} (vedi
+tab.~\ref{tab:inotify_read_event_flag}). Si tenga presente che se un file
+viene cancellato o un filesystem viene smontato i relativi osservatori vengono
+rimossi automaticamente e non è necessario utilizzare
+\func{inotify\_rm\_watch}.
+
+
+Come accennato l'interfaccia di \textit{inotify} prevede che gli eventi siano
+notificati come dati presenti in lettura sul file descriptor associato alla
+coda di notifica. Una applicazione pertanto dovrà leggere i dati da detto file
+con una \func{read}, che ritornerà sul buffer i dati presenti nella forma di
+una o più strutture di tipo \struct{inotify\_event} (la cui definizione è
+riportata in fig.~\ref{fig:inotify_event}). Qualora non siano presenti dati la
+\func{read} si bloccherà (a meno di non aver impostato il file descriptor in
+modalità non bloccante) fino all'arrivo di almeno un evento.
\begin{figure}[!htb]
\footnotesize \centering
\includestruct{listati/inotify_event.h}
\end{minipage}
\normalsize
- \caption{La struttura \structd{inotify\_event}.}
+ \caption{La struttura \structd{inotify\_event} usata dall'interfaccia di
+ \textit{inotify} per riportare gli eventi.}
\label{fig:inotify_event}
\end{figure}
+Una ulteriore caratteristica dell'interfaccia di \textit{inotify} è che essa
+permette di ottenere con \func{ioctl}, come per i file descriptor associati ai
+socket (si veda sez.~\ref{sec:sock_ioctl_IP}) il numero di byte disponibili in
+lettura sul file descriptor, utilizzando su di esso l'operazione
+\const{FIONREAD}.\footnote{questa è una delle operazioni speciali per i file
+ (vedi sez.~\ref{sec:file_ioctl}), che è disponibile solo per i socket e per
+ i file descriptor creati con \func{inotify\_init}.} Si può così utilizzare
+questa operazione, oltre che per predisporre una operazione di lettura con un
+buffer di dimensioni adeguate, anche per ottenere rapidamente il numero di
+file che sono cambiati.
+
+Una volta effettuata la lettura con \func{read} a ciascun evento sarà
+associata una struttura \struct{inotify\_event} contenente i rispettivi dati.
+Per identificare a quale file o directory l'evento corrisponde viene
+restituito nel campo \var{wd} il \textit{watch descriptor} con cui il relativo
+osservatore è stato registrato. Il campo \var{mask} contiene invece una
+maschera di bit che identifica il tipo di evento verificatosi; in essa
+compariranno sia i bit elencati nella prima parte di
+tab.~\ref{tab:inotify_event_watch}, che gli eventuali valori
+aggiuntivi\footnote{questi compaiono solo nel campo \var{maks} di
+ \struct{inotify\_event}, e non utilizzabili in fase di registrazione
+ dell'osservatore.} di tab.~\ref{tab:inotify_read_event_flag}.
-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.
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|p{10cm}|}
+ \hline
+ \textbf{Flag} & \textbf{Significato} \\
+ \hline
+ \hline
+ \const{IN\_IGNORED} & L'osservatore è stato rimosso, sia in maniera
+ esplicita con l'uso di \func{inotify\_rm\_watch},
+ che in maniera implicita per la rimozione
+ dell'oggetto osservato o per lo smontaggio del
+ filesystem su cui questo si trova.\\
+ \const{IN\_ISDIR} & L'evento avvenuto fa riferimento ad una directory
+ (consente così di distinguere, quando si pone
+ sotto osservazione una directory, fra gli eventi
+ relativi ad essa e quelli relativi ai file che
+ essa contiene).\\
+ \const{IN\_Q\_OVERFLOW}& Si sono eccedute le dimensioni della coda degli
+ eventi (\textit{overflow} della coda); in questo
+ caso il valore di \var{wd} è $-1$.\footnotemark\\
+ \const{IN\_UNMOUNT} & Il filesystem contenente l'oggetto posto sotto
+ osservazione è stato smontato.\\
+ \hline
+ \end{tabular}
+ \caption{Le costanti che identificano i flag aggiuntivi usati nella maschera
+ binaria del campo \var{mask} di \struct{inotify\_event}.}
+ \label{tab:inotify_read_event_flag}
+\end{table}
+
+\footnotetext{la coda di notifica ha una dimensione massima specificata dal
+ parametro di sistema \procfile{/proc/sys/fs/inotify/max\_queued\_events} che
+ indica il numero massimo di eventi che possono essere mantenuti sulla
+ stessa; quando detto valore viene ecceduto gli ulteriori eventi vengono
+ scartati, ma viene comunque generato un evento di tipo
+ \const{IN\_Q\_OVERFLOW}.}
+
+Il campo \var{cookie} contiene invece un intero univoco che permette di
+identificare eventi correlati (per i quali avrà lo stesso valore), al momento
+viene utilizzato soltanto per rilevare lo spostamento di un file, consentendo
+così all'applicazione di collegare la corrispondente coppia di eventi
+\const{IN\_MOVED\_TO} e \const{IN\_MOVED\_FROM}.
+
+Infine due campi \var{name} e \var{len} sono utilizzati soltanto quando
+l'evento è relativo ad un file presente in una directory posta sotto
+osservazione, in tal caso essi contengono rispettivamente il nome del file
+(come pathname relativo alla directory osservata) e la relativa dimensione in
+byte. Il campo \var{name} viene sempre restituito come stringa terminata da
+NUL, con uno o più zeri di terminazione, a seconda di eventuali necessità di
+allineamento del risultato, ed il valore di \var{len} corrisponde al totale
+della dimensione di \var{name}, zeri aggiuntivi compresi. Questo significa che
+le dimensioni di ciascun evento di \textit{inotify} saranno pari al valore
+\code{sizeof(\struct{inotify\_event}) + len}.
+
+Vediamo allora un esempio dell'uso dell'interfaccia di \textit{inotify} con un
+semplice programma che permette di mettere sotto osservazione un file o una
+directory.
% TODO inserire anche eventfd (vedi http://lwn.net/Articles/233462/)
-
+% e le restanti signalfd e timerfd introdotte con il 2.6.22
+% o trovargli un posto migliore
\subsection{L'interfaccia POSIX per l'I/O asincrono}
da \param{start}, se questo non può essere usato
\func{mmap} fallisce. Se si imposta questo flag il
valore di \param{start} deve essere allineato
- alle dimensioni di una pagina. \\
+ alle dimensioni di una pagina.\\
\const{MAP\_SHARED} & I cambiamenti sulla memoria mappata vengono
riportati sul file e saranno immediatamente
visibili agli altri processi che mappano lo stesso
aggiornato fino alla chiamata di \func{msync} o
\func{munmap}), e solo allora le modifiche saranno
visibili per l'I/O convenzionale. Incompatibile
- con \const{MAP\_PRIVATE}. \\
+ con \const{MAP\_PRIVATE}.\\
\const{MAP\_PRIVATE} & I cambiamenti sulla memoria mappata non vengono
riportati sul file. Ne viene fatta una copia
privata cui solo il processo chiamante ha
salvate su swap in caso di necessità. Non è
specificato se i cambiamenti sul file originale
vengano riportati sulla regione
- mappata. Incompatibile con \const{MAP\_SHARED}. \\
+ mappata. Incompatibile con \const{MAP\_SHARED}.\\
\const{MAP\_DENYWRITE} & In Linux viene ignorato per evitare
\textit{DoS} \itindex{Denial~of~Service~(DoS)}
(veniva usato per segnalare che tentativi di
scrittura sul file dovevano fallire con
\errcode{ETXTBSY}).\\
- \const{MAP\_EXECUTABLE}& Ignorato. \\
+ \const{MAP\_EXECUTABLE}& Ignorato.\\
\const{MAP\_NORESERVE} & Si usa con \const{MAP\_PRIVATE}. Non riserva
delle pagine di swap ad uso del meccanismo del
\textit{copy on write} \itindex{copy~on~write}
modifiche fatte alla regione mappata, in
questo caso dopo una scrittura, se non c'è più
memoria disponibile, si ha l'emissione di
- un \const{SIGSEGV}. \\
+ un \const{SIGSEGV}.\\
\const{MAP\_LOCKED} & Se impostato impedisce lo swapping delle pagine
mappate.\\
\const{MAP\_GROWSDOWN} & Usato per gli \itindex{stack} stack. Indica
richiesto \const{MAP\_FIXED}.\\
\const{MAP\_POPULATE} & Esegue il \itindex{prefaulting}
\textit{prefaulting} delle pagine di memoria
- necessarie alla mappatura. \\
+ necessarie alla mappatura.\\
\const{MAP\_NONBLOCK} & Esegue un \textit{prefaulting} più limitato che
- non causa I/O.\footnotemark \\
+ non causa I/O.\footnotemark\\
% \const{MAP\_DONTEXPAND}& Non consente una successiva espansione dell'area
% mappata con \func{mremap}, proposto ma pare non
% implementato.\\
Permette di rimappare non linearmente un precedente \textit{memory mapping}.
- \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
errore, nel qual caso \var{errno} assumerà uno dei valori:
\begin{errlist}
\item[\errcode{EINVAL}] Si è usato un valore non valido per uno degli
\subsection{L'I/O diretto fra file descriptor}
\label{sec:file_sendfile_splice}
-Uno dei problemi
-NdA è da finire, sul perché non è abilitata fra file vedi:
+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 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
+pone il problema di effettuare trasferimenti di grandi quantità di dati da
+kernel space a user space e all'indietro, quando in realtà sarebbe molto più
+efficiente tenere tutto in kernel space. Tratteremo in questa sezione alcune
+funzioni specialistiche che permettono di ottimizzare le prestazioni in questo
+tipo di situazioni.
+
+La prima funzione che si pone l'obiettivo di ottimizzare il trasferimento dei
+dati fra due file descriptor è \funcd{sendfile}; la funzione è presente in
+diverse versioni di Unix,\footnote{la si ritrova ad esempio in FreeBSD, HPUX
+ ed altri Unix.} ma non è presente né in POSIX.1-2001 né in altri standard,
+per cui vengono utilizzati diversi prototipi e semantiche
+differenti;\footnote{pertanto si eviti di utilizzarla se si devono scrivere
+ programmi portabili.} nel caso di Linux il suo prototipo è:
+\begin{functions}
+ \headdecl{sys/sendfile.h}
+
+ \funcdecl{ssize\_t sendfile(int out\_fd, int in\_fd, off\_t *offset, size\_t
+ count)}
+
+ Copia dei dati da un file descriptor ad un altro.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
+ errore, nel qual caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EAGAIN}] si è impostata la modalità non bloccante su
+ \param{out\_fd} e la scrittura si bloccherebbe.
+ \item[\errcode{EINVAL}] i file descriptor non sono validi, o sono bloccati
+ o una operazione di \func{mmap} non è disponibile per \param{in\_fd}.
+ \item[\errcode{EIO}] si è avuto un errore di lettura da \param{in\_fd}.
+ \item[\errcode{ENOMEM}] non c'è memoria sufficiente per la lettura da
+ \param{in\_fd}.
+ \end{errlist}
+ ed inoltre \errcode{EBADF} e \errcode{EFAULT}.
+ }
+\end{functions}
+
+
+%NdA è da finire, sul perché non è abilitata fra file vedi:
+%\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}}
-\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
% 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)
+% e http://kerneltrap.org/node/6505
+
+
+
+
+\subsection{Gestione avanzata dell'accesso ai dati dei file}
+\label{sec:file_fadvise}
+
+Nell'uso generico dell'interfaccia per l'accesso al contenuto dei file le
+operazioni di lettura e scrittura non necessitano di nessun intervento di
+supervisione da parte dei programmi, si eseguirà una \func{read} o una
+\func{write}, i dati verranno passati al kernel che provvederà ad effettuare
+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 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
+specifiche, relative alle proprie modalità di I/O sugli stessi. Tratteremo in
+questa sezione una serie funzioni che consentono ai programmi di ottimizzare
+il loro accesso ai dati dei file.
+
+
+% TODO documentare \func{madvise}
+% TODO documentare \func{mincore}
+% TODO documentare \func{posix\_fadvise}
+% vedi http://insights.oetiker.ch/linux/fadvise.html
+% questo tread? http://www.ussg.iu.edu/hypermail/linux/kernel/0703.1/0032.html
+% TODO documentare \func{fallocate}, introdotta con il 2.6.23
+% vedi http://lwn.net/Articles/226710/ e http://lwn.net/Articles/240571/
%\subsection{L'utilizzo delle porte di I/O}
\const{LOCK\_SH}& Richiede uno \textit{shared lock}. Più processi possono
mantenere un lock condiviso sullo stesso file.\\
\const{LOCK\_EX}& Richiede un \textit{exclusive lock}. Un solo processo
- alla volta può mantenere un lock esclusivo su un file. \\
+ alla volta può mantenere un lock esclusivo su un file.\\
\const{LOCK\_UN}& Sblocca il file.\\
\const{LOCK\_NB}& Non blocca la funzione quando il lock non è disponibile,
si specifica sempre insieme ad una delle altre operazioni
% 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
+% LocalWords: FOLLOW ONESHOT ONLYDIR FreeBSD EIO caching
%%% Local Variables: