Pregunta

Esto sería fácil con un tenedor (), pero no tengo MMU. He oído que vfork () bloquea el proceso padre hasta que se salga del niño o ejecuta exec (). ¿Cómo iba a lograr algo como esto:?

pid_t pid = vfork();

if (pid == -1) {
    // fail
    exit(-1);
}

if (pid == 0) {
    // child
    while(1) {
        // Do my daemon stuff
    }

    // Let's pretend it exits sometime
    exit();
} 

// Continue execution in parent without blocking.....
¿Fue útil?

Solución

Parece que no hay manera de hacer esto exactamente como lo tienes aquí. exec o _exit tienen que ser llamado para el padre para continuar la ejecución. O bien poner el código del demonio en otro ejecutable y exec, o utilizar al niño para desovar la tarea original. El segundo enfoque es la manera disimulada, y se describe aquí.

Otros consejos

función

daemon () para sistemas uCLinux sin MMU y tenedor ( ), por Jamie Lokier, en formato parche

No se puede hacer daemon () con vfork (). Para crear algo parecido a un demonio en! MMU usando vfork (), el proceso padre no muere (por lo que hay procesos adicionales), y se debe llamar al demonio en el fondo (es decir, añadiendo Y a la línea de comandos en el shell).

Por otro lado, Linux proporciona clone (). Armado con ese conocimiento y cuidado, es posible implementar daemon () para! MMU. Jamie Lokier tiene una función para hacer precisamente eso en ARM y i386, lo consigue a partir de aquí .

Editar:!. hecho el enlace a demonio de Jamie Lokier () para MMU Linux más prominente

Me habría pensado que este sería el tipo de problema que muchos otros habían topado antes, pero he tenido un tiempo difícil encontrar a alguien hablar de los problemas de "matar al padre".

Al principio pensé que usted debería ser capaz de hacer esto con un (tan, pero algo no) simple llamada a clone, como esto:

pid_t new_vfork(void) {
    return clone(child_func,        /* child function */
                 child_stack,          /* child stack    */
                 SIGCHLD | CLONE_VM,   /* flags */
                 NULL,                 /* argument to child */
                 NULL,                 /* pid of the child */
                 NULL,                 /* thread local storage for child */
                 NULL);                /* thread id of child in child's mem */
}

A excepción de que la determinación de la child_stack y la child_func funcione de la manera que lo hace con vfork es bastante difícil, ya que child_func tendría que ser la dirección de retorno de la llamada clon y la child_stack tendría que ser la parte superior de la pila en el punto de que se hace la llamada al sistema real (sys_clone).

Probablemente se podría tratar de llamar directamente con sys_clone

pid_t new_vfork(void) {
    return sys_clone( SIGCHLD | CLONE_VM, NULL);
}

Lo que creo que podría conseguir lo que quieres. Pasar NULL como el segundo argumento, que es el puntero child_stack, hace que el núcleo hacer lo mismo que lo hace en vfork y tenedor, que es el uso de la misma pila como padre.

Nunca he usado sys_clone directamente y no han probado esto, pero creo que debería funcionar. Creo que:

  sys_clone( SIGCHLD | CLONE_VM | CLONE_VFORK, NULL);

es equivalente a vfork.

Si esto no funciona (y no se puede encontrar la manera de hacer algo similar), entonces usted puede ser capaz de utilizar la llamada clon regular junto con setjump y longjmp llamadas de emularlo, o puede ser capaz de moverse por la necesidad de la semántica del "retorno" de dos veces fork y vfork.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top