From 96c2ad52857ad188cd53292a581a10c7c24eb0da Mon Sep 17 00:00:00 2001 From: Simone Piccardi Date: Sat, 21 Jul 2007 17:20:44 +0000 Subject: [PATCH] Correzioni ed esempio con inotify (ed epoll). --- fileunix.tex | 28 +++++++------- sources/inotify_monitor.c | 77 ++++++++++++++++++++++++++++++--------- 2 files changed, 73 insertions(+), 32 deletions(-) diff --git a/fileunix.tex b/fileunix.tex index f4c8fa6..397e657 100644 --- a/fileunix.tex +++ b/fileunix.tex @@ -888,7 +888,7 @@ di una singola system call (per i dettagli sull'uso di questa caratteristica si veda sez.~\ref{sec:ipc_file_lock}). -\subsection{La funzioni \func{sync} e \func{fsync}} +\subsection{Le funzioni \func{sync} e \func{fsync}} \label{sec:file_sync} Come accennato in sez.~\ref{sec:file_close} tutte le operazioni di scrittura @@ -960,7 +960,7 @@ disco) che deve essere effettuata esplicitamente.\footnote{in realt delle directory.} -\subsection{La funzioni \func{dup} e \func{dup2}} +\subsection{Le funzioni \func{dup} e \func{dup2}} \label{sec:file_dup} Abbiamo già visto in sez.~\ref{sec:file_sharing} come un processo figlio @@ -991,7 +991,7 @@ alla stessa voce nella \textit{file table}; per questo si dice che il nuovo file descriptor è \textsl{duplicato}, da cui il nome della funzione. \begin{figure}[htb] - \centering \includegraphics[width=15cm]{img/filedup} + \centering \includegraphics[width=14cm]{img/filedup} \caption{Schema dell'accesso ai file duplicati} \label{fig:file_dup} \end{figure} @@ -1547,17 +1547,17 @@ operazioni che sono predefinite per qualunque file,\footnote{in particolare (cioè di tipo \texttt{int *}) su cui sarà restituito il valore. \end{basedescript} -Si noti però come la gran parte di queste operazioni (per essere precisi le -prime sei dell'elenco) siano effettuabili in maniera generica anche tramite -l'uso di \func{fcntl}. Le due funzioni infatti sono molto simili e la presenza -di questa sovrapposizione è principalmente dovuta al fatto che alle origini di -Unix i progettisti considerarono che era necessario trattare diversamente -rispetto alle operazione di controllo delle modalità di I/O file e dispositivi -usando \func{fcntl} per i primi e \func{ioctl} per i -secondi;\footnote{all'epoca tra l'altro i dispositivi che usavano \func{ioctl} - erano sostanzialmente solo i terminali, il che spiega l'uso comune di - \errcode{ENOTTY} come codice di errore.} oggi non è più così ma le due -funzioni sono rimaste. +Si noti però come la gran parte di queste operazioni specifiche dei file (per +essere precisi le prime sei dell'elenco) siano effettuabili in maniera +generica anche tramite l'uso di \func{fcntl}. Le due funzioni infatti sono +molto simili e la presenza di questa sovrapposizione è principalmente dovuta +al fatto che alle origini di Unix i progettisti considerarono che era +necessario trattare diversamente rispetto alle operazione di controllo delle +modalità di I/O file e dispositivi usando \func{fcntl} per i primi e +\func{ioctl} per i secondi;\footnote{all'epoca tra l'altro i dispositivi che + usavano \func{ioctl} erano sostanzialmente solo i terminali, il che spiega + l'uso comune di \errcode{ENOTTY} come codice di errore.} oggi non è più così +ma le due funzioni sono rimaste. % LocalWords: descriptor system call cap like kernel sez l'inode inode VFS tab diff --git a/sources/inotify_monitor.c b/sources/inotify_monitor.c index 92391cf..1acfdb0 100644 --- a/sources/inotify_monitor.c +++ b/sources/inotify_monitor.c @@ -27,12 +27,16 @@ * *****************************************************************************/ #include -#include -#include /* C standard library */ -#include +#include +#include /* Linux inotify interface */ +#include /* Linux epoll interface */ +#include /* C standard library */ +#include /* Unix standard library */ #include /* error definitions and routines */ #include /* standard I/O library */ #include /* string functions */ +#include /* fcntl function */ +#include /* fcntl function */ #include "macros.h" @@ -43,11 +47,12 @@ void printevent(unsigned int mask); int main(int argc, char *argv[]) { - int i, size; - int fd, wd; - char buffer[128*sizeof(struct inotify_event)]; + int i, size, nread; + int fd, wd, epfd; + char buffer[1024 + sizeof(struct inotify_event)]; unsigned int mask=0; struct inotify_event * event; + struct epoll_event epev; /* * Input section: decode command line parameters * Use getopt function @@ -95,34 +100,70 @@ int main(int argc, char *argv[]) printf("Wrong number of arguments %d\n", argc - optind); usage(); } + /* initializa epoll */ + epfd = epoll_create(5); + if (epfd < 0) + perror("Failing on epoll_create"); + /* initalialize inotify */ - fd = inotify_init (); + fd = inotify_init(); if (fd < 0) perror("Failing on inotify_init"); - + if (fcntl(fd, F_SETFL, O_NONBLOCK)) + perror("Cannot set noblocking I/O on inotify fd"); + /* add watch */ wd = inotify_add_watch(fd, argv[optind], mask); if ( wd <= 0) { printf("Failing to add watched file %s, mask %i; %s\n", argv[optind], mask, strerror(errno)); exit(-1); - } + } + + /* add inotify fd to epoll */ + epev.data.fd = fd; + epev.events = EPOLLIN; + if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &epev)) + perror("Failing on epoll_ctl"); + /* * Main Loop: read events and print them */ while (1) { - size = read(fd, buffer, sizeof(buffer)); + if (epoll_wait(epfd, &epev, 1, -1) < 0 ) + perror("error on epoll_wait"); + + if (epev.data.fd != fd) + printf("something wrong, epoll activity on %i instead of %i\n", + epev.data.fd, fd); - event = (struct inotify_event *) buffer; - if (wd != event->wd) { - printf("Error, getting different watch descriptor, %i and %i\n", - wd, event->wd); + if (ioctl(fd, FIONREAD, &size)) + perror("error on getting inotify event size"); + + if (size > sizeof(buffer)) { + printf("Too many %i data to read, something wrong\n", size); exit(1); } - printf("Observed event on %s\n", argv[optind-1+event->wd]); - if (event->name != NULL) - printf("On file %s\n", event->name); - printevent(event->mask); + i = 0; + while (i < size) { + nread = read(fd, buffer, size); + if (nread < 0) { + perror("error reading inotify data"); + exit(1); + } + i += nread; + + event = (struct inotify_event *) buffer; + if (wd != event->wd) { + printf("Getting different watch descriptor, %i and %i\n", + wd, event->wd); + exit(1); + } + printf("Observed event on %s\n", argv[optind-1+event->wd]); + if (event->name != NULL) + printf("On file %s\n", event->name); + printevent(event->mask); + } } return 0; -- 2.30.2