Операционная система UNIX
Часть 59 из 155 Информация о книге
#include <sys/types.h>#include <sys/param.h>#include <sys/resource.h>main(int argc, char **argv) {int fd;struct rlimit flim;/* Если родительский процесс — init, можно не беспокоитьсяза терминальные сигналы. Если нет — необходимо игнорироватьсигналы, связанные с вводом/выводом на терминалфонового процесса: SIGTTOU, SIGTTIN, SIGTSTP */if (getppid() != 1) {signal(SIGTTOU, SIG_IGN);signal(SIGTTIN, SIG_IGN);signal(SIGTSTP, SIG_IGN);/* Теперь необходимо организовать собственную группу и сеанс,не имеющие управляющего терминала. Однако лидером группы исеанса может стать процесс, если он еще не является лидером.Поскольку предыстория запуска данной программы неизвестна,необходима гарантия, что наш процесс не является лидером.Для этого порождаем дочерний процесс. Т.к. его PID уникален,то ни группы, ни сеанса с таким идентификатором не существует,а значит нет и лидера. При этом родительский процесснемедленно завершает выполнение, поскольку он уже не нужен.Существует еще одна причина необходимости порождениядочернего процесса. Если демон был запущен из командной строкикомандного интерпретатора shell не в фоновом режиме,последний будет ожидать завершения выполнения демона,и таким образом, терминал будет заблокирован.Порождая процесс и завершая выполнение родителя,имитируем для командного интерпретатора завершениеработы демона, после чего shell выведет свое приглашение */if (fork () !=0)exit(0); /* Родитель заканчивает работу *//* Дочерний процесс с помощью системного вызовастановится лидером новой группы, сеанса и не имеет[28]ассоциированного терминала */}/* Теперь необходимо закрыть открытые файлы. Закроемвсе возможные файловые дескрипторы. Максимальное числооткрытых файлов получим с помощью функции getrlimit */getrlimit(RLIMIT_NOFILE, &flim);for (fd = 0; fd < flim.rlim_max; fd++)close(fd);/* Сменим текущий каталог на корневой */chdir("/");/* Заявим о себе в системном журнале. Для этого сначалаустановим опции ведения журнала: каждая запись будетпредваряться идентификатором PID демона, при невозможностизаписи в журнал сообщения будут выводиться на консоль,источник сообщений определим как "системный демон"(см. комментарии к функциям ведения журнала ниже). */openlog("Скелет демона" , LOG_PID | LOG_CONS, LOG_DAEMON);/* Отметимся */syslog(LOG_INFO, "Демон начал плодотворную работу...");closelog();/* Далее следует текст программы, реализующий полезные функциидемона. Эта часть предоставляется читателю для собственнойразработки. */...}В программе использовалось еще не обсуждавшаяся возможность системного журнала сообщений выполняющихся программ. Функцией генерации сообщений является syslog(3), отправляющая сообщение демону системного журнала syslogd(1M), который в свою очередь либо дописывает сообщения в системный журнал, либо выводит на их консоль, либо перенаправляет в соответствии со списком пользователей данной или удаленной системы. Конкретный пункт назначения определяется конфигурационным файлом (/etc/syslog.conf). Функция имеет определение:
#include <syslog.h>void syslog(int priority, char *logstring, /* параметры*/...);Каждому сообщению
назначается приоритет, указанный параметромlogstring. Возможные значения этого параметра включают:priority
LOG_EMERGИдентифицирует состояние "паники" в системе. Обычно рассылается всем пользователям. LOG_ALERTИдентифицирует ненормальное состояние, которое должно быть исправлено немедленно, например, нарушение целостности системной базы данных. LOG_CRITИдентифицирует критическое событие, например, ошибку дискового устройства. LOG_ERRИдентифицирует различные ошибки. LOG_WARNINGИдентифицирует предупреждения. LOG_NOTICEИдентифицирует события, которые не являются ошибками, но требуют внимания. LOG_INFOИдентифицирует информационные сообщения, как, например, использованное в приведенной программе. LOG_DEBUGИдентифицирует сообщение, обычно используемое только при отладке программы.