Издательский дом ООО "Гейм Лэнд"СПЕЦВЫПУСК ЖУРНАЛА ХАКЕР #62, ЯНВАРЬ 2006 г.

Ядерная слежка

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;

};

Переменная длина имени файла порождает некоторые трудности при считывании, но сам факт появления пофайловой нотификации не может не радовать. Я бы посоветовал читать подобные структуры в два захода — сначала статичную часть, потом переменную:

Назад на стр. 062-056-1  Содержание  Вперед на стр. 062-056-3
Hosted by uCoz