Создание демона в среде Linux
Процессы демонов
Процесс демона является процессом фоновой службы, переодически выполняет задачи и ожидает какие либо события.
Как правило демоны запускаются во время загрузки системы.
Чтобы вывести список процессов где есть демоны, необходимо выполнить следующую команду:
ps -ajx
Демоны не привязаны к терминалу, TPGID = -1, UID = 0, родительский процесс PPID = 1 (init)
-j - показать информацию о задании, где TPGID - идентификатор группы процессов переднего плана не связанная с терминалом, TTY - терминал управления, PGID - идентификатор группы процессов, SID - идентификатор сеанса.
-x - показать процессы без управления терминалом
toly@X250:~$ ps -ajx | head -n 1 ; ps -ajx | grep cron
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
1 748 748 748 ? -1 Ss 0 0:01 /usr/sbin/cron -f
22231 2395 2390 22231 pts/2 2390 S+ 1000 0:00 grep --color=auto cron
После входа в систему создается процесс лидер, для лидера и для его дочерних процессов PID = SID
Терминал через который входит пользователь становится управляющим для сеанса.
Процесс лидера сеанса - контроль процесса
1 сеанс 1 терминал
TPGID идентификатор группы процессов, определяет, входит ли процесс в группу процессов связанных с терминалом. Если процесс не связан не с одним терминалом, его значение = -1.
В группе приоритетных процессов(переднего плана) TPGID = PGID, в группе фоновых процессов TPGID != PGID
Чтобы убедиться в этом, запустить две инструкция сначала в фоновом режиме, затем на переднем плане:
ping 127.0.1.1 | grep icmp > temp &
ping 127.0.1.1 | grep icmp
Сравним:
toly@X250:~$ ps -ajx | head -n 1; ps -ajx | grep -e ping -e icmp -e 4857
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
22231 4342 4342 22231 pts/2 4857 S 1000 0:00 ping 127.0.1.1
22231 4857 4857 22231 pts/2 4857 S+ 1000 0:00 ping 127.0.1.1
6097 22231 22231 22231 pts/2 4857 Ss 1000 0:01 bash
Видно что у всех одинаковый SID(один сеанс, одна оболочка) и там где запущен фоновый режим, значение PID отличается от TGPID.
Видно, что bash является лидером сессии и TTY = 22231(PID bash)
Создание процесса демона fork()
Смена рабочей директории демона chdir()
Очистить маску создания файла демоном umask(0)
В языке C:
#include
Если при вызове процесс уже является лидером, тогда функция возвращает ошибку.
При выполнении этой функции создается процесс лидер и его группа процессов, родительский процесс отбрасывается и становится потерянным.
Если процесс был привязан к родительскому терминалу, то терминал также отбрасывается.
В Linux найденный потерянный процесс будет автоматически принят процессом init, причем не обязательно init, в некоторых дистрибутивах, это может быть пользовательский процесс.
Процесс создания демона
Создать дочерний процесс
Создать новый сеанс в дочернем процессе
Как раз таки здесь используется системная функция sedsid()
Идентификатор группы процессов является обязательным атрибутом процесса, снятие этого идентификатора с руководителя группы процессов не повлияет на идентификатор группы процесса.
С начала запуска сеанса все процессы принадлежат одному сеансу.
Вызов sedsid нужен для того чтобы освободить процесс от контроля предыдущего сеанса, удалить процесс из контроля исходной группы процессов, дать процессу выйти из под контроля управляющего терминала.
Пока функция не задействована, предыдущий процесс, группа процессов и управляющий терминал не изменились, поэтому они не являются независимыми и могут контролироваться другими процессами.
Изменить текущий каталог на корневой каталог
Для этого есть функция chdir()
Сбросить маску разрешения файла
Дочерний процесс созданный fork() наследует родительскую маску прав доступа. Для сброса маски используется функция umask()
Закрыть дескриптор файла
Добавить журнал логов
openlog() это функция, которая используется для открытия ссылки на syslog
syslog() функция для формата и приоритета вывода сообщений в журнал
closelog() закрывает ссылку на syslog
syslog служба управления журналами linux
Реализация демона
#include<stdio.h>
#include<fcntl.h>
#include<syslog.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<string.h>
int main()
{
int i, fdes;
char *buffer = "My name is Demon\n";
pid_t pid; //pid_t тип данных для id процесса
pid = fork(); //Выполнение первого шага
if(pid < 0)
{
printf("Error\n");
exit(1);
}
else if(pid > 0)
{
exit(0); //родительский процесс завершается
}
//Открыть ссылку на системный журнал
openlog("syslog-demon", LOG_PID, LOG_DAEMON);
if((setsid()) < 0)
{
syslog(LOG_ERR, "%s\n", "setsid()"); //Выполнение второго шага
exit(1);
}
if((chdir("/")) < 0)
{
syslog(LOG_ERR, "%s\n", "chdir"); //Выполнение третьего шага
exit(1);
}
umask (0); //Выполнение четвертого шага
for(i = 0; i <getdtablesize(); i ++) //Выполнение пятого шага
{
close(i);
}
//Конец создания демона
//Задание демона
while(1)
{
if((fdes = open("/tmp/demon.log", O_CREAT|O_WRONLY|O_APPEND, 0600)) < 0)
{
syslog(LOG_ERR, "%s\n", "open");
exit(1);
}
write(fdes, buffer, strlen(buffer) + 1);
close(fdes);
sleep(5);
}
closelog();
exit(0);
}
Результат выполнения
$ ps -ajx | grep demon1
1219 7000 7000 7000 ? -1 Ss 1000 0:00 ./demon1
1219 7971 7971 7971 ? -1 Ss 1000 0:00 ./demon1
5565 7976 7975 5565 pts/0 7975 S+ 1000 0:00 grep --color=auto demon1
Запуск демона
Для запуска демона необходим сценарий инициализации
Источники
Здесь пока нет комментариев