Unix - статьи



         

Демоны - часть 4


Функция sysconf() с параметром _SC_OPEN_MAX возвращает максимально возможное количество дескрипторов, которые может открыть наша программа. Мы вызываем функцию close() для каждого дескриптора (независимо от того, открыт он или нет), за исключением дескриптора pid- файла, который должен оставаться открытым.

Во время работы демона дескрипторы стандартных потоков ввода, вывода и ошибок также должны быть открыты, поскольку они необходимы многим функциям стандартной библиотеки. В то же время, эти дескприторы не должны указывать на какие-либо реальные потоки ввода/вывода. Для того, чтобы решить эту задачу, мы закрываем первые три дескриптора, а затем снова открываем их, указывая в качестве имени файла /dev/null: stdioFD = open("/dev/null", O_RDWR); dup(stdioFD); dup(stdioFD);

Теперь мы можем быть уверены, что демон не получит доступа к какому- либо терминалу. Тем не менее, у демона должна быть возможность выводить куда-то сообщения о своей работе. Традиционно для этого используются файлы журналов (log-файлы). Файлы журналов для демона подобны черным ящикам самолетов. Если в работе демона произошел какой-то сбой, пользователь может проанализировать файл журнала и (при определенном везении) установить причину сбоя. Ничто не мешает нашему демону открыть свой собственный файл журнала, но это не очень удобно. Большинство демонов пользуются услугами утилиты syslog, ведущей журналы множества системных событий. Мы открываем доступ к журналу syslog с помощью функции openlog(3): openlog(logPrefix, LOG_PID|LOG_CONS|LOG_NDELAY|LOG_NOWAIT, LOG_LOCAL0); (void) setlogmask(LOG_UPTO(logLevel));

Первый параметр функции openlog() – префикс, который будет добавляться к каждой записи в системном журнале. Далее следуют различные опции syslog. Функция setlogmask(3) позволяет установить уровень приоритета сообщений, которые записываются в журнал событий. При вызове функции BecomeDaemonProcess() мы передаем в параметре logLevel значение LOG_DEBUG. В сочетании с макросом LOG_UPTO это означает, что в журнал будут записываться все сообщения с приоритетом, начиная с наивысшего и заканчивая LOG_DEBUG.

Последнее, что нам нужно сделать для «демонизации» процесса – вызывать функцию setpgrp();

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

Функция ConfigureSignalHandlers() настраивает обработчики сигналов. Сигналы, которые получит наш демон, можно разделить на три группы: игнорируемые, «фатальные» и обрабатываемые. Вызывая функцию signal(SIGUSR2, SIG_IGN);

мы указываем, что наш демон должен игнорировать сигнал SIGUSR2. Аналогично мы поступаем с сигналами SIGPIPE, SIGALRM, SIGTSTP SIGPROF, SIGCHLD. Сигналы SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGIOT, SIGBUS, SIGFPE, SIGSEGV, SIGSTKFLT, SIGCONT, SIGPWR и SIGSYS относятся к категории «фатальных». Мы не можем их игнорировать, но и продолжать выполнение процесса-демона после получения одного из этих сигналов нежелательно. Мы назначаем всем этим сигналам обработчик FatalSigHandler, например: signal(SIGQUIT, FatalSigHandler);




Содержание  Назад  Вперед