From 8e235dc9eb48a0fdc6dab240ebede646f1391bb3 Mon Sep 17 00:00:00 2001 From: Simone Piccardi Date: Mon, 9 Apr 2007 13:35:04 +0000 Subject: [PATCH] Inizio materiale su inotify, e correzioni varie --- fileadv.tex | 136 ++++++++++++++++++++++++++++++++++--------- fileunix.tex | 25 +++++--- sources/TCP_countd.c | 2 +- 3 files changed, 126 insertions(+), 37 deletions(-) diff --git a/fileadv.tex b/fileadv.tex index ea2eb4b..9f0a225 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -543,7 +543,7 @@ accesso ai file; per questo motivo Stevens chiama questa modalit In questo modo si può evitare l'uso delle funzioni \func{poll} o \func{select} che, quando vengono usate con un numero molto grande di file descriptor, non -hanno buone prestazioni. % aggiungere cenno a epoll quando l'avrò scritta +hanno buone prestazioni. % TODO aggiungere cenno a epoll quando l'avrò scritta In tal caso infatti la maggior parte del loro tempo di esecuzione è impegnato ad eseguire una scansione su tutti i file descriptor tenuti sotto controllo per determinare quali di essi (in genere una piccola @@ -626,11 +626,11 @@ soluzione disponibile con l'interfaccia tradizionale, che Queste nuove funzionalità sono delle estensioni specifiche, non standardizzate, che sono disponibili soltanto su Linux (anche se altri kernel -supportano meccanismi simili). Esse sono realizzate, e solo a partire dalla -versione 2.4 del kernel, attraverso l'uso di alcuni \textsl{comandi} -aggiuntivi per la funzione \func{fcntl} (vedi sez.~\ref{sec:file_fcntl}), che -divengono disponibili soltanto se si è definita la macro \macro{\_GNU\_SOURCE} -prima di includere \file{fcntl.h}. +supportano meccanismi simili). Alcune di esse sono realizzate, e solo a +partire dalla versione 2.4 del kernel, attraverso l'uso di alcuni +\textsl{comandi} aggiuntivi per la funzione \func{fcntl} (vedi +sez.~\ref{sec:file_fcntl}), che divengono disponibili soltanto se si è +definita la macro \macro{\_GNU\_SOURCE} prima di includere \file{fcntl.h}. \index{file!lease|(} @@ -699,7 +699,8 @@ su un file, e che un \textit{lease} pu può ottenere un \textit{lease} soltanto per un file appartenente ad un \acr{uid} corrispondente a quello del processo. Soltanto un processo con privilegi di amministratore (cioè con la \itindex{capabilities} capability -\const{CAP\_LEASE}) può acquisire \textit{lease} su qualunque file. +\const{CAP\_LEASE}, vedi sez.~\ref{sec:proc_capabilities}) può acquisire +\textit{lease} su qualunque file. Se su un file è presente un \textit{lease} quando il \textit{lease breaker} esegue una \func{truncate} o una \func{open} che confligge con @@ -743,28 +744,20 @@ kernel Benché possa risultare utile per sincronizzare l'accesso ad uno stesso file da parte di più processi, l'uso dei \textit{file lease} non consente comunque di -risolvere il problema di rilevare automaticamente quando un file viene -modificato, che è quanto necessario ad esempio ai programma di gestione dei -file dei vari desktop grafici. +risolvere il problema di rilevare automaticamente quando un file o una +directory vengono modificati, che è quanto necessario ad esempio ai programma +di gestione dei file dei vari desktop grafici. Per risolvere questo problema è stata allora creata un'altra interfaccia, chiamata \textit{dnotify}, che consente di richiedere una notifica quando una directory, o di uno qualunque dei file in essa contenuti, viene modificato. Come per i \textit{file lease} la notifica avviene di default attraverso il -segnale \const{SIGIO}, ma questo può essere modificato e si può ottenere nel -gestore il file descriptor che è stato modificato dal contenuto della -struttura \struct{siginfo\_t}. +segnale \const{SIGIO}, ma se ne può utilizzare un altro. inoltre si potrà +ottenere nel gestore del segnale il file descriptor che è stato modificato +tramite il contenuto della struttura \struct{siginfo\_t}. \index{file!lease|)} -Ci si può registrare per le notifiche dei cambiamenti al contenuto di una -certa directory eseguendo \func{fcntl} su un file descriptor \param{fd} -associato alla stessa con il comando \const{F\_NOTIFY}. In questo caso -l'argomento \param{arg} serve ad indicare per quali classi eventi si vuole -ricevere la notifica, e prende come valore una maschera binaria composta -dall'OR aritmetico di una o più delle costanti riportate in -tab.~\ref{tab:file_notify}. - \begin{table}[htb] \centering \footnotesize @@ -800,23 +793,110 @@ tab.~\ref{tab:file_notify}. \label{tab:file_notify} \end{table} -A meno di non impostare in maniera esplicita una notifica permanente usando -\const{DN\_MULTISHOT}, la notifica è singola: viene cioè inviata una sola -volta quando si verifica uno qualunque fra gli eventi per i quali la si è -richiesta. Questo significa che un programma deve registrarsi un'altra volta se -desidera essere notificato di ulteriori cambiamenti. Se si eseguono diverse + +Ci si può registrare per le notifiche dei cambiamenti al contenuto di una +certa directory eseguendo la funzione \func{fcntl} su un file descriptor +associato alla stessa con il comando \const{F\_NOTIFY}. In questo caso +l'argomento \param{arg} di \func{fcntl} serve ad indicare per quali classi +eventi si vuole ricevere la notifica, e prende come valore una maschera +binaria composta dall'OR aritmetico di una o più delle costanti riportate in +tab.~\ref{tab:file_notify}. + +A meno di non impostare in maniera esplicita una notifica permanente usando il +valore \const{DN\_MULTISHOT}, la notifica è singola: viene cioè inviata una +sola volta quando si verifica uno qualunque fra gli eventi per i quali la si è +richiesta. Questo significa che un programma deve registrarsi un'altra volta +se desidera essere notificato di ulteriori cambiamenti. Se si eseguono diverse chiamate con \const{F\_NOTIFY} e con valori diversi per \param{arg} questi ultimi si \textsl{accumulano}; cioè eventuali nuovi classi di eventi specificate in chiamate successive vengono aggiunte a quelle già impostate nelle precedenti. Se si vuole rimuovere la notifica si deve invece specificare un valore nullo. + +\index{file!inotify|(} + +Il maggiore problema di \textit{dnotify} è quello della scalabilità, e della +complessità di gestione dovuta all'uso dei segnali. Per questo motivo 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.} + \index{file!dnotify|)} +L'interfaccia di \textit{inotify} è una caratteristica 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 file +descriptor. La coda viene creata attraverso la funzione \funcd{inotify\_init}, +il cui prototipo è: +\begin{prototype}{sys/inotify.h} + {int inotify\_init(void)} + + Inizializza una istanza di \textit{inotify}. + + \bodydesc{La funzione restituisce un file descriptor in caso di successo, o + $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno dei valori: + \begin{errlist} + \item[\errcode{EMFILE}] si è raggiunto il numero massimo di istanze di + \textit{inotify} consentite all'utente. + \item[\errcode{ENFILE}] si è raggiunto il massimo di file descriptor aperti + nel sistema. + \item[\errcode{ENOMEM}] non c'è sufficiente memoria nel kernel per creare + l'istanza. + \end{errlist} +} +\end{prototype} + +La funzione non prende alcun argomento, e restituisce un file descriptor +associato alla coda, attraverso il quale verranno effettuate le operazioni di +notifica. Si tratta di un file descriptor speciale, che non è associato a +nessun file, ma che viene utilizzato per notificare gli eventi che si sono +posti in osservazione all'applicazione che usa l'interfaccia di +\textit{inotify}. + +Trattandosi di file descriptor a tutti gli effetti, esso potrà essere +utilizzato con le funzioni \func{select} e \func{poll}. Dato che gli eventi +vengono notificati come dati disponibili in lettura sul file descriptor +stesso, dette funzioni ritorneranno tutte le volte che si avrà un evento di +notifica. Si potrà cioè gestirlo secondo le modalità illustrate in +sez.~\ref{sec:file_multiplexing}. Inoltre, come per i file descriptor +associati ai socket (vedi sez.~\ref{sec:sock_ioctl_IP}) si potrà ottenere il +numero di byte disponibili in lettura eseguendo su di esso l'operazione +\const{FIONREAD} con \func{ioctl}. + +Una volta creata la coda di notifica, ed ottenuto il relativo file descriptor, +l'interfaccia prevede che si definiscano gli eventi da tenere sotto +osservazione associando ad esso una \textsl{lista di osservazione} (o +\textit{watch list}) che indica quali file e directory tenere d'occhio. Per +gestire la lista di osservazione l'interfaccia fornisce due funzioni, la prima +è \funcd{inotify\_add\_watch}, il cui prototipo è: +\begin{prototype}{sys/inotify.h} + {int inotify\_add\_watch(int fd, const char *pathname, uint32\_t mask)} + + Aggiunge una voce alla lista di osservazione di \param{fd}. + + \bodydesc{La funzione restituisce un valore positivo in caso di successo, o + $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno dei valori: + \begin{errlist} + \item[\errcode{EACCESS}] non si ha accesso in lettura al file indicato. + \item[\errcode{EINVAL}] \param{mask} non contiene eventi legali o \param{fd} + non è un filesystem di \textit{inotify}. + \item[\errcode{ENOSPC}] si è raggiunto il numero massimo di voci di + osservazione o il kernel non ha potuto allocare una risorsa necessaria. + \end{errlist} + ed inoltre \errval{EFAULT}, \errval{ENOMEM} e \errval{EBADF}.} +\end{prototype} + + -\index{file!inotify|)} % TODO inserire anche inotify, vedi http://www.linuxjournal.com/article/8478 -\index{file!inotify|(} +% TODO e man inotify + +\index{file!inotify|)} + + + diff --git a/fileunix.tex b/fileunix.tex index a42d381..09bcbd2 100644 --- a/fileunix.tex +++ b/fileunix.tex @@ -1300,16 +1300,25 @@ seguito\footnote{per l'uso di \func{ioctl} con i socket si veda sez.~\ref{sec:sock_ctrl_func}.} quelle relative ad alcuni casi specifici (ad esempio la gestione dei terminali è effettuata attraverso \func{ioctl} in quasi tutte le implementazioni di Unix), qui riportiamo solo i valori di -alcuni comandi che sono definiti per ogni file: +alcuni comandi che sono definiti per ogni file ordinario: \begin{basedescript}{\desclabelwidth{2.0cm}} -\item[\const{FIOCLEX}] Imposta il flag di \itindex{close-on-exec} - \textit{close-on-exec}. -\item[\const{FIONCLEX}] Cancella il flag di \itindex{close-on-exec} - \textit{close-on-exec}. -\item[\const{FIOASYNC}] Abilita l'I/O asincrono. -\item[\const{FIONBIO}] Abilita l'I/O in modalità non bloccante. +\item[\const{FIOCLEX}] imposta il flag di \itindex{close-on-exec} + \textit{close-on-exec} sul file. +\item[\const{FIONCLEX}] cancella il flag di \itindex{close-on-exec} + \textit{close-on-exec} sul file. +\item[\const{FIOASYNC}] abilita la modalità di I/O asincrono sul file (vedi + sez.~\ref{sec:file_asyncronous_operation}). +\item[\const{FIONBIO}] abilita sul file l'I/O in modalità non bloccante. +\item[\const{FIOSETOWN}] imposta il processo che riceverà i segnali + \const{SIGURG} e \const{SIGIO} generati sul file. +\item[\const{FIOGETOWN}] legge il processo che riceverà i segnali + \const{SIGURG} e \const{SIGIO} generati sul file. +\item[\const{FIONREAD}] legge il numero di byte disponibili in lettura sul + file descriptor. +%\item[\const{FIOQSIZE}] . \end{basedescript} -relativi ad operazioni comunque eseguibili anche attraverso \func{fcntl}. +di cui però i primi sei sono relativi ad operazioni che si possono eseguire +anche tramite \func{fcntl}. % TODO estendere la lista delle ioctl sui file diff --git a/sources/TCP_countd.c b/sources/TCP_countd.c index cf761e7..1cdfbf1 100644 --- a/sources/TCP_countd.c +++ b/sources/TCP_countd.c @@ -201,7 +201,7 @@ int main(int argc, char *argv[]) * routine to print usage info and exit */ void usage(void) { - printf("Elementary echo server\n"); + printf("A counter server\n"); printf("Usage:\n"); printf(" echod [-h] \n"); printf(" -h print this help\n"); -- 2.30.2