printf("cookie =%4d; ", i->cookie);

printf("mask = ");

if (i->mask & IN_ACCESS) printf("IN_ACCESS ");

if (i->mask & IN_ATTRIB) printf("IN_ATTRIB ");

if (i->mask & IN_CLOSE_NOWRITE) printf("IN_CLOSE_NOWRITE ");

if (i->mask & IN_CLOSE_WRITE) printf("IN_CLOSE_WRITE ");

if (i->mask & IN_CREATE) printf("IN_CREATE ");

if (i->mask & IN_DELETE) printf("IN_DELETE ");

if (i->mask & IN_DELETE_SELF) printf("IN_DELETE_SELF ");

if (i->mask & IN_IGNORED) printf("IN_IGNORED ");

if (i->mask & IN_ISDIR) printf("IN_ISDIR ");

if (i->mask & IN_MODIFY) printf("IN_MODIFY ");

if (i->mask & IN_MOVE_SELF) printf("IN_MOVE_SELF ");

if (i->mask & IN_MOVED_FROM) printf("IN_MOVED_FROM ");

if (i->mask & IN_MOVED_TO) printf("IN_MOVED_TO ");

if (i->mask & IN_OPEN) printf("IN_OPEN ");

if (i->mask & IN_Q_OVERFLOW) printf("IN_Q_OVERFLOW ");

if (i->mask & IN_UNMOUNT) printf("IN_UNMOUNT ");

printf("\n");

if (i->len > 0)

printf(" name = %s\n", i->name);

}

#define BUF_LEN (10 * (sizeof(struct inotify_event) + NAME_MAX + 1))

int

main(int argc, char *argv[])

{

int inotifyFd, wd, j;

char buf[BUF_LEN];

ssize_t numRead;

char *p;

struct inotify_event *event;

if (argc < 2 || strcmp(argv[1], "-help") == 0)

usageErr("%s pathname… \n", argv[0]);

inotifyFd = inotify_init(); /* Создать объект inotify */

if (inotifyFd == -1)

errExit("inotify_init");

for (j = 1; j < argc; j++) {

 wd = inotify_add_watch(inotifyFd, argv[j], IN_ALL_EVENTS);

if (wd == -1)

errExit("inotify_add_watch");

printf("Watching %s using wd %d\n", argv[j], wd);

}

for (;;) { /* Читать события вечно */

 numRead = read(inotifyFd, buf, BUF_LEN);

if (numRead == 0)

fatal("read() из inotify fd вернула 0!");

if (numRead == -1)

errExit("read");

printf("Read %ld bytes from inotify fd\n", (long) numRead);

/* Обработка всех событий из буфера, переданного read() */

for (p = buf; p < buf + numRead;) {

 event = (struct inotify_event *) p;

displayInotifyEvent(event);

p += sizeof(struct inotify_event) + event->len;

}

}

exit(EXIT_SUCCESS);

}

inotify/demo_inotify.c

Программа из листинга 19.1 выполняет следующие шаги:

• использует функцию inotify_init() для создания файлового дескриптора inotify ;

• задействует функцию inotify_add_watch() для добавления элемента списка наблюдения для каждого из файлов, перечисленных в аргументах командной строки программы . Каждый из элементов списка осуществляет мониторинг всех возможных событий;

• выполняет бесконечный цикл, который:

• читает буфер событий из файлового дескриптора inotify ;

• вызывает функцию для displayInotifyEvent() отображения содержимого каждой структуры inotify_event в буфере .

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

$./demo_inotify dir1 dir2 &

[1] 5386

Watching dir1 using wd 1

Watching dir2 using wd 2

Затем запускаем выполнение команд, генерирующих события в двух каталогах. Начинаем с создания файла с помощью команды cat(1):

$ cat > dir1/aaa

Read 64 bytes from inotify fd

wd = 1; mask = IN_CREATE

name = aaa

wd = 1; mask = IN_OPEN

name = aaa

Вышеприведенный вывод, созданный фоновой программой, показывает, что функция read() передала буфер, содержащий два события. Мы продолжим вводом некой информации в файл и завершающего нуль-символа:

Hello world

Read 32 bytes from inotify fd

wd = 1; mask = IN_MODIFY

name = aaa

Нажмите Ctrl-D

Read 32 bytes from inotify fd

wd = 1; mask = IN_CLOSE_WRITE

name = aaa

Затем мы переименуем файл с переносом в другой каталог под наблюдением. Это приведет к генерации двух событий: одного для каталога, из которого файл переносится (дескриптор наблюдения 1) и второго — для каталога, в который файл будет перенесен (дескриптор наблюдения 2):

$ mv dir1/aaa dir2/bbb

Read 64 bytes from inotify fd

wd = 1; cookie = 548; mask = IN_MOVED_FROM

name = aaa

wd = 2; cookie = 548; mask = IN_MOVED_TO

name = bbb

Значения полей cookie обоих событий совпадают, что позволяет приложению связать их.

При создании подкаталога в одном из наблюдаемых каталогов маска генерируемого при этом события содержит бит IN_ISDIR, показывающий, что субъект события является каталогом:

$ mkdir dir2/ddd

Read 32 bytes from inotify fd

wd = 1; mask = IN_CREATE IN_ISDIR

name = ddd

На данном этапе важно повторить, что мониторинг inotify не является рекурсивным. Если бы приложению потребовалось осуществлять мониторинг событий в только что созданном каталоге, то ему нужно было бы совершить еще один вызов inotify_add_watch() с указанием путевого имени данного подкаталога.

Наконец, мы удаляем один из наблюдаемых подкаталогов:

$ rmdir dir1

Read 32 bytes from inotify fd

wd = 1; mask = IN_DELETE_SELF

wd = 1; mask = IN_IGNORED

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

19.5. Ограничения очереди и файлы /proc
Перейти на страницу:

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