¿Cómo puedo generar un demonio en uClinux usando vfork?
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.....
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
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
.