2010-10-31 2 views
15

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

ответ

18

Inotify C API
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"); 

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

+0

Есть ли какая-то особая причина, почему и вы, и Фабиан решили не приводить примеры для сценариев оболочки inotify? – puk

+3

inotify - это API ядра Linux, а не программа пространства пользователя, которую вы можете использовать в сценарии оболочки. Если вы хотите использовать inotify API в своих сценариях, посмотрите на инструменты inotify (https://github.com/rvoicilas/inotify-tools/wiki/). – joschi

+0

Я просто использую inotifywait/watch для своих каталогов (через скрипты оболочки). Что-то не так с этими двумя? – puk

9

Ниже приведен фрагмент того, как вы можете использовать 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 */ 
+0

⁺¹ для упоминания Qt, люди, которые смотрят здесь с выхода поисковой системы, могут видеть, что страница не имеет ничего общего с Qt. –

0

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

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

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

в главном окне.ч добавить:

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; 
} 
Смежные вопросы