X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=fileadv.tex;h=662d8f8afaae9c9f03d0890d4eec82f915cec2f7;hp=330bed97ac81bd6bb049ee4953d822d6f7b51618;hb=e7010c3fbd41a2de44c7b513c5de6e2c6d7ab4b4;hpb=b34574d507f26ade7f9d4d120770fc1235ff6dff diff --git a/fileadv.tex b/fileadv.tex index 330bed9..662d8f8 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -410,13 +410,13 @@ nel campo \var{revents} per notificare delle condizioni di errore. \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.\\ @@ -668,15 +668,15 @@ delle operazioni cui fanno riferimento. \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} @@ -848,38 +848,45 @@ La funzione ritorna il numero di eventi rilevati, o un valore nullo qualora 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}. @@ -989,8 +996,8 @@ diventati attivi. L'unico modo per essere sicuri che questo non avvenga 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 @@ -1004,27 +1011,29 @@ risposta\footnote{o meglio la non risposta, tanto che questa nelle Unix FAQ \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}. @@ -1136,7 +1145,7 @@ operazione di lettura, declassando il \textit{lease} a lettura con 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 @@ -1153,13 +1162,19 @@ 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 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|)} @@ -1189,7 +1204,7 @@ tramite il contenuto della struttura \struct{siginfo\_t}. \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} @@ -1221,30 +1236,34 @@ specificare un valore nullo. 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)} @@ -1263,35 +1282,39 @@ attraverso la funzione \funcd{inotify\_init}, il cui prototipo } \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)} @@ -1309,68 +1332,152 @@ prima di queste 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\_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}; è 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: @@ -1383,9 +1490,20 @@ di osservazione, usando la seconda funzione dell'interfaccia di gestione, } \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] @@ -1411,6 +1529,29 @@ 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} & .\\ + \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 @@ -1418,7 +1559,8 @@ numero di file che sono cambiati. % 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} @@ -2015,7 +2157,7 @@ tab.~\ref{tab:file_mmap_flag}. 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 @@ -2023,7 +2165,7 @@ tab.~\ref{tab:file_mmap_flag}. 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 @@ -2033,13 +2175,13 @@ tab.~\ref{tab:file_mmap_flag}. 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} @@ -2047,7 +2189,7 @@ tab.~\ref{tab:file_mmap_flag}. 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 @@ -2065,9 +2207,9 @@ tab.~\ref{tab:file_mmap_flag}. 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.\\ @@ -2421,7 +2563,7 @@ nuova system call, \funcd{remap\_file\_pages}, il cui prototipo 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 @@ -2484,14 +2626,55 @@ mappatura che gi \itindend{memory~mapping} -%\subsection{L'I/O diretto fra file descriptor} -%\label{sec:file_sendfile_splice} +\subsection{L'I/O diretto fra file descriptor} +\label{sec:file_sendfile_splice} -%Uno dei problemi +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. -%NdA è da finire, sul perché non è abilitata fra file vedi: +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}} @@ -2501,18 +2684,38 @@ mappatura che gi % 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. -%\subsection{Gestione avanzata del caching dei dati} -%\label{sec:file_fadvise} % 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} +% vedi http://lwn.net/Articles/226710/ e http://lwn.net/Articles/240571/ + %\subsection{L'utilizzo delle porte di I/O} %\label{sec:file_io_port} @@ -3257,7 +3460,7 @@ tab.~\ref{tab:file_lockf_type}. \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 @@ -3413,10 +3616,11 @@ possibilit % 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