Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

Начинаем работать с Inotify

Оригинал: Getting Started with Inotify
Автор: Amit Saha
Дата публикации: 1 Апреля 2011 г.
Перевод: А.Панин
Дата перевода: 9 октября 2012 г.

Inotify является функцией ядра Linux, предоставляющей интерфейс для отслеживания изменений файловой системы пользовательским приложениям. Эта статья демонстрирует примеры использования API Inotify для отслеживания интересующих событий и выполнения различных действий при наступлении этих событий.

Изменения файловой системы, которые можно отследить при помощи Inotify включают в себя создание, удаление или изменение директорий и файлов. Для того, чтобы начать использовать API Inotify в своих программах на языке C, вам необходимо подключить заголовочный файл sys/inotify.h.

Наблюдения (Watches)

Наблюдение лежит в основе Inotify. Вы можете использовать наблюдение для указания директории или файла, а также событий, за которыми вы хотите следить. Например, функция создания наблюдения inotify_add_watch(fd, root, IN_CREATE | IN_MODIFY | IN_DELETE) позволяет указать, что вы хотите следить за директорией, заданной переменной root, наблюдая за событиями создания, изменения и удаления файлов и директорий внутри нее, что можно понять по маске событий IN_CREATE | IN_MODIFY | IN_DELETE. Значения констант для задания маски событий находятся в в файле linux/inotify.h.

Приведенная выше функция возвращает целочисленное значение, являющееся уникальным идентификатором наблюдения, или -1 в случае ошибки. Аргумент fd является файловым дескриптором, связанным с конкретным наблюдением. Наблюдение идентифицируется при помощи пути, поэтому если вам необходимо создать другое наблюдение с таким же путем, необходимо вызвать inotify_add_watch() с тем же путем, но с другой маской событий.

Простая демонстрационная программа

Данная демонстрационная программа на языке C позволяет следить за созданием, изменением и удалением файлов и директорий внутри заданной директории:

Ниже показан пример вывода после компиляции программы и ее запуска:
$ gcc listing1.c
$ ./a,.out /home/gene/
Watching:: /home/gene/ 
.
.
The file .xsession-errors was modified with WD 1 
The file .xsession-errors was modified with WD 1 
The file .xsession-errors was modified with WD 1 
The directory foobar was Created.

Первым шагом при использовании Inotify должна быть инициализация этой системы при помощи функции inotify_init(), возвращающей файловый дескрипор, который может быть использован для добавления наблюдений и чтения данных событий впоследствии в приложении.

Данные событий возвращаются в виде структуры struct inotify_event (определенной в файле linux/inotify.h), которую можно получить при помощи системного вызова read().

Наконец, наблюдение удаляется и ресурсы, связанные с Inotify, освобождается при помощи вызовов функций inotify_rm_watch () и close() соответственно.

Наблюдение за поддиректориями

К сожалению, не существует метода для указания того, что вы хотите наблюдать за изменениями во всех поддиректориях заданной директории. Следовательно, для решения этой задачи необходимо обойти все поддиректории и создать наблюдения для каждой из них.

Следующая программа на языке C выполняет указанные действия, обходя только поддиректории заданной директории при помощи функций из заголовочного файла dirent.h и добавляет по наблюдению для каждой из них. Впоследствии, вместо того, чтобы выводить сообщения напрямую в стандартный вывод программы stdout, сообщения записываются в файл журнала с именем inotify_logger.log.

Автоматическая компиляция файлов

Теперь, когда вы имеете представление о том, как использовать Inotify в приложениях, которым требуется контролировать изменения файловой системы, давайте займемся интересным и, возможно, очень полезным делом. Используя Inotify, будем следить за изменениями директории, и в том случае, если файл исходного кода создается или изменяется, будем вызывать gcc для компиляции файла и перемещения программы в отдельную директорию /bin внутри нашей директории. Исходный код программы, который мы сохраним в файле auto_compile.c, представлен ниже:

Ниже приведен вывод при компиляции и запуске этой программы на языке C:
$ gcc auto_compile.c 
$ ./a.out /home/gene/codes/ 
Watching:: /home/gene/codes/ 
Compiling:: hello1.c 
Compiling:: hello2.c

Конечно же, вы можете легко изменить программу для компиляции и выполнения программ на других языках программирования.

Inotify-tools

Inotify-tools - это библиотека на языке C и набор программ с интерфейсом командной строки, предоставляющих доступ к функциям системы Inotify. Одним из наиболее полезных инструментов данного пакета является программа inotifywatch, которая может использоваться для наблюдения за изменениями директории и обладает большим набором функций, чем наша вторая программа.

dnotify, inotify и fanotify

Технология inotify, впервые представленная в ядре версии 2.6.36, заменила собой технологии dnotify и fanotify за короткий промежуток времени. Обратитесь к статье в LWN, чтобы узнать подробнее об этих технологиях.

Если вы посмотрите исходные коды ядра в поддиректории fs/notify, вы можете обнаружить реализации всех трех технологий, гармонично сосуществующих друг с другом.

В данной статье мы кратко рассмотрели очень полезную функцию ядра Linux, доступную в пространстве пользователя. Хотя идея данной функции не нова (используется с 2005 года), теперь вы знаете, как разрабатывать приложения, которые выполняют действия в зависимости от изменений файловой системы. Если вы используете язык программирования, отличный от C, помните о существовании API для C++, Java, Python, Ruby и даже модуля для node.js! Несколько советов по разработке программ на базе рассмотренных функций:
  • Расширьте функции программы auto_compile.c до плагина файлового менеджера, такого как Nautilus, чтобы при создании или изменении файлов исходного кода в заданной директории, происходила компиляция.
  • Программы, работающие с Inotify, будут наиболее удобны в том случае, если они будут реализованы в виде служб, работающих как фоновые процессы без вмешательства пользователя. Следовательно, цикл while(1) может быть реализован лучшим образом как функция пробуждения, в остальное время процесс будет находиться в спящем состоянии.