¿Por qué bifurcar () dos veces? [duplicate]

6 minutos de lectura

avatar de usuario
DerMike

Nagios me deja configurar child_processes_fork_twice=<0/1>.

los documentación dice

Esta opción determina si Nagios bifurcará o no los procesos secundarios dos veces cuando ejecute comprobaciones de host y servicio. De forma predeterminada, Nagios bifurca () dos veces. Sin embargo, si la opción use_large_installation_tweaks está habilitada, solo se bifurcará () una vez.

Por lo que sé fork() generará un nuevo proceso hijo. ¿Por qué querría hacer eso dos veces?

  • @larsmans Gracias por ese enlace. No estaba en mi lista cuando estaba investigando la pregunta primero. Acabo de aprender mucho allí y coloqué algunos votos a favor.

    – DerMike

    7 junio 2012 a las 13:31

avatar de usuario
nj-ath

Muy bien, primero que nada: ¿qué es un proceso zombi?

Es un proceso que está muerto, pero su padre estaba ocupado haciendo otro trabajo, por lo que no pudo recopilar el estado de salida del hijo.

En algunos casos, el niño corre durante mucho tiempo, el padre no puede esperar tanto tiempo y continuará con su trabajo (tenga en cuenta que el padre no muere, pero continúa con sus tareas restantes pero no se preocupa por el niño ).

De esta manera, se crea un proceso zombie.

Ahora vayamos al grano. ¿Cómo ayuda bifurcar dos veces aquí?

Lo importante a tener en cuenta es que el nieto hace el trabajo que el proceso padre quiere que haga su hijo.

Ahora, la primera vez que se llama bifurcación, el primer niño simplemente vuelve a bifurcar y sale. De esta forma, el padre no tiene que esperar mucho tiempo para recopilar el estado de salida del hijo (ya que el único trabajo del hijo es crear otro hijo y salir). Entonces, el primer hijo no se convierte en un zombi.

En cuanto al nieto, su padre ya ha muerto. Por lo tanto, el nieto será adoptado por el init proceso, que siempre recopila el estado de salida de todos sus procesos secundarios. Entonces, ahora el padre no tiene que esperar mucho y no se creará ningún proceso zombie.

Hay otras formas de evitar un proceso zombi; esta es solo una técnica común.

¡Espero que esto ayude!

  • ah Las relaciones son complicadas. Y enit es un alma bondadosa para adoptar a los nietos.

    – CubicleSoft

    14 mayo 2016 a las 14:27

En Linux, un demonio generalmente se crea bifurcando dos veces con el proceso intermedio saliendo después de bifurcar al nieto. Esto tiene el efecto de dejar huérfano el proceso del nieto. Como resultado, se convierte en responsabilidad del sistema operativo limpiarlo si finaliza. La razón tiene que ver con lo que se conoce como procesos zombis que continúan viviendo y consumiendo recursos después de salir porque su padre, que normalmente sería el responsable de la limpieza, también ha muerto.

  • No veo cómo esto es mejor que bifurcar solo una vez. Creo que la verdadera razón tiene algo que ver con las sesiones y el control de terminales, no con la huérfana, pero puede que me equivoque…

    – R.. GitHub DEJA DE AYUDAR A ICE

    7 de junio de 2012 a las 15:09

  • La razón principal es que si inicia su daemon en una sesión de inicio de sesión, la doble bifurcación haría que el proceso del daemon tenga init (pid 1) como padre, y cuando cierre la sesión, SIGHUP no matará el proceso. No debería tener nada que ver con el proceso zombi, ya que normalmente la causa principal del proceso zombi es que el proceso principal no está “esperando ()” en el proceso secundario terminado, y el sistema operativo mantiene el valor de retorno del proceso secundario, esperando para que su padre lo consiga. Entonces, en el proceso zombie, el proceso ya se cerró, pero el sistema operativo lo mantiene, por lo que no está realmente muerto, de ahí el nombre zombie.

    – usuario658991

    9 de julio de 2019 a las 17:21

También de la documentación,

Normalmente, Nagios bifurcará () dos veces cuando ejecuta comprobaciones de host y servicio. Esto se hace para (1) garantizar un alto nivel de resistencia contra los complementos que fallan y fallan y (2) hacer que el sistema operativo se encargue de limpiar el proceso del nieto una vez que sale.

Preguntas frecuentes sobre la programación de Unix §1.6.2:

1.6.2 ¿Cómo evito que ocurran?

Debe asegurarse de que su proceso principal llame wait() (o
waitpid(), wait3(), etc.) para cada proceso hijo que termina; o, en algunos sistemas, puede indicarle al sistema que no está interesado en los estados de salida secundarios.

Otro enfoque es fork() dos veces, y hacer que el proceso secundario inmediato salga de inmediato. Esto hace que el proceso nieto quede huérfano, por lo que el proceso init es responsable de limpiarlo. Para el código para hacer esto, vea la función fork2() en la sección de ejemplos.

Para ignorar los estados de salida secundarios, debe hacer lo siguiente (verifique las páginas de manual de su sistema para ver si esto funciona):

     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);

Si esto tiene éxito, entonces el wait() las funciones no pueden funcionar; si alguno de ellos es llamado, esperará hasta todos los procesos secundarios han terminado, luego devuelven el error con errno == ECHILD.

La otra técnica es captar la señal SIGCHLD y hacer que el controlador de señal llame waitpid() o wait3(). Vea la sección de ejemplos para un programa completo.

avatar de usuario
Jain Anjan

Este código demuestra cómo usar el doble fork método para permitir que el proceso nieto sea adoptado por init, sin riesgo de procesos zombie.

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>

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);
    }
}

el padre fork el nuevo proceso hijo, y luego wait para que termine. el niño fork un proceso de nieto, y luego exit(0).

En este caso, el nieto no hace nada excepto exit(0), pero se puede hacer que haga lo que quiera que haga el proceso daemon. El nieto puede vivir mucho tiempo y será reclamado por el init proceso, cuando esté completo.

  • Una explicación estaría bien.

    –Scott Solmer

    29 mayo 2014 a las 16:43


  • Op en realidad pregunta por qué el programa está escrito de la forma en que lo ha escrito.

    – nj-ath

    18/09/2014 a las 15:45

  • @MichaelGaskill gracias por la edición. Eliminaré mi comentario.

    –Ashish Ahuja

    24 de junio de 2016 a las 11:01

  • Una explicación estaría bien.

    –Scott Solmer

    29 mayo 2014 a las 16:43


  • Op en realidad pregunta por qué el programa está escrito de la forma en que lo ha escrito.

    – nj-ath

    18/09/2014 a las 15:45

  • @MichaelGaskill gracias por la edición. Eliminaré mi comentario.

    –Ashish Ahuja

    24 de junio de 2016 a las 11:01

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad