Was ist der richtige Weg inotify zu benutzen?
Frage
Ich möchte den inotify
Mechanismus auf Linux verwenden. Ich möchte meine Anwendung wissen, wann eine Datei aaa
geändert wurde. Können Sie mir bitte mit einer Probe zur Verfügung stellen, wie das zu tun?
Lösung
- Dokumentation (von Monitor-Dateisystemaktivität mit inotify )
Die inotify
C API
inotify
bietet drei Systemaufrufe zu bauen Dateisystem überwacht aller Art:
-
inotify_init()
erstellt eine Instanz desinotify
Subsystem im Kernel und gibt einen Dateideskriptor auf Erfolg und-1
ein Fehler auftrat. Wie andere Systemaufrufe, wenninotify_init()
fehlschlägt, überprüfenerrno
für die Diagnose. -
inotify_add_watch()
, wie der Name schon sagt, fügt eine Uhr . Jede Uhr muss einen Pfadnamen und eine Liste der relevanten Ereignisse liefern, wobei jedes Ereignis durch eine Konstante angegeben wird, wieIN_MODIFY
. Um mehr als ein Ereignis zu überwachen, verwenden Sie einfach die logische oder - das Rohr (|) Operator in C-zwischen jedem Ereignis. Wenninotify_add_watch()
erfolgreich ist, gibt der Aufruf eine eindeutige Kennung für die registrierte Uhr; Andernfalls gibt es-1
. Verwenden Sie die Kennung zu ändern oder die zugehörige Uhr zu entfernen. -
inotify_rm_watch()
entfernt eine Uhr.
Die read()
und close()
Systemaufrufe werden ebenfalls benötigt. In Anbetracht der Beschreiber, erhalten durch inotify_init()
, Call read()
auf für Benachrichtigungen zu warten. Unter der Annahme einer typischen Dateideskriptor, die Applikationsblöcke den Empfang der Ereignisse der Warteschlange, die als Daten in dem Strom exprimiert werden. Der gemeinsame close () auf dem Dateideskriptor von Löschungen inotify_init()
ergab und gibt alle aktiven Uhren sowie alle mit der inotify Instanz zugeordneten Speicher. (Der typische Referenzzähler Vorbehalt gilt auch hier. Alle Datei-Deskriptoren mit einer Instanz verbunden ist, müssen geschlossen werden, bevor der Speicher durch die Uhr verbraucht und durch inotify befreit wird.)
- Ein Beispiel (von Kernel Korner - Intro 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");
In diesem Beispiel wird eine Uhr auf dem Verzeichnis / home / RLove / Desktop für Umstellungen, Datei-Kreationen oder Löschen von Dateien.
Andere Tipps
Im Folgenden ist ein Ausschnitt aus wie Sie inotify zu sehen „aaa“ verwenden können. Beachten Sie, dass ich nicht getestet habe, habe ich es nicht einmal zusammengestellt! Sie müssen die Fehlerprüfung, um es hinzuzufügen.
Statt eine Sperrung der Verwendung lesen Sie auch Umfrage / select auf inotfd verwenden können.
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 */
Wenn alles, was Sie brauchen, ist ein Kommandozeilen-Anwendung ist, gibt es eine namens inotifywait
dass Uhren Dateien inotify
vom Terminal 1
# touch cheese
# while inotifywait -e modify cheese; do
> echo someone touched my cheese
> done
vom Terminal 2
echo lol >> cheese
Hier ist das, was auf dem Terminal 1 zu sehen ist,
Setting up watches.
Watches established.
cheese MODIFY
someone touched my cheese
Setting up watches.
Watches established.
Aktualisieren :. Verwendung nur mit Vorsicht und sehen Sie die Kommentare
Da die anfängliche Frage Qt als Tag zu erwähnen scheint, als hier in mehreren Stellungnahmen wird darauf hingewiesen, Suchmaschinen, die Sie hier führen kann.
Wenn jemand möchte wissen, wie es mit Qt zu tun, sehen http://doc.qt.io/qt-5/qfilesystemwatcher.html für die Qt-Version. Unter Linux verwendet es eine Teilmenge von Inotify, wenn es verfügbar ist, siehe die Erklärung auf der Qt-Seite für Details.
Grundsätzlich sind die benötigten Code sieht wie folgt aus:
in mainwindow.h add:
QFileSystemWatcher * watcher;
private slots:
void directoryChanged(const QString & path);
void fileChanged(const QString & path);
und für 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
fügen Sie auch die Schlitze in mainwindow.cpp, die aufgerufen werden, wenn eine Datei / Verzeichnis-Änderung bemerkt wird:
void MainWindow::directoryChanged(const QString & path) {
qDebug() << path;
}
void MainWindow::fileChanged(const QString & path) {
qDebug() << path;
}