2012-01-08 9 views
21

Quando ho provato a scrivere un demone sotto Linux usando C, mi è stato detto che dovrei aggiungere codice seguente dopo forcella blocco di codice:Perché DEVE staccare da tty quando si scrive un daemon 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); 

La mia domanda è: C'è un must per fare le operazioni di cui sopra ?

+0

penso che parte della ragione è che un demone non si prevede di scrivere l'output o di leggere l'input. Se dovessi iniziare, ad es. un server HTTP su una sessione SSH, non ti aspetteresti un avviso di avvertimento casuale più avanti nella sessione. –

+1

@JohnChadwick Quello che stai dicendo è infatti una delle cose che vuoi fare, mentre trasformarsi in un demone, ma a raggiungere questo obiettivo con la chiusura stdin, stdout e stderr. Si scollega dal terminale per evitare determinati segnali (vedere le risposte di seguito). –

+1

Puoi "annullare" la mia risposta e accettare invece @ AdamZalcman's? Fa un lavoro molto migliore di me. E ha pienamente ragione su setsid(), dovresti usarlo. – fge

risposta

34

È necessario dissociare il processo daemon dal terminale per evitare di inviare i segnali relativi al funzionamento del terminale (come SIGHUP quando termina la sessione terminale e potenzialmente SIGTTIN e SIGTTOU).

Si noti tuttavia che il modo di dissociare dal terminale utilizzando TIOCNOTTY ioctl è in gran parte obsoleto. Dovresti usare invece setsid().

Il motivo per cui un daemon lascia il gruppo di processi originale non è quello di ricevere i segnali inviati a quel gruppo. Si noti che setsid() posiziona anche il processo nel proprio gruppo di processi.

+2

+1 per 'setsid()' – fge

+0

+1 per una risposta molto buona e completa, in particolare il "perché lo facciamo?" parte. –

+0

+1. Avvertimento: anche dopo setsid (2) può essere possibile acquisire un terminale di controllo, se non si fa attenzione (fork() di nuovo o O_NOCITY). – pilcrow

10

L'altra risposta è chiara e tecnicamente corretta (e quindi upvoted conseguenza).

Un'altra risposta è: "No, non scrivere il codice che si daemonizes."

usare al posto di un quadro di supervisione processo (come daemontools o runit o launchd) che si occupa di questo per voi.

Il server UNIX tradizionale è auto-daemonizing, e come tale si agita più di molte cose: la directory di lavoro corrente, gruppo di processi e l'indipendenza della sessione, maschere di segnale e la disposizione, radice di filesystem, privilegi, umask, descrittori di file aperti, ecc

Tuttavia, la maggior parte o tutti questi attributi di processo sono ereditati attraverso un exec(), il che significa che un processo server può essere generalmente "nato" con il gruppo di processi desiderato, la directory di lavoro, root, ecc. Non c'è molto bisogno di fare tutto da soli , anche se spesso dovrai ancora gestire le operazioni privilegiate e ottenere la revoca dei privilegi.

(Anzi, direi non c'è rischio a lungo termine per iscritto programmi di auto-daemonizing. Boilerplate "backgrounding" routine vengono copiati e incollati e frettolosamente porting ed estese, e il programmatore passa il tempo sul codice accessorio piuttosto che sul scopo principale del programma.)

+0

Ottima risposta!La demonizzazione dovrebbe essere la scelta del chiamante, non forzata dall'applicazione stessa. E per il chiamante, ci sono molti strumenti esistenti, non c'è bisogno di reinventarlo nell'applicazione. –

Problemi correlati