Qual è la ragione per l'esecuzione di una doppia forcella durante la creazione di un demone?

StackOverflow https://stackoverflow.com/questions/881388

  •  22-08-2019
  •  | 
  •  

Domanda

Sto cercando di creare un demone in python. Ho trovato il seguente questione, che ha qualche buon le risorse in esso che sto attualmente seguendo, ma io sono curioso di sapere perché una doppia forcella è necessario. Ho graffiato intorno google e ho trovato un sacco di risorse dichiarando che uno è necessario, ma non è per questo.

Alcuni menzione che è di impedire il demone di acquisire un terminale di controllo. Come sarebbe fare questo senza il secondo bivio? Quali sono le ripercussioni?

È stato utile?

Soluzione

Guardando il codice fa riferimento nella domanda, la giustificazione è:

# Fork a second child and exit immediately to prevent zombies.  This
# causes the second child process to be orphaned, making the init
# process responsible for its cleanup.  And, since the first child is
# a session leader without a controlling terminal, it's possible for
# it to acquire one by opening a terminal in the future (System V-
# based systems).  This second fork guarantees that the child is no
# longer a session leader, preventing the daemon from ever acquiring
# a controlling terminal.

Quindi è di garantire che il demone è ri-imparentato su init (nel caso in cui il processo dando il via il demone è vissuto a lungo), ed elimina ogni possibilità di riacquistare il demone di un terminale di controllo. Quindi, se nessuno di questi casi si applicano, quindi una forchetta dovrebbe essere sufficiente. " Unix Network Programming - Stevens " ha una buona sezione su questo

Altri suggerimenti

Stavo cercando di capire la doppia forcella e incappato in questo problema qui. Dopo un sacco di ricerca questo è quello che ho capito. Speriamo che aiuterà a chiarire meglio le cose per chi ha la stessa domanda.

In Unix ogni processo appartiene ad un gruppo che a sua volta appartiene a una sessione. Ecco la gerarchia ...

Session (SID) → Process Group (pgid) → processo (PID)

Il primo processo nel gruppo processo diventa il leader del gruppo di processo e il primo processo nella sessione diventa il leader di sessione. Ogni sessione può avere uno TTY ad esso associati. Solo un leader sessione può prendere il controllo di un TTY. Per un processo per essere veramente daemonized (RAN in background) dobbiamo garantire che il leader di sessione viene ucciso in modo tale che non v'è alcuna possibilità di sessione mai prendere il controllo del TTY.

Ho eseguito programma demone esempio python di Sander Marechal da questo sito sulla mia Ubuntu. Ecco i risultati con i miei commenti.

1. `Parent`    = PID: 28084, PGID: 28084, SID: 28046
2. `Fork#1`    = PID: 28085, PGID: 28084, SID: 28046
3. `Decouple#1`= PID: 28085, PGID: 28085, SID: 28085
4. `Fork#2`    = PID: 28086, PGID: 28085, SID: 28085

Si noti che il processo è il leader di sessione dopo Decouple#1, perché è PID = SID. Si potrebbe ancora prendere il controllo di un TTY.

Si noti che Fork#2 non è più il PID != SID leader di sessione. Questo processo non può mai prendere il controllo di un TTY. In verità daemonized.

Personalmente trovo terminologia fork-due volte per essere fonte di confusione. Un linguaggio migliore potrebbe essere forcella-disaccoppiare-forcella.

Ulteriori collegamenti di interesse:

A rigor di termini, il doppio della forcella non ha nulla a che fare con la ri-genitorialità il demone come figlio di init. Tutto ciò che è necessario ri-genitore il bambino è che il genitore deve uscire. Questo può essere fatto con una sola forchetta. Inoltre, facendo un doppio forchetta per sé non ri-genitore il processo demone di init; padre del demone deve di uscita. In altre parole, il genitore esce sempre quando si biforcano un demone corretta in modo che il processo demone viene ri-imparentato al init.

Quindi, perché la doppia forcella? POSIX.1-2008 Sezione 11.1.3, " il terminale di controllo", ha la risposta (enfasi aggiunta):

  

