214 votes

Quelle est la raison d'effectuer une double fourche lors de la création d'un démon ?

J'essaie de créer un démon en python. J'ai trouvé le fichier question suivante qui contient de bonnes ressources que je suis en train de suivre, mais je suis curieux de savoir pourquoi une double fourchette est nécessaire. J'ai cherché sur Google et j'ai trouvé beaucoup de ressources déclarant qu'une fourche est nécessaire, mais pas pourquoi.

Certains mentionnent que c'est pour empêcher le démon d'acquérir un terminal de contrôle. Comment pourrait-il le faire sans la deuxième fourche ? Quelles sont les répercussions ?

1 votes

4 votes

L'une des difficultés de la double fourche est que le parent ne peut pas facilement obtenir le PID du processus petit-enfant (la balise fork() renvoie le PID de l'enfant au parent, il est donc facile d'obtenir le PID du processus enfant, mais pas si facile d'obtenir le PID du processus petit-enfant ).

209voto

Praveen Gollakota Points 8440

J'essayais de comprendre la double fourchette et je suis tombé sur cette question ici. Après de nombreuses recherches, voici ce que j'ai trouvé. J'espère que cela aidera à clarifier les choses pour ceux qui se posent la même question.

Sous Unix, chaque processus appartient à un groupe qui, à son tour, appartient à une session. Voici la hiérarchie

Session (SID) Groupe de processus (PGID) Processus (PID)

Le premier processus du groupe de processus devient le leader du groupe de processus et le premier processus de la session devient le leader de la session. Chaque session peut être associée à un ATS. Seul un chef de session peut prendre le contrôle d'un ATS. Pour qu'un processus soit réellement démonisé (exécuté en arrière-plan), nous devons nous assurer que le chef de session est tué afin qu'il n'y ait aucune possibilité que la session prenne le contrôle de l'ATS.

J'ai exécuté le programme démon d'exemple python de Sander Marechal à partir de ce site sur mon Ubuntu. Voici les résultats avec mes commentaires.

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

Notez que le processus est le chef de session après Decouple#1 parce que c'est PID = SID . Il peut toujours prendre le contrôle d'un ATS.

Il convient de noter que Fork#2 n'est plus le chef de file de la session PID != SID . Ce processus ne peut jamais prendre le contrôle d'un ATS. Véritablement démonisé.

Personnellement, je trouve que la terminologie "fourchette deux fois" est confuse. Une meilleure expression pourrait être fork-decouple-fork (fourche-découplée-fourche).

Autres liens d'intérêt :

3 votes

Le double bifurcation permet également d'éviter la création de zombies lorsque le processus parent s'exécute plus longtemps et que, pour une raison ou une autre, le gestionnaire par défaut du signal informant que le processus est mort est supprimé.

0 votes

Mais le second peut aussi appeler le découplage et devenir chef de session, puis acquérir le terminal.

3 votes

Ce n'est pas le cas. Le premier fork() empêche déjà la création de zombies, à condition que vous fermiez le parent.

158voto

Dan Moulding Points 46866

Strictement parlant, la double fourche n'a rien à voir avec le fait de re-parenter le démon en tant qu'enfant de init . Pour que l'enfant redevienne parent, il suffit que le parent se retire. Cela peut être fait avec une seule fourche. De même, une double fourche ne permet pas de re-parenter le processus démon à init ; le parent du démon debe sortie. En d'autres termes, le parent quitte toujours le processus lorsqu'il prend la forme d'un démon approprié, de sorte que le processus démon est de nouveau apparenté à init .

Pourquoi cette double fourchette ? POSIX.1-2008 Section 11.1.3, " Le terminal de contrôle "La réponse se trouve dans l'encadré (c'est nous qui soulignons) :

Le terminal de contrôle d'une session est allouée par le chef de session d'une manière définie par la mise en œuvre. Si un chef de session n'a pas de terminal de contrôle et qu'il ouvre un fichier de terminal qui n'est pas déjà associé à une session sans utiliser l'option O_NOCTTY (voir open() ), la question de savoir si le terminal devient le terminal de contrôle du chef de session est définie au niveau de l'implémentation. Si un processus qui est n'est pas un animateur de session ouvre un fichier terminal, ou la touche O_NOCTTY L'option est utilisée sur open() , ce terminal ne devient pas le terminal de contrôle du processus appelant .

Cela nous indique que si un processus démon fait quelque chose comme ceci ...

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

... puis le processus démon pourrait acquérir /dev/console comme terminal de contrôle, selon que le processus démon est un chef de session ou non, et selon l'implémentation du système. Le programme peut garantie que l'appel ci-dessus n'acquiert pas de terminal de contrôle si le programme s'assure d'abord qu'il ne s'agit pas d'un chef de session.

Normalement, lors du lancement d'un démon, setsid est appelé (par le processus enfant après avoir appelé fork ) pour dissocier le démon de son terminal de contrôle. Cependant, l'appel à setsid signifie également que le processus appelant sera le chef de session de la nouvelle session, ce qui laisse ouverte la possibilité que le démon récupère un terminal de contrôle. La technique de la double fourche permet de s'assurer que le processus démon n'est pas le chef de session, ce qui garantit qu'un appel à open comme dans l'exemple ci-dessus, ne permettra pas au processus démon d'obtenir à nouveau un terminal de contrôle.

