Смотреть в Telegram
Демоны в Linux Демон - это процесс, обладающий длинным жизненным циклом. Часто демоны создаются на этапе загрузки системы и работают до момента ее выключения. Выполняется они в фоновом режиме, не имеют контролирующего терминала и обычно не привязаны к конкретной пользовательской сессии. Примеры системных демонов У каждого системного демона есть своя микроцель существования. Одни контролируют сетевые соединения, другие отвечают за взаимодействие между приложениями по системе dbus. Примерами популярных демонов являются: 1) cron — демон, который выполняет команды в запланированное время; 2) sshd — демон, который отвечает за обработку SSH-подключений; 3) httpd — демон HTTP-сервера (Apache), который обслуживает веб-страницы; Вы можете и сами "поймать" демонов через различные утилиты: ps, top, pstree. Базовыми отличительными параметрами таких процессов являются имя, которое заканчивается на 'd', родительский процесс init и отсутствующий терминал:
$ ps -o pid,ppid,cmd

PID    PPID CMD
1239    1 /usr/lib/snapd/snapd  
1250    1 /usr/libexec/udisks2/udisksd
Дополнительно хочется отметить, что процессам-демонам присуща особенность, которая гарантирует, что ядро не сможет генерировать для них никаких сигналов, связанных с терминалом (SIGINT, SIGTSTP и SIGHUP). Создание демона Глобально существует 2 типа демонов: "SysV Daemons" и "New-Style Daemons". Первый тип является традиционным и преимущественно использовался до появления systemd. Второй, в свою очередь, опирается на инфраструктуру systemd и является сервисом. Сейчас не будем вдаваться в принцип работы сервисов и рассмотрим инициализацию каноничного SysV демона. Для того, чтобы стать демоном, программа должна выполнить следующие шаги: 1. Сделать вызов fork(), после которого родитель завершается, а потомок продолжает работать. Это нужно для отделения демона от терминала, из которого он был запущен. В результате, процесс становится потомком для init:
pid_t pid = fork();

if (pid < 0)
    exit(EXIT_FAILURE);

if (pid > 0)
    exit(EXIT_SUCCESS); 
2. Дочерний процесс вызывает setsid(), чтобы начать новую сессию, стать ее лидером и разорвать любые связи с контролирующим терминалом:
if (setsid() < 0)
    exit(EXIT_FAILURE);
3. Проигнорировать сигнал SIGHUP для того, чтобы не завершиться при закрытии терминала, внутри которого был воспроизведен запуск:
signal(SIGHUP, SIG_IGN);
4. Повторно выполнить fork(). Этот шаг иногда выполняется для предотвращения возможности захвата вновь созданного демона новым управляющим терминалом. 5. Очистить атрибут umask, чтобы файлы и каталоги, созданные демоном, имели запрашиваемые права доступа, указанные в вызовах open() и mkdir():
umask(0);
6. Поменять текущий рабочий каталог процесса (обычно на корневой). Это необходимо для исключения блокировки файловой системы и возможности, в случае необходимости, сделать для нее unmount:
chdir("/");
7. Закрыть все открытые файловые дескрипторы, которые демон унаследовал от своего родителя. Поскольку демон потерял свой контролирующий терминал и работает в фоновом режиме, ему больше не нужно хранить дескрипторы с номерами 0, 1 и 2, их тоже закрываем:
for (int x = sysconf(_SC_OPEN_MAX); x>=0; x--)
    close (x);
8. Переоткрыть дескрипторы STDIN, STDOUT, STDERR и перенаправить стандартные потоки в виртуальное устройство "/dev/null". Данный шаг необходим по нескольким причинам. Во-первых, вновь открытые файлы неизбежно возьмут себе минимально доступный порядковый номер (0, 1, 2 ...), что может привести к нежелательным записям со стороны функций, которые работают с этими дескрипторами. Во-вторых, данное действие позволяет избежать ошибок при вызове библиотечных функций, которые выполняют операции ввода/вывода с этими дескрипторами:
int fd0 = open("/dev/null", O_RDWR); 
int fd1 = dup(0); 
int fd2 = dup(0);
9. Запустить основной цикл, в котором демон будет выполнять свою работу:
while (1) {
}
Linux++ | IT-Образование
Love Center
Love Center
Бот для знакомств