• Событие IN_IGNORED генерируется при удалении элемента списка наблюдения. Это может произойти по нескольким причинам: приложение использовало вызов inotify_and_watch() для явного удаления элемента, либо элемент был имплицитно удален ядром, так как объект мониторинга был удален, либо файловая система, в которой данный объект находился, была размонтирована. Событие IN_IGNORED не генерируется, когда элемент списка наблюдения с установленным флагом IN_ONESHOT автоматически удаляется после произошедшего события.

• Если субъект события — каталог, то вдобавок к другим битам в поле mask также будет установлен бит IN_ISDIR.

• Событие IN_UNMOUNT информирует приложение, что файловая система, содержавшая наблюдаемый объект, была размонтирована. После этого события будет доставлено следующее событие, содержащее бит IN_IGNORED.

• Флаг IN_Q_OVERFLOW описывается в разделе 19.5, где ведется обсуждение ограничений очереди событий inotify.

Поле cookie используется для объединения связанных друг с другом событий. В настоящее время оно применяется только при переименовании файла. Когда происходит это событие для каталога, содержавшего переименовываемый файл, генерируется событие IN_MOVE_FROM, а затем событие IN_MOVE_TO генерируется для каталога, содержащего переименованный файл. (Если файлу присваивается новое имя в одном и том же каталоге, то оба события происходят с данным каталогом.) В поле cookie этих двух событий будет храниться одно и то же уникальное значение, что позволит приложению связать их.

Если событие происходит с файлом внутри наблюдаемого каталога, то поле name используется для возврата строки, идентифицирующей файл и завершающейся нуль-символом. Если же событие происходит с самим объектом наблюдения, то поле name не применяется, а поле len будет содержать 0.

Поле len показывает, сколько байтов было выделено для поля name. Это поле является обязательным, так как между окончанием строки, сохраненной в поле name и началом следующей структуры inotify_event, содержащейся в буфере, возвращенном функцией read(), может находиться несколько заполняющих байтов (см. рис. 19.2). Длина каждого события inotify, таким образом, может быть вычислена как sizeof(struct notify_event) + len.

Если буфер, переданный функции read(), слишком мал, чтобы вместить еще и следующую структуру inotify_event, то, в целях предупреждения приложения об этом, функция read() завершается с ошибкой EINVAL. (В версиях ядра, предшествовавших версии 2.6.21, функция read() в таком случае возвращала значение 0. Изменение в пользу применения константы EINVAL дает более четкое указание на допущенную программную ошибку.) Приложение может ответить повторной попыткой вызова функции read() с буфером увеличенного размера. Однако этой проблемы можно вовсе избежать, удостоверяясь, что буфер имеет достаточный размер для хранения хотя бы одного события: размер буфера, переданного функции read(), должен быть не менее (sizeof(struct inotify_event) + + NAME_MAX + 1) байт, где NAME_MAX — максимальная длина имени файла плюс один байт для завершающего нуль-символа.

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

Вызов ioctl(fd, FIONREAD, &numbytes) возвращает количество байтов, доступных в настоящий момент для чтения, а также объект inotify, на который ссылается файловый описатель fd.

События, считываемые из файлового дескриптора inotify, формируют собой упорядоченную очередь. Таким образом, например, гарантируется, что при переименовании файла событие IN_MOVED_FROM будет прочитано перед событием IN_MOVED_TO.

При добавлении нового события в конец очереди событий ядро объединит данное событие с событием, находящимся в хвосте очереди (таким образом, фактически получается, что новое в очередь не ставится), если оба этих события имеют одинаковые значения полей wd, mask, cookie и name. Так происходит потому, что многим приложениям нет необходимости знать о повторяющихся экземплярах одного и того же события, а отбрасывание лишних событий уменьшает количество памяти (ядра), необходимой для хранения очереди. Однако это значит, что мы не можем использовать inotify для достоверного определения того, сколько раз или как часто происходило повторяющееся событие.

Пример программы

Несмотря на то что в предшествующем описании много деталей, интерфейс API inotify на самом деле достаточно прост в обращении. В листинге 19.1 показано его применение.

Листинг 19.1. Использование интерфейса API inotify

inotify/demo_inotify.c

#include

#include

#include "tlpi_hdr.h"

static void /* Отобразить информацию из структуры inotify_event*/

displayInotifyEvent(struct inotify_event *i)

{

printf(" wd =%2d; ", i->wd);

if (i->cookie > 0)

Перейти на страницу:

Похожие книги