Il terminale di controllo per una sessione è assegnato dal leader di sessione in modo definito dall'implementazione. Se un leader di sessione non ha terminale di controllo, e si apre un file di dispositivo terminale che non sia già associato a una sessione senza utilizzare l'opzione O_NOCTTY (vedi open()), è definito dall'implementazione se il terminale diventa il terminale di controllo del leader di sessione. Se un processo che è non è un leader di sessione si apre un file di terminale, o l'opzione O_NOCTTY viene utilizzato su open(), allora che il terminale non deve diventare il terminale di controllo del processo chiamante .

Questo ci dice che se un processo demone fa qualcosa di simile ...

int fd = open("/dev/console", O_RDWR);

... quindi il processo demone potrebbe acquisire /dev/console come il suo terminale di controllo, a seconda che il processo demone è un leader di sessione, e in funzione del sistema di implementazione. Il programma può garanzia che la chiamata di cui sopra non acquisterà un terminale di controllo se il programma assicura prima che non è un leader di sessione.

In genere, quando il lancio di un demone, setsid è chiamato (dal processo figlio dopo aver chiamato fork) per dissociare il demone dal suo terminale di controllo. Tuttavia, chiamando setsid significa anche che il processo chiamante sarà il leader di sessione della nuova sessione, il che lascia aperta la possibilità che il demone potrebbe riacquisire un terminale di controllo. La tecnica della doppia forcella assicura che il processo daemon non è il leader di sessione, che poi garantisce che una chiamata a open, come nell'esempio di cui sopra, non comporterà il processo demone riacquistando un terminale di controllo.

La tecnica della doppia forcella è un po 'paranoico. Potrebbe non essere necessario se si sa che il demone non potrà mai aprire un file di dispositivo terminale. Inoltre, in alcuni sistemi può non essere necessaria anche se il daemon fa aprire un file di dispositivo terminale, dal momento che il comportamento è definito dall'implementazione. Tuttavia, una cosa che non è definito dall'implementazione è che solo un leader di sessione può allocare il terminale di controllo. Se un processo non è un leader di sessione, non può assegnare un terminale di controllo. Pertanto, se si vuole essere paranoici e di essere certo che il processo demone non può inavvertitamente acquisire un terminale di controllo, a prescindere dalla eventuali specifiche di implementazione definita, quindi la tecnica della doppia forcella è essenziale.

Bad CTK :

"Su alcune versioni di Unix, si è costretti a fare un doppio-forchetta all'avvio, al fine di entrare in modalità demone. Questo perché singola biforcazione non è garantito a staccarsi dal controllo del terminale."

Secondo "Programmazione Avanzata nell'ambiente Unix", da Stephens e Rago, la seconda forcella è più una raccomandazione, ed è fatto di garantire che il demone non acquisisce un terminale di controllo sui sistemi System V-based.

Una ragione è che il processo genitore può immediatamente wait_pid () per il bambino, e poi non pensarci più. Quando poi grand-bambino muore, è genitore è init, e attenderà () per esso - e tenendo fuori dallo stato di zombie.

Il risultato è che il processo padre non ha bisogno di essere a conoscenza dei bambini biforcuta, e rende anche possibile la forcella processi in esecuzione lunghe da librerie, ecc.

La chiamata daemon () ha il _exit chiamata genitore () se riesce. La motivazione originale potrebbe essere stato per permettere al genitore di fare un po 'di lavoro extra, mentre il bambino è daemonizing.

Può anche essere basata su una convinzione che è necessario al fine di garantire il demone non ha alcun processo padre ed è reparented a init -., Ma ciò avverrà in ogni caso una volta che il genitore muore nel singolo caso forcella

Quindi suppongo che tutto solo si riduce alla tradizione, alla fine -. Una singola forcella è sufficiente fino a quando il genitore muore in breve tempo in ogni caso

Una discussione decente di apparire per essere a http: // www. developerweb.net/forum/showthread.php?t=3025

Citando mlampkin da lì:

  

... pensare alla chiamata setsid () come il "nuovo" modo di fare cosa (dissociarsi dal terminale) e il [secondo] chiamata fork () dopo che la ridondanza per affrontare lo SVr4 ...

Potrebbe essere più facile da capire in questo modo:

  • La prima forchetta e setsid creerà una nuova sessione (ma l'ID del processo == ID di sessione).
  • Il secondo bivio si assicura l'ID del processo! = ID di sessione.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top