Русские Блоги
Процесс системного программирования Linux (восемь): подробное объяснение и создание процесса демона, использование daemon ()
1. Обзор Daemon
Linux Daemon (демон) — это специальный процесс, работающий в фоновом режиме. Он не зависит от терминала управления и периодически выполняет определенные задачи или ожидает определенных событий. Он может работать без ввода данных пользователем и предоставлять услуги как для всей системы, так и для пользовательской программы. Большинство серверов в системе Linux реализованы с помощью демонов. К распространенным процессам демона относятся системный журнал syslogd, веб-сервер httpd, почтовый сервер sendmail и сервер базы данных mysqld.
Демоны, как правило, начинают работать при запуске системы, и если их не принудительно завершить, в противном случае продолжайте работу, пока система не будет выключена. Демоны часто запускаются с привилегиями суперпользователя (root), потому что они используют специальные порты (1-1024) или получают доступ к определенным специальным ресурсам.
Родительский процесс демона — это процесс init, потому что его реальный родительский процесс завершается до выхода из дочернего процесса после разветвления дочернего процесса, поэтому он является потерянным процессом, унаследованным init. Демон является неинтерактивной программой без управляющего терминала, поэтому любой вывод, будь то стандартный вывод устройства stdout или стандартный вывод ошибки устройства stderr, требует специальной обработки.
Имя демона обычно заканчивается на d, например sshd, xinetd, crond и т. Д.
Во-вторых, шаги для создания демона
Сначала мы должны понять некоторые основные понятия:
- Каждый процесс также принадлежит к группе процессов
- У каждого владельца процесса есть номер группы процессов, который равен номеру PID лидера группы процессов.
- Процесс может установить только идентификационный номер группы процессов для себя или подпроцесса
Сеанс — это набор из одной или нескольких групп процессов.
Функция setsid () может установить период диалога:
Если процесс, вызывающий setsid, не является лидером группы процессов, эта функция создает новый сеанс 。
(1) Этот процесс становится первым процессом периода диалога
(2) Этот процесс становится лидером процесса новой группы процессов.
(3) В этом процессе нет управляющего терминала. Если у процесса есть управляющий терминал до вызова setsid, контакт с терминалом освобождается. Если процесс является лидером группы процессов, эта функция возвращает ошибку.
(4) Чтобы убедиться в этом, мы сначала вызываем fork (), а затем exit (), в это время работает только дочерний процесс.
Теперь давайте рассмотрим шаги, необходимые для создания демона:
Общие шаги для написания демона:
(1) Выполнить форк и выйти из родительского процесса;
(2) вызовите функцию setsid в дочернем процессе, чтобы создать новый сеанс;
(3) вызовите функцию chdir в дочернем процессе, чтобы сделать корневой каталог «/» рабочим каталогом дочернего процесса;
(4) Вызовите функцию umask в подпроцессе и установите для umask процесса значение 0;
(5) Закройте все ненужные файловые дескрипторы в дочернем процессе
1. Запустите в фоновом режиме.
Чтобы избежать приостановки управляющего терминала, поместите Daemon в фоновый режим для выполнения. Метод заключается в вызове fork процесса, чтобы завершить родительский процесс и позволить Daemon выполняться в фоновом режиме в дочернем процессе.
if(pid=fork())
exit (0); // Это родительский процесс, завершить родительский процесс, дочерний процесс продолжается
2. Выйдите из терминала управления и войдите в сеанс и группу процессов.
Необходимо сначала представить взаимосвязь между процессом и управляющим терминалом в Linux, сеансом входа в систему и группой процессов: процесс принадлежит группе процессов, а номер группы процессов (GID) является лидером группы процессов Идентификатор процесса (PID). Сеанс входа может содержать несколько групп процессов. Эти группы процессов имеют общий управляющий терминал. Этот управляющий терминал обычно является терминалом входа в систему, который создает процесс.
Терминал управления, сеанс входа в систему и группа процессов обычно наследуются от родительского процесса. Наша цель — избавиться от них и сделать их невосприимчивыми к их влиянию. Метод заключается в вызове setsid () на основе пункта 1, чтобы сделать процесс лидером сеанса:
setsid();
Объяснение: Когда процесс является лидером сеанса, вызовы setsid () не выполняются. Но первый пункт гарантировал, что процесс не является лидером сессии. После успешного вызова setsid () процесс становится новым лидером сеанса и новым лидером процесса и отделяется от исходного сеанса входа в систему и группы процессов. Вследствие исключительности процесса разговора с управляющим терминалом процесс отделяется от управляющего терминала одновременно.
3. Запретить процессу повторное открытие терминала управления
Теперь процесс стал лидером терминала в сеансе без терминала. Но он может повторно открыть контрольный терминал. Вы можете запретить процессу повторное открытие терминала управления, сделав процесс больше не лидером сеанса:
if(pid=fork())
exit (0); // Завершаем первый дочерний процесс, второй дочерний процесс продолжается (второй дочерний процесс больше не является лидером сеанса)
4. Закройте дескриптор открытого файла
Процесс наследует дескриптор открытого файла от родительского процесса, который его создал. Если он не закрыт, системные ресурсы будут потрачены впустую, что приведет к размонтированию файловой системы, в которой расположен процесс, и к непредсказуемым ошибкам. Закройте их следующим образом:
для (i = 0; я закрываю дескриптор открытого файла close (i);>
5. Изменить текущий рабочий каталог
Когда процесс активен, файловая система, в которой находится его рабочий каталог, не может быть размонтирована. Как правило, вам нужно изменить рабочий каталог на корневой каталог. Для дампов ядра процесс записи рабочего журнала меняет рабочий каталог на определенный каталог, такой как / tmpchdir («/»)
6. Сбросьте маску создания файла
Процесс наследует маску создания файла от родительского процесса, который ее создал. Это может изменить бит доступа к файлу, созданному демоном. Чтобы предотвратить это, очистите маску создания файла: umask (0);
7. Обработка сигнала SIGCHLD
Нет необходимости обрабатывать сигналы SIGCHLD. Но для некоторых процессов, особенно для процесса сервера, он часто генерирует подпроцессы для обработки запроса при поступлении запроса. Если родительский процесс не ожидает завершения дочернего процесса, дочерний процесс станет процессом зомби (zombie) и займет системные ресурсы. Если родительский процесс ожидает завершения дочернего процесса, это увеличит нагрузку на родительский процесс и повлияет на одновременную производительность серверного процесса. В Linux вы можете просто установить действие сигнала SIGCHLD на SIG_IGN.
signal(SIGCHLD,SIG_IGN);
Таким образом, ядро не будет генерировать процесс зомби в конце дочернего процесса. Это отличается от BSD4, который должен явно дождаться завершения дочернего процесса, прежде чем выпускать процесс зомби.
Три, создайте демон
Перед созданием давайте разберемся с использованием setsid ():
DESCRIPTION
setsid() creates a new session if the calling process is not a process
group leader . The calling process is the leader of the new session ,
the process group leader of the new process group, and has no control-
ling tty . The process group ID and session ID of the calling process
are set to the PID of the calling process . The calling process will be
the only process in this new process group and in this new session .
// Вызывающий процесс должен быть не текущим лидером группы процессов. После вызова генерируется новый период сеанса, и в период сеанса существует только одна группа процессов, и лидер группы процессов является вызывающим процессом без управляющего терминала. И идентификатор сеанса установлен на PID вызывающего процесса
RETURN VALUE
On success, the (new) session ID of the calling process is returned.
On error, (pid_t) -1 is returned, and errno is set to indicate the
error.
Теперь создайте демон согласно приведенным выше шагам:
Следующая программа предназначена для создания демона, а затем с помощью этого демона каждую минуту записывает текущее время в файл daemon.log
Результаты показывают, что когда я выполняю a.out как обычный пользователь, вновь созданный демон не появляется в таблице процессов, но когда я выполняю как пользователь root, он успешно выполняется, и файл daemon.log создается в каталоге /, После просмотра кошки это действительно пишется раз в минуту. Почему он может выполняться только пользователем root, потому что когда мы создали процесс демона, мы переключили текущий каталог на каталог my /, поэтому, когда я позже создаю файл daemon.log, он фактически находится в каталоге /. Разрешения, может быть, вы спросите, почему это не так? На самом деле, есть ошибка, но мы закрыли стандартный ввод и перенаправили на / dev / null при создании демона, поэтому мы не можем увидеть сообщение об ошибке.
В-четвертых, используйте библиотечную функцию daemon () для создания демона
Фактически, мы можем использовать функцию daemon () для создания процесса-демона, прототип функции:
int daemon(int nochdir, int noclose);
DESCRIPTION
The daemon() function is for programs wishing to detach themselves from
the controlling terminal and run in the background as system daemons.
If nochdir is zero, daemon() changes the process’s current working
directory to the root directory («/»); otherwise,
If noclose is zero, daemon() redirects standard input, standard output
and standard error to /dev/null; otherwise, no changes are made to
these file descriptors.
Функция: Создать демон
nochdir: = 0 меняет текущий каталог на «/»
noclose: = 0 перенаправить стандартный ввод, стандартный вывод, стандартную ошибку в «/ dev / null»
Теперь мы используем daemon (), чтобы переписать программу прямо сейчас:
Результат такой же, как и раньше, только root может преуспеть, обычные пользователи не могут видеть сообщение об ошибке при выполнении
Теперь позвольте daemon (0,1), только не закрывайте стандартные результаты ввода и вывода:
Вы можете увидеть сообщение об ошибке
Теперь давайте daemon (1,0), он не перенаправлен, результат выглядит следующим образом:
На этот раз обычный пользователь преуспел, думая, что он не переключился в каталог / и имеет разрешения
Фактически, мы можем использовать daemon () по умолчанию, который мы только что создали, для создания программы процесса демона:
Код выглядит следующим образом:
Демон — это особый процесс, работающий в фоновом режиме. Он не зависит от терминала управления и периодически выполняет определенные задачи или ожидает определенных событий. Демон очень полезный процесс.
1. Самая важная особенность демона — запуск в фоновом режиме.
2. Демон должен быть изолирован от среды перед запуском. Эти среды включают в себя открытые дескрипторы файлов, управляющие терминалы, сеансы и группы процессов, рабочие каталоги и маски создания файлов. Эти среды обычно наследуются демоном от его родительского процесса (особенно оболочки).
3. Способ запуска демона особенный. Он может быть запущен из сценария запуска /etc/rc.d при запуске системы Linux, может быть запущен crond процесса планирования работы или может быть выполнен пользовательским терминалом (оболочкой).
Короче говоря, кроме этих специальностей, процесс-демон практически не отличается от обычного процесса. Поэтому написание демона фактически превращает обычный процесс в демон в соответствии с характеристиками демона, описанными выше. Если у вас есть более глубокое понимание процесса, его легче понять и запрограммировать.
Правила программирования демонов
(1) Первое, что нужно сделать, это вызвать umask, чтобы установить для слова маски создания режима файла значение 0.
Маска прав доступа к файлу: означает блокировку соответствующего бита в праве доступа к файлу. Например, существует маска прав доступа к файлу 050, которая блокирует права на чтение и выполнение для владельца группы файлов (соответствует двоичному, rwx, 101). Поскольку дочерний процесс, созданный функцией fork, наследует маску разрешений файла родительского процесса, это вызывает большие проблемы для дочернего процесса при использовании файла. Таким образом, установка маски прав доступа к файлу на 0 (то есть не блокирование каких-либо разрешений) может повысить гибкость демона. Функция установки маски прав доступа к файлам — umask. Обычное использование — это umask (0).
(2) Вызовите fork, а затем завершите родительский процесс (выход). if(pid=fork()) exit(0);
(3) Вызовите setsid для создания нового сеанса и выхода из управляющего терминала и группы процессов. Роль функции setsid: используется для создания нового разговора и выступает в качестве лидера группы разговоров.
Вызов setsid имеет три функции: (a) позволить процессу избавиться от исходного управления сеансом, (b) позволить процессу избавиться от исходного управления группой процессов, (c) позволить процессу избавиться от исходного управления терминалом управления setsid()
Цель использования функции setsid: поскольку первым шагом создания процесса-демона является вызов функции fork для создания дочернего процесса, а затем выход из родительского процесса. Когда вызывается функция fork, дочерний процесс копирует период сеанса, группу процессов, управляющий терминал и т. Д. Родительского процесса. Хотя родительский процесс завершается, период сеанса, группа процессов, управляющий терминал и т. Д. Не изменились, поэтому это не так Независимость открылась в смысле. После использования функции setsid процесс может быть полностью независимым, чтобы избавиться от контроля над другими процессами.
(4) Измените текущий рабочий каталог на корневой каталог. #define NOFILE 256 for(i=0;i
(5) Закройте файловые дескрипторы, которые больше не нужны. Это приводит к тому, что демон больше не содержит определенные файловые дескрипторы, унаследованные от его родительского процесса (родительский процесс может быть процессом оболочки или каким-либо другим процессом).
(6) Некоторые демоны открывают / dev / null, чтобы иметь файловые дескрипторы 0, 1 и 2, так что любая библиотечная процедура, которая пытается прочитать стандартный ввод, записать стандартный вывод и стандартную ошибку, не будет иметь никакого эффекта. Поскольку демон не связан с терминальным устройством, его выходные данные не могут быть отображены на терминальном устройстве, и некуда принимать входные данные от интерактивных пользователей.
Источник