Ядерная слежка Alexander S. Salieff Спецвыпуск: Хакер, номер #062, стр. 062-056-1 (salieff@mail.ru) Мониторинг файловой системы в UNIX задаЧи интеллектуального резервированиЯ данных неразрывно связаны с мониторингом активности файловой системы. эта область всегда была насыщена сложными решениями и изощренными алгоритмами, но существуют качественно отличающиеся методы, которые облегчают эту задаЧу, — о них и поговорим Что делать, когда наступил неизбежный момент и стоит задача отслеживания изменения контента, занимающего гигабайты пространства? Можно раз в несколько минут считывать файлы и директории по одной штуке и сверять их содержимое с кешем. Решение явно не из области легковесных, как по потреблению памяти, так и по загрузке процессора. Можно пофайлово обсчитывать чексуммы, но задача обсчета нескольких сотен тысяч файлов тоже не блещет изяществом. Казалось бы, ситуация критическая, но попробуем подойти к ней с качественно иной стороны. В комплексе современных операционных систем user-space процессы не могут производить изменение контента файловой системы, разве только через сервисные вызовы ядра ОС. Другими словами, теоретически каждый такой вызов может быть отслежен и использован как нотификация изменения контента ФС. Как показывает практика, не только теоретически, но и практически. Существуют kernel-space-системы, отслеживающие обращения к ядру и отправляющие нужную информацию процессам user-space. При таком подходе процесс получает нотификацию только в случае реального изменения ФС, с минимальным потреблением вычислительных ресурсов и памяти. DirNotify Dirnotify или dnotify — классический механизм ядерного мониторинга активности файловой системы, он появился в младших сабминорах ядер Linux версии 2.4. Данный модуль отслеживает все стандартные системные вызовы (open, read, write, close, etc), сопоставляет их аргументы с таблицей нотификации и, при надобности, посылает оповещение нужному процессу. В качестве механизма управления таблицей нотификации в ядре user-space процессы используют механизм fcntl: fd = open("mydir", O_RDONLY); fcntl(fd, F_NOTIFY, myflags); Подобная конструкция устанавливает нотификацию событий, указанных в myflags, на каталог mydir. В качестве механизма оповещения ядро использует механизм UNIX/Linux-сигналов. По умолчанию используется сигнал SIGIO, но есть возможность установить свои сигналы: fcntl(fd, F_SETSIG, SIGUSR1); На выбранный сигнал программист устанавливает сигнальный обработчик, который и будет вызываться при каждом оповещении о файловой активности (то есть при приходе выбранного сигнала): static void handler(int sig, siginfo_t *si, void *data) {... struct sigaction act; int fd; act.sa_sigaction = handler; sigemptyset(&act.sa_mask); act.sa_flags = SA_SIGINFO; sigaction(SIGUSR1, &act, NULL); Мониторинг можно повесить и на несколько директорий, в этом случае нужно запомнить соответствие директорий и их дескрипторов, а сигнальный обработчик сможет извлечь активный дескриптор из поля si->si_fd. Выше я упомянул переменную myflags, которая представляет собой набор масок, объединенных логическим or. На директорию можно повесить следующие маски: |