Вход/Регистрация
Разработка приложений в среде Linux. Второе издание
вернуться

Троан Эрик В.

Шрифт:

Для отмены уведомления о событии вызовите

fcntl
с командой
F_NOTIFY
и последним аргументом, равным нулю.

Обычно уведомление каталога автоматически отменяется после передачи одного сигнала. Для эффективного уведомления каталога окончательный аргумент для

fcntl
должен быть объединен операцией "ИЛИ" с
DN_MULTISHOT
, что вызывает отправку сигналов для всех подходящих событий до отмены уведомления.

По умолчанию для уведомления каталога передается

SIGIO
. Если приложение желает использовать для этого другой сигнал (например, для разных каталогов могут понадобиться разные сигналы), можно применить команду
F_SETSIG
в
fcntl
, а в качестве последнего аргумента определить нужный сигнал. Если используется
F_SETSIG
(даже если установлен сигнал
SIGIO
), ядро также помещает файловый дескриптор на каталог в элементе
si_fd
аргумента обработчика сигналов
siginfo_t
[103] , позволяя приложению узнать, какие из контролируемых каталогов обновились [104] .

103

Это то же, что и метод, используемый для владения файлами (глава 13).

104

Обработчик сигналов все еще следует регистрировать с помощью флага

SA_SIGINFO
, чтобы файловый дескриптор надлежащим образом получил доступ к сигналу.

Если контролируется несколько каталогов и для всех каталогов выбран один сигнал, крайне необходимо использовать сигнал реального времени, чтобы убедиться, что ни одно из событий не затерялось.

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

SIGRTMIN
при смене каталога и использует
si_fd
, чтобы обнаружить, какой именно каталог был изменен. С целью предотвращения условий состязаний программа использует сигналы с очередизацией и блокирование сигналов. Сигнал может быть доставлен только один раз — при вызове
sigsuspend
в строке 203. Это обеспечивает повторное сканирование каталога в случае внесения изменений в каталог во время его сканирования; иначе эти изменения останутся незамеченными. Использование сигналов с очередизацией разрешает любые изменения каталога во время работы программы; эти сигналы доставляется при каждом новом вызове
sigsuspend
, гарантируя, что ничего не пропущено.

1: /* dirchange.с */

2:

3: #define _GNU_SOURCE

4: #include <dirent.h>

5: #include <errno.h>

6: #include <fcntl.h>

7: #include <signal.h>

8: #include <stdio.h>

9: #include <stdlib.h>

 10: #include <string.h>

 11: #include <unistd.h>

 12:

 13: /* Для сохранения имен файлов из каталога используется связный

 14: список. Поле exists служит для хранения служебной информации

 15: при проверке изменений. */

 16: struct fileInfo {

 17: char * name;

 18: struct fileInfo * next;

 19: int exists;

 20: };

 21:

 22: /* Это глобальный массив. Он отображает файловые дескрипторы на пути

 23: каталогов, сохраняет список файлов в каталоге и предоставляет

 24: обработчику сигналов место для отображения того факта, что каталог

 25: должен сканироваться повторно. Последний элемент имеет path,

 26: равный NULL, обозначающий конец массива. */

 27:

 28: struct directoryInfo {

 29: char * path;

 30: int fd;

 31: int changed;

 32: struct fileInfo * contents;

 33: } * directoryList;

 34:

 35: /* Это никогда не возвращает пустой список; любой каталог содержит,

 36: по крайней мере, "." и ".." */

 37: int buildDirectoryList(char * path, struct fileInfo ** listPtr) {

 38: DIR * dir;

 39: struct dirent * ent;

 40: struct fileInfo * list = NULL;

 41:

 42: if (!(dir = opendir(path))) {

 43: perror("opendir");

 44: return 1;

 45: }

 46:

 47: while ((ent = readdir(dir))) {

 48: if (!list) {

 49: list = malloc(sizeof(*list));

 50: list->next = NULL;

 51: *listPtr = list;

 52: } else {

 53: list->next = malloc(sizeof(*list));

 54: list = list->next;

 55: }

 56:

 57: list->name = strdup(ent->d_name);

 58: }

 59:

 60: if (errno) {

 61: perror("readdir");

 62: closedir(dir);

 63: return 1;

 64: }

 65:

  • Читать дальше
  • 1
  • ...
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • ...

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

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: