Использование демона syslogd для вывода сообщений об ошибках
32
Вызывается функция
openlog
. Первый ее аргумент берется из вызывающего процесса и обычно является именем программы (например,
argv[0]
). Мы указываем, что идентификатор процесса должен добавляться к каждому сообщению. Аргумент
facility
также задается вызывающим процессом, и его значением может быть константа из табл. 13.2 либо, если приемлемо значение по умолчанию
LOG_USER
, нулевое значение.
Отметим, что поскольку демон выполняется без управляющего терминала, он никогда
не должен получать сигнал
SIGHUP
от ядра. Следовательно, многие демоны используют этот сигнал в качестве уведомления от администратора, что файл конфигурации демона изменился и демон должен еще раз считать файл. Два других сигнала, которые демон никогда не должен получать, — это сигналы
SIGINT
и
SIGWINCH
, и они также могут использоваться для уведомления демона о некоторых изменениях.
Пример: сервер времени и даты в качестве демона
В листинге 13.2 представлено изменение нашего сервера времени и даты, не зависящего от протокола. В отличие от сервера, показанного в листинге 11.8, в нем вызывается функция
daemon_init
, чтобы этот сервер мог выполняться в качестве демона.
Листинг 13.2. Не зависящий от протокола сервер времени и даты, работающий в качестве демона
, как только программа запускается, а затем вызываем нашу функцию
err_msg
вместо
printf
, чтобы вывести IP-адрес и порт клиента.
На самом деле, если мы хотим, чтобы наши программы могли выполняться как демоны, мы должны исключить вызов функций
printf
и
fprintf
и вместо них использовать нашу функцию
err_msg
.
Обратите внимание, что мы проверяем argc и выводим соответствующее сообщение до вызова
daemon_init
. Таким образом пользователь, запустивший демона, получает немедленное уведомление о недопустимом количестве аргументов. После вызова
daemon_init
все сообщения направляются в системный журнал.
Если мы запустим эту программу на нашем узле
linux
и затем проверим файл
/var/log/messages
(куда мы отправляем все сообщения
LOG_USER
) после соединения с тем же узлом, мы получим:
Jul 10 09:54:37 linux daytimetcpsrv2[24288]: connection from 127.0.0.1.55862
Дата, время и имя узла автоматически ставятся в начале сообщения демоном
syslogd
.
13.5. Демон inetd
В типичной системе Unix может существовать много серверов, ожидающих запроса клиента. Примерами являются FTP, Telnet, Rlogin, TFTP и т.д. В системах, предшествующих 4.3BSD, каждая из этих служб имела связанный с ней процесс. Этот процесс запускался во время загрузки из файла
/etc/rc
, и каждый процесс выполнял практически идентичные задачи запуска: создание сокета, связывание при помощи функции
bind
заранее известного порта с сокетом, ожидание соединения (TCP) или получения дейтаграммы (UDP) и последующее выполнение функции
fork
. Дочерний процесс выполнял обслуживание клиента, а родительский процесс ждал, когда поступит следующий запрос клиента. Эта модель характеризуется двумя недостатками.
1. Все демоны содержали практически идентичный код запуска, направленный сначала на создание сокета, а затем на превращение процесса в процесс демона (аналогично нашей функции
daemon_init
).
2. Каждый демон занимал некоторое место в таблице процессов, но при этом большую часть времени находился в состоянии ожидания.
. Этот демон может применяться серверами, использующими TCP или UDP, и не поддерживает других протоколов, таких как доменные сокеты Unix. Демон
inetd
решает две вышеупомянутые проблемы.
1. Он упрощает написание процессов демонов, поскольку обрабатывает большинство подробностей запуска. Таким образом устраняется необходимость вызова нашей функции
daemon_init
для каждого сервера.
2. Этот демон позволяет одиночному процессу (
inetd
) ждать входящие клиентские запросы ко множеству служб (вместо одного процесса для каждой службы). Это сокращает общее число процессов в системе.
Процесс
inetd
сам становится демоном, используя технологии, которые мы изложили при описании функции
daemon_init
. Затем он считывает и обрабатывает файл конфигурации, обычно файл
/etc/inetd.conf
. Этот файл задает, какие службы должен обрабатывать суперсервер, а также что нужно делать, когда приходит запрос к одной из этих служб. Каждая строка содержит поля, показанные в табл. 13.4. Вот несколько строк в качестве примера: