Unix - статьи



     Куплю плитку в ванную по материалам сайта. | Шлюхи Заставская здесь еще больше. |     

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


Сейчас мы пропустим блок операторов if (argc > 1) {...} (мы вернемся к нему позже) и рассмотрим основные этапы работы демона. Функция BecomeDaemonProcess() превращает обычный консольный процесс Linux в процесс-демон. Функция ConfigureSignalHandlers() настраивает обработчики сигналов процесса-демона, а функция BindPassiveSocket() открывает определеный порт TCP/IP для прослушивания входящих запросов. Далее следует цикл, в котором сервер обрабатывает запросы. Многие сетевые серверы, получив запрос, создают дочерний процесс для его обработки. Таким образом достигается возможность параллельной обработки запросов. Некоторые серверы используют для параллельной обработки запросов потоки. Что касается нашего сервера, то из соображений простоты он обрабатывает запросы в последовательном (блокирующем) режиме. Мы ведь не ожидаем, что наш демонстрационный сервер будет получать много запросов, не так ли?

Нормальный выход из цикла обработки запросов происходит при получении процессом сигнала SIGUSER1. После выхода из цикла процесс вызывает функцию TidyUp() и завершает работу. Мы, безусловно, можем завершить процесс-демон, послав ему сигнал SIGKILL (SIGTERM и некоторые другие), но пользовательский сигнал SIGUSER1 гарантирует вежливое завершение нашего демога. «Вежливое завершение» означает, что сервер ответит на текущий запрос перед тем, как завершиться и удалит свой pid- файл.

Рассмотрим теперь подробнее функцию BecomeDaemonProcess(), благодаря которой обычный процесс Linux становится демоном. Мы не будем перепечатывать тексты функций целиком, так как иначе статья будет состоять исключительно из листингов (на самом деле, длина листингов даже превышает пространство, выделенное под статью). По этой причине во время чтения статьи рекомендуется постоянно иметь под рукой прилагаемый исходный текст.

В строке chdir("/");

Мы делаем корневую директорию текущей директорией процесса-демона. Будучи запущен, наш демон может работать вплоть до перезагрузки системы, поэтому его текущая диретокрия должна принадлежать файловой системе, которая не может быть размонтирована. Далее следует вызов lockFD = open(lockFileName, O_RDWR|O_CREAT|O_EXCL, 0644);

Каждый процесс-демон создает так называемый pid-файл (или файл блокировки). Этот файл обычно содержится в директории /var/run и имеет имя daemon.pid, где “daemon” соответствует имени демона. Файл блокировки содержит значение PID процесса демона. Этот файл важен по двум причинам. Во-первых, его наличие позволяет установить, что в системе уже запущен один экземпляр демона. Большинство демонов, включая наш, должны выполняяться не более чем в одном экземпляре (это логично, если учесть, что демоны часто обращаются к неразделяемым ресурсам, таким, как сетевые порты). Завершаясь, процесс-демон удаляет pid-файл, указывая тем самым, что можно запустить другой экземпляр процесса. Однако, работа демона не всегда завершается нормально, и тогда на диске остается pid-файл несуществующего процесса. Это, казалось бы, может стать непреодолимым препятствием для повторного запуска демона, но на самом деле, демоны успешно справляются с такими ситуациями. В процессе запуска демон проверяет наличие на диске pid-файла с соответствующим именем. Если такой файл существует, демон считывает из него значение PID и с помощью функции kill(2) проверяет, существует ли в системе процесс с указанным PID. Если процесс существует, значит, пользователь пытается запустить демон повторно. В этом случае программа выводит соответствующее сообщение и завершается. Если процесса с указанным PID в системе нет, значит pid-файл принадлежал аварийного завершенному демону. В этой ситуации программа обычно советует пользователю удалить pid-файл (ответственность в таких делах всегда лучше переложить на пользователя) и попытаться запустить ее еще раз. Может, конечно, случиться и так, что после аварийного завершения демона на диске останется его pid-файл, а затем какой-то другой процесс получит тот же самый PID, что был у демона. В этой ситуации для вновь запускаемого демона все будет выглядеть так, как будто его копия уже работает в системе, и запустить демон повторно вы не сможете. К счастью, описанная ситуация крайне маловероятна.

Вторая причина, по которой файл блокировки считается полезным, заключается в том, что с помощью этого файла мы можем быстро выяснить PID демона, не прибегая к команде ps.

Далее наш демон вызывает функцию fork(3), которая создает копию его процесса. Родительский процесс при этом завершается: curPID=fork(); switch(curPID) { case 0: /* мы в дочернем процессе */ break; case -1: /* ошибка fork() - случилось что-то страшное */ fprintf(stderr,"Error: initial fork failed: %s\n", strerror(errno)); return -1; break; default: /* мы в родительском процессе, завершаем его */ exit(0); break; }




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