Ядерная слежка Alexander S. Salieff Спецвыпуск: Хакер, номер #062, стр. 062-056-2 DN_ACCESS — файл был открыт (на чтение) DN_MODIFY — файл был модифицирован DN_CREATE — файл был создан DN_DELETE — файл был удален DN_RENAME — файл был переименован DN_ATTRIB — у файла сменились атрибуты (chmod,chown) К сожалению, оповещение приходит только для директории, а какой именно файл изменился, придется выяснять самостоятельно, однако часто локализация конкретной директории неслабо облегчает задачу. В схеме по умолчанию процесс должен установить нотификацию на каталог, получить оповещение и снова установить нотификацию. Но если маски не изменяются, то не имеет смысла переустанавливать нотификацию каждый раз, в этом случае добавляется специализированная маска DN_MULTISHOT, и тогда оповещение не сбрасывается после каждой доставки, а сохраняется постоянно: fcntl(fd, F_NOTIFY, DN_MODIFY|DN_CREATE|DN_MULTISHOT); Если используешь мультишот, настоятельно рекомендую вместо стандартного SIGIO установить realtime-сигнал: одинаковые стандартные сигналы могут затирать друг друга при задержках в обработке, в то время как realtime-сигналы выстраиваются в очередь: fcntl(fd, F_SETSIG, SIGRTMIN + 1); ... sigaction(SIGRTMIN + 1, &act, NULL); Inotify Несмотря на популярность, механизм dnotify имеет определенные проблемы. Ограничения со стороны user-space заключаются в сигнальном механизме и использовании каталогов как конечных единиц нотификации. В реализации со стороны ядра тоже есть набор недоработок, пока не останавливаюсь на них. Из-за описанных причин начиная с ядра Linux 2.6.13 появился новый стандартный механизм нотификации файловой активности, его имя — inotify. Основной узел механизма inotify — это символьное псевдоустройство /dev/inotify с мажором 10 и минором 63. На это устройство устанавливаются события слежения посредством механизма ioctl, через который передается структура inotify_watch_request, содержащая имя директории и маски слежения: int fd = open("/dev/inotify", O_RDONLY); struct inotify_watch_request iwr; iwr.dirname = strdup (dirname); iwr.mask = mask; int wd = ioctl(fd, INOTIFY_WATCH, &iwr); Inotify имеет намного больше масок, чем у dnotify (не стал засорять текст, см. врезку). Рекомендуется сохранить дескриптор wd для дальнейших манипуляций с событиями на данной директории. Далее можно ожидать данных, доступных для чтения, и читать их из файла /dev/inotify. Данные приходят в виде событий, оформленных в структуры inotify_event. Такая структура содержит в себе ioctl-дескриптор (тот самый wd) установленных событий, набор произошедших событий, cookie в четыре байта для синхронизации, длина имени файла, с которым случилось событие, и это самое имя файла: struct inotify_event { __s32 wd; __u32 mask; __u32 cookie; size_t len; char *filename; }; Переменная длина имени файла порождает некоторые трудности при считывании, но сам факт появления пофайловой нотификации не может не радовать. Я бы посоветовал читать подобные структуры в два захода — сначала статичную часть, потом переменную: |