Как использовать inotify?

Я хочу использовать механизм inotify для Linux. Я хочу, чтобы мое приложение узнало, когда был изменен файл aaa. Можете ли вы предоставить мне пример, как это сделать?

Ответы

Ответ 1

API-интерфейс inotify C
Inotify предоставляет три системных вызова для создания мониторов файловой системы всех типов:

  • inotify_init() создает экземпляр подсистемы inotify в ядре и возвращает дескриптор файла при успехе и -1 при ошибке. Как и другие системные вызовы, если inotify_init() не работает, проверьте errno для диагностики.
  • inotify_add_watch(), как следует из названия, добавляет часы. На каждом часе должен быть указан путь и список соответствующих событий, где каждое событие задается константой, например IN_MODIFY. Чтобы отслеживать несколько событий, просто используйте логический или -трубный (|) оператор в С-между каждым событием. Если inotify_add_watch() завершается успешно, вызов возвращает уникальный идентификатор зарегистрированных часов; в противном случае он возвращает -1. Используйте идентификатор для изменения или удаления связанных часов.
  • inotify_rm_watch() удаляет часы.

Также необходимы системные вызовы read() и close(). Учитывая дескриптор, полученный inotify_init(), вызовите функцию read() для ожидания предупреждений. Предполагая типичный файловый дескриптор, приложение блокирует до получения событий, которые выражаются как данные в потоке. Общий метод close() в дескрипторе файла, полученный inotify_init(), удаляет и освобождает все активные часы, а также всю память, связанную с экземпляром inotify. (Здесь также применяется стандартное оговорка о ссылках на ссылки. Все дескрипторы файлов, связанные с экземпляром, должны быть закрыты до того, как память, потребляемая часами, и 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");

В этом примере добавляются часы в каталоге /home/rlove/Desktop для любых изменений, создания файлов или удаления файлов.

Ответ 2

Ниже приведен фрагмент того, как вы можете использовать inotify для просмотра "aaa". Заметьте, что я не тестировал это, я даже не скомпилировал его! Вам нужно будет добавить к нему проверку ошибок.

Вместо использования блокирующего чтения вы также можете использовать poll/select on 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 */

Ответ 3

Поскольку исходный вопрос, похоже, упоминает Qt как тег, как указано в нескольких комментариях здесь, поисковые системы, возможно, привели вас сюда.

Если кто-то хочет знать, как это сделать с Qt, см. http://doc.qt.io/qt-5/qfilesystemwatcher.html для Qt-версии. В Linux он использует подмножество Inotify, если он доступен, подробнее см. Пояснения на странице Qt.

В основном необходимый код выглядит следующим образом:

в mainwindow.h add:

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

и для 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

также добавить слоты в mainwindow.cpp, которые вызывается, если замечено изменение файла/каталога:

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