2010-10-31 13 views
15

Desidero utilizzare il meccanismo inotify su Linux. Voglio che la mia applicazione sappia quando è stato modificato un file aaa. Potete per favore fornirmi un esempio su come farlo?Come utilizzare inotify?

risposta

18

L'API C inotify
Inotify fornisce tre chiamate di sistema per costruire monitor del file system di tutti i tipi:

  • inotify_init() crea un'istanza di il sottosistema inotify nel kernel e restituisce un descrittore di file in caso di successo e -1 in caso di errore. Come altre chiamate di sistema, se inotify_init() fallisce, controlla errno per la diagnostica.
  • inotify_add_watch(), come suggerisce il nome, aggiunge un orologio. Ogni orologio deve fornire un percorso e un elenco di eventi pertinenti, in cui ogni evento è specificato da una costante, ad esempio IN_MODIFY. Per monitorare più di un evento, usa semplicemente l'operatore logico o-pipe (|) in C-tra ogni evento. Se inotify_add_watch() ha esito positivo, la chiamata restituisce un identificativo univoco per l'orologio registrato; altrimenti restituisce -1. Utilizzare l'identificatore per modificare o rimuovere l'orologio associato.
  • inotify_rm_watch() rimuove un orologio.

Sono inoltre necessarie le chiamate di sistema read() e close(). Dato il descrittore restituito da inotify_init(), chiamate read() per attendere gli avvisi. Assumendo un tipico descrittore di file, l'applicazione blocca il ricevimento di eventi, che sono espressi come dati nel flusso. La chiusura comune() sul descrittore di file restituito da inotify_init() cancella e libera tutti gli orologi attivi e tutta la memoria associata all'istanza inotify. (Il tipico avvertimento conteggio di riferimento si applica anche qui. Tutti i descrittori di file associati a un'istanza devono essere chiusi prima che la memoria consumata dai orologi e inotify viene liberato.)

#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"); 

questo esempio viene aggiunto un orologio sulla directory/home/rlove/Desktop di eventuali modifiche, il file creazioni o eliminazioni di file.

+0

C'è una ragione particolare per cui sia tu che Fabian avete scelto di non dare esempi per lo scripting di shell di inotify? – puk

+3

inotify stesso è un'API del kernel Linux e non un programma dello spazio utente che è possibile utilizzare in uno script di shell. Se si desidera utilizzare l'API inotify negli script, consultare gli strumenti inotify (https://github.com/rvoicilas/inotify-tools/wiki/). – joschi

+0

Io uso solo inotifywait/watch per le mie directory (tramite script di shell). C'è qualcosa di sbagliato in questi due? – puk

9

Di seguito è riportato uno snippet di come è possibile utilizzare inotify per visualizzare "aaa". Nota che non l'ho ancora testato, non l'ho nemmeno compilato! Sarà necessario aggiungere il controllo degli errori ad esso.

Invece di utilizzare una lettura di blocco, è anche possibile utilizzare il sondaggio/selezionare 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

for¹ per menzionare Qt, i popoli che guarda da un motore di ricerca potrebbero vedere che la pagina non ha nulla a che fare con Qt. –

0

Dal momento che la domanda iniziale sembra parlare di Qt come un tag come notato in diversi commenti qui, i motori di ricerca possono avere piombo qui.

Se qualcuno vuole sapere come farlo con Qt, vedere http://doc.qt.io/qt-5/qfilesystemwatcher.html per la versione Qt. Su Linux utilizza un sottoinsieme di Inotify, se disponibile, vedere la spiegazione sulla pagina Qt per i dettagli.

In pratica il codice necessario assomiglia a questo:

in MainWindow.h aggiuntivo:

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

e per 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 

aggiungere anche gli slot mainwindow.cpp che sono chiamati se un file/directory-change è notato:

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