2010-10-31 11 views
15

Quiero usar el mecanismo inotify en Linux. Quiero que mi aplicación sepa cuándo se modificó un archivo aaa. ¿Me puede dar una muestra de cómo hacerlo?¿Cómo utilizar inotify?

Respuesta

18

La API de C inotify
Inotify ofrece tres llamadas al sistema para construir monitores del sistema de archivos de todo tipo:

  • inotify_init() crea una instancia de el subsistema inotify en el núcleo y devuelve un descriptor de archivo en caso de éxito y -1 en caso de error. Al igual que otras llamadas al sistema, si inotify_init() falla, verifique errno para el diagnóstico.
  • inotify_add_watch(), como su nombre lo indica, agrega un reloj. Cada reloj debe proporcionar una ruta de acceso y una lista de eventos pertinentes, donde cada evento se especifica mediante una constante, como IN_MODIFY. Para monitorear más de un evento, simplemente use el operador lógico or-the pipe (|) en C-entre cada evento. Si inotify_add_watch() tiene éxito, la llamada devuelve un identificador único para el reloj registrado; de lo contrario, devuelve -1. Use el identificador para alterar o eliminar el reloj asociado.
  • inotify_rm_watch() elimina un reloj.

También son necesarias las llamadas al sistema read() y close(). Dado el descriptor generado por inotify_init(), llame a read() para esperar alertas. Suponiendo un descriptor de archivo típico, la aplicación bloquea la recepción de eventos, que se expresan como datos en la transmisión. El cierre común() en el descriptor de archivo obtenido de inotify_init() elimina y libera todos los relojes activos así como también toda la memoria asociada a la instancia de inotify. (La advertencia típica cuenta de referencia se aplica, también. Todos los descriptores de fichero asociados con una instancia deben estar cerradas antes de que se liberó a la memoria consumida por los relojes y por inotify.)

#include "inotify.h" 
#include "inotify-syscalls.h" 
int wd; 
wd = inotify_add_watch (fd, 
      "/home/rlove/Desktop", IN_MODIFY | IN_CREATE | IN_DELETE); 
if (wd < 0) 
     perror ("inotify_add_watch"); 

este ejemplo se agrega un reloj en el directorio/home/RLove/escritorio de cualquier modificación, archivo de creaciones o supresiones de archivo.

+0

¿Hay alguna razón en particular por la que tanto tú como Fabian hayan elegido no dar ejemplos para las secuencias de comandos shell de inotify? – puk

+3

inotify es una API de kernel de Linux y no un programa de espacio de usuario que puede usar en un script de shell. Si desea utilizar la API de inotify en sus scripts, eche un vistazo a inotify-tools (https://github.com/rvoicilas/inotify-tools/wiki/). – joschi

+0

Solo uso inotifywait/watch para mis directorios (a través de scripts de shell). ¿Hay algo mal con estos dos? – puk

9

A continuación se muestra un fragmento de cómo se puede utilizar inotify para ver "aaa". Tenga en cuenta que no lo he probado, ¡ni siquiera lo he compilado! Deberá agregarle una verificación de errores.

En lugar de utilizar una lectura de bloqueo, también puede usar sondear/seleccionar en inotfd.

const char *filename = "aaa"; 
int inotfd = inotify_init(); 

int watch_desc = inotify_add_watch(inotfd, filename, IN_MODIFY); 

size_t bufsiz = sizeof(struct inotify_event) + PATH_MAX + 1; 
struct inotify_event* event = malloc(bufsiz); 

/* wait for an event to occur */ 
read(inotfd, event, bufsiz); 

/* process event struct here */ 
+0

⁺¹ para mencionar Qt, la gente que mira aquí desde un resultado de motor de búsqueda podría ver, que la página no tiene nada que ver con Qt. –

0

Dado que la pregunta inicial parece mencionar Qt como una etiqueta como se señala en varios comentarios aquí, los motores de búsqueda pueden haberlo guiado hasta aquí.

Si alguien quiere saber cómo hacerlo con Qt, vea http://doc.qt.io/qt-5/qfilesystemwatcher.html para la versión Qt. En Linux usa un subconjunto de Inotify, si está disponible, ver la explicación en la página de Qt para más detalles.

Básicamente el código necesario es así:

en MainWindow.h complemento:

QFileSystemWatcher * watcher; 
private slots: 
    void directoryChanged(const QString & path); 
    void fileChanged(const QString & path); 

y para mainwindow.cpp:

#include <QFileInfo> 
#include <QFileSystemWatcher> 

watcher = new QFileSystemWatcher(this); 
connect(watcher, SIGNAL(fileChanged(const QString &)), this, SLOT(fileChanged(const QString &))); 
connect(watcher, SIGNAL(directoryChanged(const QString &)), this, SLOT(directoryChanged(const QString &))); 
watcher->addPath("/tmp/"); // watch directory 
watcher->addPath("/tmp/a.file"); // watch file 

también añadir las ranuras de mainwindow.cpp que se llaman si un archivo/directorio de cambio se nota:

void MainWindow::directoryChanged(const QString & path) { 
    qDebug() << path; 
} 
void MainWindow::fileChanged(const QString & path) { 
    qDebug() << path; 
}