Демоните са процеси, които не се изпълняват директно под контрола на потребителя, а служат във фонов режим. Обикновено те започват при стартиране на системата и работят непрекъснато, докато системата се изключи. Единствената разлика между тези и нормалните процеси е, че те не изпращат съобщения до конзолата или екрана по никакъв начин.

Ето как можете да създадете демон на Linux машина.

Кратко въведение в това как се създават демони

Много демони работят в системата и някои познати примери за демони са както следва:

  • crond: Прави командите да се изпълняват в определеното време
  • sshd: Позволява влизане в системата от отдалечени машини
  • httpd: Обслужва уеб страници
  • nfsd: Позволява споделяне на файлове през мрежата

Също така, демон процесите обикновено се именуват така, че да завършват с буквата д, въпреки че не е задължително.

За да работи процес като демон, се следва следният път:

  • Първоначалните операции, като четене на конфигурационни файлове или получаване на необходимите системни ресурси, трябва да се извършат, преди процесът да стане демон. По този начин системата може да докладва получените грешки на потребителя и процесът ще бъде прекратен с подходящ код за грешка.
    instagram viewer
  • Създава се фонов процес с init като негов родителски процес. За тази цел първо се разклонява подпроцес от процеса init, а след това горният процес се прекратява с изход.
  • Нова сесия трябва да се отвори чрез извикване на функцията setsid и процесът трябва да бъде изключен от терминала.
  • Всички дескриптори на отворени файлове, наследени от родителския процес, са затворени.
  • Стандартен вход, изход, а съобщенията за грешки се пренасочват към /dev/null.
  • Работната директория на процеса трябва да се промени.

Какво представляват сесиите на Daemon?

След като влязат в системата чрез терминал, потребителите могат да стартират много приложения чрез програмата shell. Тези процеси трябва да се затворят, когато потребителят излезе от системата. Операционната система групира тези процеси в групи сесии и процеси.

Всяка сесия се състои от групи процеси. Можете да опишете тази ситуация по следния начин:

Терминалът, където процесите получават своите входове и изпращат своите изходи, се нарича контролен терминал. Контролиращ терминал е свързан само с една сесия в даден момент.

Една сесия и групите процеси в нея имат идентификационни (ID) номера; тези идентификационни номера са идентификационните номера на процеса (PID) на ръководителите на сесията и групата на процесите. Дъщерният процес споделя същата група като неговия родителски процес. Когато има множество процеси комуникация с тръбния механизъм, първият процес става лидер на групата на процеса.

Създаване на демон процес в Linux

Тук ще видите как можете да създадете демон функция. За тази цел ще създадете функция с име _daemon. Можете да започнете с именуване на кода на приложението, което ще работи като демон като тест.в, и кода, като ще създадете функцията демон daemon.c.

//test.c
#включи <stdio.h>
международен_daemon(международен, международен);
международенглавен()
{
getchar();
_daemon (0, 0);
getchar();
връщане0;
}
//daemon.c
#включи <sys/types.h>
#включи <sys/stat.h>
#включи <stdlib.h>
#включи <stdio.h>
#включи <fcntl.h>
#включи <unistd.h>
#включи <linux/fs.h>
#включи <linux/limits.h>
международен_daemon(международен nochdir, международен затвори){
pid_t pid;
pid = вилица (); // Разклоняване на родителския процес
ако (pid < 0) {
изход(EXIT_FAILURE);
}
ако (pid > 0) {
изход(ИЗХОД_УСПЕХ);
}
връщане0;
}

За да създадете демон, имате нужда от фонов процес, чийто родителски процес е init. В кода по-горе, _daemon създава дъщерен процес и след това убива родителския процес. В този случай вашият нов процес ще бъде подпроцес на init и ще продължи да работи във фонов режим.

Сега компилирайте приложението със следната команда и проверете състоянието на процеса преди и след _deamon е наречен:

gccтесттест.° Сдемон.° С

Стартирайте приложението и превключете към друг терминал, без да натискате други клавиши:

./тест

Можете да видите, че стойностите, свързани с вашия процес, са както следва. Тук ще трябва да използвате командата ps, за да получите информация, свързана с процеса. В този случай, _daemon функцията все още не е извикана.

ps -C тест -o "pid ppid pgid sid tty статистикакоманда"
# Изход
PID PPID PGID SID TT STAT COMMAND
10296 5119 10296 5117 точки/2 S+ ./тест

Когато погледнете в СТАТИСТИКА поле, виждате, че вашият процес се изпълнява, но чака да настъпи събитие извън графика, което ще го накара да работи на преден план.

Съкращение смисъл
С Изчакване на сън да се случи събитие
т Приложението спря
с Водач на сесията
+ Приложението работи на преден план

Можете да видите, че родителският процес на вашето приложение е обвивката, както се очаква.

ps -jp 5119 
# Изход
PID PGID SID TTY TIME CMD
5119 5119 5117 точки/2 00:00:02 zsh

Сега се върнете към терминала, където изпълнявате приложението си, и натиснете Въведете да се позове на _daemon функция. След това погледнете отново информацията за процеса на другия терминал.

ps -C тест -o "pid ppid pgid sid tty статистикакоманда"
# Изход
PID PPID PGID SID TT STAT COMMAND
22504 1 22481 5117 точки/2 S ./тест

На първо място, можете да кажете, че новият подпроцес работи във фонов режим, тъй като не виждате + характер в СТАТИСТИКА поле. Сега проверете кой е родителският процес на процеса, като използвате следната команда:

ps -jp 1 
​​​​​​​# Изход
PID PGID SID TTY TIME CMD
1 1 1? 00:00:01systemd

Вече можете да видите, че родителският процес на вашия процес е systemd процес. По-горе беше споменато, че за следващата стъпка трябва да се отвори нова сесия и процесът да бъде изключен от контролния терминал. За това използвате функцията setsid. Добавете това обаждане към вашето _daemon функция.

Част от кода за добавяне е както следва:

if (setsid() == -1) 
връщане-1;

Сега, след като сте проверили състоянието преди _daemon наречен, сега можете да премахнете първия getchar функция в тест.в код.

//test.c
#включи <stdio.h>
международен_daemon(международен, международен);
международенглавен()
{
_daemon (0, 0);
getchar();
връщане0;
}

След като компилирате и стартирате приложението отново, отидете на терминала, където сте направили вашите отзиви. Новото състояние на вашия процес е както следва:

ps -C тест -o "pid ppid pgid sid tty статистикакоманда"
​​​​​​​# Изход
PID PPID PGID SID TT STAT COMMAND
25494 1 25494 25494? Ss ./тест

В ? влезте в TT поле показва, че вашият процес вече не е свързан с терминал. Забележете, че PID, PGID, и SID стойностите на вашия процес са еднакви. Вашият процес вече е лидер на сесията.

В следващата стъпка променете работната директория на основната директория според стойността на аргумента, който сте предали. Можете да добавите следния фрагмент към _daemon функция за това:

if (!nochdir) {
ако (chdir("/") == -1)
връщане-1;
}

Сега, според предадения аргумент, всички файлови дескриптори могат да бъдат затворени. Добавете следния код към _daemon функция:

#define NR_OPEN 1024
ако (!noclose) {
за (i = 0; и < NR_OPEN; i++)
затвори (i);
отворен("/dev/нула", O_RDWR);
дуп (0);
дуп (0);
}

След като всички файлови дескриптори бъдат затворени, новите файлове, отворени от демон, ще бъдат показани съответно с дескриптори 0, 1 и 2. В този случай, например, printf командите в кода ще бъдат насочени към втория отворен файл. За да се избегне това, първите три идентификатора сочат към /dev/null устройство.

В този случай крайното състояние на _daemon функцията ще бъде както следва:

#включи <sys/types.h>
#включи <sys/stat.h>
#включи <stdio.h>
#включи <stdlib.h>
#включи <fcntl.h>
#включи <errno.h>
#включи <unistd.h>
#включи <syslog.h>
#включи <низ.ч>
международен_daemon(нищожен){
// PID: ID на процеса
// SID: ID на сесията
pid_t pid, sid;
pid = вилица (); // Разклоняване на родителския процес
ако (pid < 0) {
изход(EXIT_FAILURE);
}
ако (pid > 0) {
изход(ИЗХОД_УСПЕХ);
}
// Създайте а SIDзадете
sid = setsid();
ако (сид < 0) {
// НЕУСПЕХА
изход(EXIT_FAILURE);
}
ако ((chdir("/")) < 0) {
// НЕУСПЕХА
изход(EXIT_FAILURE);
}
затваряне (STDIN_FILENO);
затваряне (STDOUT_FILENO);
затваряне (STDERR_FILENO);
докато (1) {
// Някои задачи
сън (30);
}
изход(ИЗХОД_УСПЕХ);
}

Ето пример за фрагмент от код, който изпълнява sshd приложение като а демон:

...
if (!(debug_flag || inetd_flag || no_daemon_flag)) {
международен fd;
if (демон (0, 0) < 0)
фатално ("daemon() неуспешно: %.200s", strerror (errno));
/* Прекъсване на връзката с управляващия tty. */
fd = отворен (_PATH_TTY, O_RDWR | O_NOCTTY);
ако (fd >= 0) {
(нищожен) ioctl (fd, TIOCNOTTY, NULL);
затваряне (fd);
}
}
...

Демоните са важни за системното програмиране на Linux

Демоните са програми, които изпълняват различни действия по предварително дефиниран начин, зададен в отговор на определени събития. Те работят безшумно на вашата Linux машина. Те не са под директния контрол на потребителя и всяка услуга, работеща във фонов режим, има своя демон.

Важно е да овладеете демони, за да научите структурата на ядрото на операционната система Linux и да разберете работата на различни системни архитектури.

Какво е демон?

Прочетете Следващото

ДялтуитДялелектронна поща

Свързани теми

  • Linux
  • Linux ядро
  • Програмиране
  • C Програмиране

За автора

Фатих Кючуккаракурт (Публикувани 5 статии)

Инженер и разработчик на софтуер, който е фен на математиката и технологиите. Винаги е харесвал компютрите, математиката и физиката. Той е разработил проекти на двигатели за игри, както и машинно обучение, изкуствени невронни мрежи и библиотеки с линейна алгебра. Освен това продължава да работи върху машинно обучение и линейни матрици.

Още от Fatih Küçükkarakurt

Абонирайте се за нашия бюлетин

Присъединете се към нашия бюлетин за технически съвети, ревюта, безплатни електронни книги и ексклузивни оферти!

Щракнете тук, за да се абонирате