Почему fork () дважды

Nagios позволяет мне настроить child_processes_fork_twice= .

В документации говорится:

Этот параметр определяет, обрабатывает ли Nagios дочерний процесс fork () дважды, когда он выполняет проверки хоста и службы. По умолчанию Nagios fork () s дважды. Однако если параметр use_large_installation_tweaks включен, он будет только fork () один раз.

Насколько я знаю, fork() создаст новый дочерний процесс. Зачем мне это делать дважды?

В Linux демона обычно создаются путем разворачивания дважды с промежуточным процессом, выходящим после раздвоения внука. Это приводит к сиротству процесса внука. В результате, ОС становится ответственным за очистку после нее, если она завершается. Причина связана с тем, что известно как зомби-процессы, которые продолжают жить и потребляют ресурсы после выхода, поскольку их родитель, который обычно несет ответственность за очистку, также умер.

Хорошо, так что теперь, прежде всего: что такое зомби-процесс?

Это процесс, который мертв, но его родитель был занят другой работой, поэтому он не смог собрать статус выхода ребенка.

В некоторых случаях ребенок работает очень долго, родитель не может дождаться этого долгого времени и продолжит свою работу (обратите внимание, что родитель не умирает, но продолжает свои оставшиеся задачи, но не заботится о ребенке ).

Таким образом, создается зомбический процесс.

Теперь давайте приступим к делу. Как разворачивается двойная помощь здесь?

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

Теперь вызывается первый вилка, первый ребенок просто разворачивается и выходит. Таким образом, родитель не должен долго ждать, чтобы получить статус выхода ребенка (поскольку единственным заданием ребенка является создание другого ребенка и выход). Итак, первый ребенок не становится зомби.

Что касается внука, его родитель уже умер. Следовательно, внук будет принят процессом init , который всегда собирает статус выхода всех его дочерних процессов. Итак, теперь родитель не должен ждать очень долго, и никакой зомби-процесс не будет создан.

Есть и другие способы избежать зомбического процесса; это всего лишь обычная техника.

Надеюсь это поможет!

Также из документации ,

Обычно Nagios будет fork () дважды, когда он выполняет проверки хоста и службы. Это делается для того, чтобы (1) обеспечить высокий уровень сопротивления плагинам, которые идут наперекосяк и segfault, и (2) заставить ОС работать с очисткой процесса внука после его выхода.

Unix Programming Faq §1.6.2:

1.6.2 Как я могу предотвратить их появление?

Вы должны убедиться, что ваш родительский процесс вызывает wait() (или waitpid() , wait3() и т. Д.) Для каждого дочернего процесса, который завершает работу; или, в некоторых системах, вы можете проинструктировать систему о том, что вы не заинтересованы в состояниях выхода ребенка.

Другой подход заключается в fork() дважды , и сразу же выйдет сразу же дочерний процесс. Это приводит к тому, что процесс внука становится сиротой, поэтому процесс init отвечает за его очистку. Для этого кода см. Функцию fork2() в разделе примеров.

Чтобы игнорировать дочерние состояния выхода, вам необходимо выполнить следующие действия (проверьте, не работает ли файл вашей системы):

  struct sigaction sa; sa.sa_handler = SIG_IGN; #ifdef SA_NOCLDWAIT sa.sa_flags = SA_NOCLDWAIT; #else sa.sa_flags = 0; #endif sigemptyset(&sa.sa_mask); sigaction(SIGCHLD, &sa, NULL); 

Если это успешно, функции wait() могут работать; если какой-либо из них errno == ECHILD , они будут ждать, пока все дочерние процессы не будут завершены, а затем возвратите ошибку с errno == ECHILD .

Другой метод – захватить сигнал SIGCHLD и wait3() сигнал waitpid() или wait3() . См. Раздел примеров для полной программы.

Этот код демонстрирует, как использовать метод двойной fork чтобы позволить процессу внука стать принятым init, без риска зомби-процессов.

 #include  #include  #include  #include  int main() { pid_t p1 = fork(); if (p1 != 0) { printf("p1 process id is %d", getpid()); wait(); system("ps"); } else { pid_t p2 = fork(); int pid = getpid(); if (p2 != 0) { printf("p2 process id is %d", pid); } else { printf("p3 process id is %d", pid); } exit(0); } } 

Родитель fork новый дочерний процесс, а затем wait его завершения. Ребенок fork процесс внука, а затем exit(0) .

В этом случае внук не делает ничего, кроме exit(0) , но может быть сделан для того, чтобы сделать все, что вам нужно, чтобы выполнить процесс демона. Внук может жить долго и будет восстановлен процессом init , когда он будет завершен.

Interesting Posts
Давайте будем гением компьютера.