2012-01-08 8 views
21

Cuando trataba de un demonio de bajo Linux usando C, me dijeron que debería añadir siguiente código después de tenedor bloque de código:¿Por qué DEBE desconectarse de tty cuando escribe un demonio de Linux?

/* Preparations */ 
... 

/* Fork a new process */ 
pid_t cpid = fork(); 
if (cpid == -1){perror("fork");exit(1);} 
if (cpid > 0){exit(0);} 

/* WHY detach from tty ? */ 
int fd = open("/dev/tty", O_RDWR); 
ioctl(fd, TIOCNOTTY, NULL); 

/* Why set PGID as current PID ? */ 
setpgid(getpid(), 0); 

Mi pregunta es: ¿Hay una necesidad de hacer las operaciones anteriores ?

+0

Creo que parte de la razón es que no se espera que un daemon escriba la salida o la entrada de lectura. Si tuviera que comenzar, p. un servidor HTTP en una sesión SSH, no esperaría salida de advertencia aleatoria más adelante en la sesión. –

+1

@JohnChadwick Lo que estás diciendo es de hecho una de las cosas que quieres hacer mientras te transformas en un daemon, pero lo logras al cerrar stdin, stdout y stderr. Se desconecta del terminal para evitar ciertas señales (ver respuestas a continuación). –

+1

¿Puedes "dejar de aceptar" mi respuesta y aceptar @ AdamZalcman's en su lugar? Él hace un trabajo mucho mejor que yo. Y él tiene toda la razón sobre setsid(), deberías usar eso. – fge

Respuesta

34

Debe desasociar su proceso de daemon del terminal para evitar que se envíen señales relacionadas con el funcionamiento del terminal (como SIGHUP cuando finaliza la sesión de terminal, así como potencialmente SIGTTIN y SIGTTOU).

Sin embargo, tenga en cuenta que la forma de desvincularse del terminal con TIOCNOTTY ioctl es en gran parte obsoleta. Deberías usar setsid() en su lugar.

El motivo por el cual un daemon abandona su grupo de proceso original no es para recibir las señales enviadas a ese grupo. Tenga en cuenta que setsid() también coloca su proceso en su propio grupo de procesos.

+2

+1 para 'setsid()' – fge

+0

+1 para una respuesta muy buena y completa, especialmente el "¿por qué lo hacemos?" parte. –

+0

+1. Advertencia: incluso después de setsid (2) es posible adquirir un terminal de control si no se tiene cuidado (fork() otra vez u O_NOCTTY). – pilcrow

10

La otra respuesta es clara y técnicamente correcta (y por eso subí en consecuencia).

Otra respuesta es: "No, no escriba el código que se demoniza a sí mismo".

usar en su lugar un marco de supervisión del proceso (como daemontools o runit o launchd) que se encarga de esto para usted. El servidor UNIX tradicional es autodestructivo y, como tal, se preocupa por muchas cosas: directorio de trabajo actual, grupo de procesos y independencia de sesión, máscaras de señal y disposición, raíz del sistema de archivos, privilegios, umask, descriptores de archivos abiertos, etc.

Sin embargo, la mayoría o todos estos atributos de proceso se heredan a través de exec(), lo que significa que un proceso de servidor normalmente puede "nacer" con el grupo de proceso deseado, directorio de trabajo, raíz, etc. Hay poca necesidad de hacer todo usted mismo , aunque a menudo tendrá que administrar las operaciones privilegiadas y la revocación de privilegios usted mismo.

(De hecho, yo diría que hay un riesgo a largo plazo al escribir programas de autodiagnóstico. Las rutinas repetitivas de "fondo" se copian y pegan, se transfieren apresuradamente y el programador pasa tiempo en el código auxiliar en lugar de en el principal propósito del programa.)

+0

¡Gran respuesta!Daemonizing debe ser la elección de la persona que llama, no forzada por la aplicación en sí misma. Y para quien llama, hay muchas herramientas existentes, no es necesario volver a inventarlas en la aplicación. –

Cuestiones relacionadas