La technique de la double fourchette est un peu paranoïaque. Elle n'est peut-être pas nécessaire si vous savoir que le démon n'ouvrira jamais un fichier de périphérique de terminal. De plus, sur certains systèmes, il peut ne pas être nécessaire de le faire même si le démon ouvre un fichier de terminal, puisque ce comportement est défini par l'implémentation. Cependant, une chose qui n'est pas définie au niveau de l'implémentation est que seul un chef de session peut allouer le terminal de contrôle. Si un processus n'est pas un chef de session, il ne peut pas allouer un terminal de contrôle. Par conséquent, si vous voulez être paranoïaque et être certain que le processus démon ne peut pas acquérir par inadvertance un terminal de contrôle, quelles que soient les spécificités définies par l'implémentation, la technique de la double fourchette est essentielle.

4 votes

+1 Dommage que cette réponse soit venue ~quatre ans après que la question ait été posée.

23 votes

Mais cela n'explique toujours pas pourquoi il est si important qu'un démon ne puisse pas réacquérir un terminal de contrôle

13 votes

Le mot clé est "acquérir par inadvertance" un terminal de contrôle. Si le processus ouvre un terminal et qu'il devient le terminal de contrôle du processus, si quelqu'un émet un ^C à partir de ce terminal, cela peut mettre fin au processus. Il peut donc être intéressant de protéger un processus contre l'acquisition par inadvertance d'un terminal de contrôle. Personnellement, je m'en tiendrai à un simple fork et à setsid() pour le code que j'écris et dont je sais qu'il n'ouvrira pas de terminal.

124voto

Beano Points 3021

En regardant le code référencé dans la question, la justification est la suivante :

Fourchez un deuxième enfant et sortez immédiatement pour éviter les zombies. Ceci rend le deuxième processus enfant orphelin, ce qui fait que le processus init responsable de son nettoyage. Et un chef de session sans terminal de contrôle, il est possible qu'il d'en acquérir un en ouvrant un terminal à l'avenir (systèmes basés sur le système V). ). Cette deuxième fourche garantit que le fils n'est pas n'est plus un chef de session, empêchant le démon d'acquérir un terminal de contrôle. un terminal de contrôle.

Il s'agit donc de s'assurer que le démon est re-parenté sur init (juste au cas où le processus lançant le démon aurait une longue durée de vie), et d'éliminer tout risque que le démon récupère un tty de contrôle. Si aucun de ces cas ne s'applique, une seule fourche devrait suffire. " Programmation réseau Unix - Stevens "contient une bonne section à ce sujet.

34 votes

Ce n'est pas tout à fait exact. La manière standard de créer un démon est de faire simplement p=fork(); if(p) exit(); setsid() . Dans ce cas, le processus parent se termine également et le premier processus enfant est réparti. La magie de la double fourchette est sólo nécessaire pour empêcher le démon d'acquérir un tty.

1 votes

Donc, si je comprends bien, si mon programme démarre et forks a child ce tout premier processus enfant sera un processus session leader et pourra ouvrir un terminal ATS. Mais si je fork à nouveau à partir de ce fils et que je termine ce premier fils, le second fils forké ne sera pas un session leader et ne pourra pas ouvrir un terminal TTY. Cette affirmation est-elle correcte ?

5 votes

@tonix : le simple fait de forker ne crée pas un chef de session. Cela est fait par setsid() . Ainsi, le premier processus fourchu devient un chef de session après avoir appelé setsid() puis nous nous séparons à nouveau de manière à ce que le processus final à double fourche ne soit plus un chef de session. En dehors de l'exigence de setsid() pour être un animateur de session, vous avez raison.

11voto

Stefan Thyberg Points 1546

Tiré de Mauvais CTK :

"Sur certaines versions d'Unix, vous êtes obligé de faire une double fourche au démarrage, afin de passer en mode démon. Cela est dû au fait qu'une fourche simple n'est pas garantie pour se détacher du terminal de contrôle."

3 votes

Comment se fait-il qu'un simple fork ne se détache pas du terminal de contrôle alors que le double fork le fait ? Sous quels Unixes cela se produit-il ?

13 votes

Un démon doit fermer ses descripteurs de fichiers d'entrée et de sortie (fds), sinon il serait toujours attaché au terminal dans lequel il a été démarré. Un processus forké hérite des fds de son parent. Apparemment, le premier enfant ferme les fds mais cela ne nettoie pas tout. Lors de la deuxième bifurcation, les fds n'existent plus, et le deuxième enfant ne peut donc plus être connecté à quoi que ce soit.

5 votes

@Aaron : Non, un démon se "détache" correctement de son terminal de contrôle en appelant setsid après une première fourchette. Il s'assure ensuite qu'il séjours détaché d'un terminal de contrôle en passant à nouveau par une fourche et en demandant au chef de session (le processus qui a appelé le terminal de contrôle) de se retirer. setsid ) sortir.

7voto

Paolo Tedesco Points 22442

Selon "Advanced Programming in the Unix Environment", de Stephens et Rago, la deuxième fourche est plutôt une recommandation, et elle est faite pour garantir que le démon n'acquiert pas un terminal de contrôle sur les systèmes basés sur le System V.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X