Как правильно использовать inotify? - PullRequest
24 голосов
/ 31 октября 2010

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

Ответы [ 4 ]

28 голосов
/ 31 октября 2010

API inotify C

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

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

Системные вызовы read() и close() также необходимы.Учитывая дескриптор, выданный inotify_init(), позвоните read(), чтобы дождаться оповещения.Предполагая типичный файловый дескриптор, приложение блокирует ожидание получения событий, которые выражаются как данные в потоке.Общая функция close () в дескрипторе файла, полученном из inotify_init(), удаляет и освобождает все активные часы, а также всю память, связанную с экземпляром inotify.(Типичное предостережение счетчика ссылок применимо и здесь. Все файловые дескрипторы, связанные с экземпляром, должны быть закрыты до освобождения памяти, используемой часами и функцией inotify.)

  • Пример (из * 1043)* Kernel Korner - Введение для 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 для любых изменений, создания файлов илиудаление файлов.

11 голосов
/ 02 ноября 2010

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

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

Если вам нужно только приложение командной строки, есть приложение под названием inotifywait, которое просматривает файлы, используя inotify

с терминала 1

# touch cheese
# while inotifywait -e modify cheese; do 
>   echo someone touched my cheese
> done

с терминала 2

echo lol >> cheese

вот что видно на терминале 1

Setting up watches.
Watches established.
cheese MODIFY 
someone touched my cheese
Setting up watches.
Watches established.

Обновление : используйте с осторожностью и смотрите комментарии.

0 голосов
/ 25 апреля 2016

Поскольку первоначальный вопрос, кажется, упоминает 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;
}
...