Ich versuche einen Daemon in Python zu erstellen. Ich habe die folgende Frage gefunden , die einige gute Ressourcen enthält, denen ich derzeit folge, aber ich bin gespannt, warum eine Doppelgabel notwendig ist. Ich habe mich bei Google umgesehen und viele Ressourcen gefunden, die erklären, dass eine notwendig ist, aber nicht warum.
Einige erwähnen, dass dies verhindern soll, dass der Dämon ein steuerndes Terminal erhält. Wie würde es das ohne die zweite Gabel machen? Was sind die Auswirkungen?
fork()
abrufen kann (der Aufruf gibt die PID des Kindes an den Elternteil zurück, sodass es einfach ist, die PID des untergeordneten Prozesses abzurufen, dies jedoch nicht so einfach ist Holen Sie sich die PID des Enkelprozesses ).Antworten:
Mit Blick auf den Code, auf den in der Frage verwiesen wird, lautet die Begründung:
Es muss also sichergestellt werden, dass der Dämon erneut auf init übergeordnet wird (nur für den Fall, dass der Prozess, der den Dämon startet, langlebig ist), und es wird jede Chance ausgeschlossen, dass der Dämon wieder eine steuernde Tty erhält. Wenn also keiner dieser Fälle zutrifft, sollte eine Gabel ausreichen. " Unix Network Programming - Stevens " hat einen guten Abschnitt dazu.
quelle
p=fork(); if(p) exit(); setsid()
. In diesem Fall wird auch der Elternteil beendet und der erste untergeordnete Prozess wird repariert. Die Doppelgabel-Magie ist nur erforderlich, um zu verhindern, dass der Dämon einen tty erhält.forks
einchild
Prozess, dieser allererste untergeordnete Prozesssession leader
ein TTY-Terminal sein und in der Lage sein, ihn zu öffnen. Aber wenn ich mich wieder von diesem Kind abkehre und dieses erste Kind beende, ist das zweite gegabelte Kind keinsession leader
und kann kein TTY-Terminal öffnen. Ist diese Aussage richtig?setsid()
. Der erste gegabelte Prozess wird also nach dem Aufruf zum Sitzungsleiter,setsid()
und dann werden wir erneut gegabelt, sodass der letzte, doppelt gegabelte Prozess kein Sitzungsleiter mehr ist. Abgesehen von der Anforderungsetsid()
, ein Sitzungsleiter zu sein, sind Sie genau richtig.Ich habe versucht, die Doppelgabel zu verstehen und bin hier auf diese Frage gestoßen. Nach vielen Recherchen habe ich das herausgefunden. Hoffentlich hilft es, die Dinge für jeden, der die gleiche Frage hat, besser zu klären.
Unter Unix gehört jeder Prozess zu einer Gruppe, die wiederum zu einer Sitzung gehört. Hier ist die Hierarchie ...
Sitzung (SID) → Prozessgruppe (PGID) → Prozess (PID)
Der erste Prozess in der Prozessgruppe wird zum Prozessgruppenleiter und der erste Prozess in der Sitzung zum Sitzungsleiter. Jeder Sitzung kann ein TTY zugeordnet sein. Nur ein Sitzungsleiter kann die Kontrolle über ein TTY übernehmen. Damit ein Prozess wirklich dämonisiert wird (im Hintergrund ausgeführt wird), sollten wir sicherstellen, dass der Sitzungsleiter getötet wird, damit die Sitzung niemals die Kontrolle über das TTY übernehmen kann.
Ich habe Sander Marechals Python-Beispiel-Daemon-Programm von dieser Site auf meinem Ubuntu ausgeführt. Hier sind die Ergebnisse mit meinen Kommentaren.
Beachten Sie, dass der Prozess nachher der Sitzungsleiter ist
Decouple#1
, da dies der Fall istPID = SID
. Es könnte immer noch die Kontrolle über ein TTY übernehmen.Beachten Sie, dass dies
Fork#2
nicht mehr der Sitzungsleiter istPID != SID
. Dieser Prozess kann niemals die Kontrolle über ein TTY übernehmen. Wirklich dämonisiert.Ich persönlich finde die Terminologie zweimal verwirrend. Eine bessere Redewendung könnte Gabel-Entkopplungs-Gabel sein.
Zusätzliche interessante Links:
quelle
fork()
verhindert bereits das Erstellen von Zombies, vorausgesetzt, Sie schließen das übergeordnete Element.setsid()
vor einer Single anzurufenfork()
? Eigentlich denke ich, dass die Antworten auf diese Frage das beantworten.Genau genommen hat die Doppelgabel nichts damit zu tun, den Dämon als Kind von neu zu erziehen
init
. Alles, was notwendig ist, um das Kind wieder zu erziehen, ist, dass das Elternteil beendet werden muss. Dies kann mit nur einer Gabel erfolgen. Wenn Sie einen Double-Fork alleine ausführen, wird der Daemon-Prozess nicht erneut übergeordnetinit
. Das übergeordnete Element des Dämons muss beendet werden . Mit anderen Worten, das übergeordnete Element wird immer beendet, wenn ein geeigneter Dämon gegabelt wird, sodass der Dämonprozess erneut übergeordnet wirdinit
.Warum also die Doppelgabel? POSIX.1-2008 Abschnitt 11.1.3, " Das steuernde Terminal ", enthält die Antwort (Hervorhebung hinzugefügt):
Dies sagt uns, dass, wenn ein Daemon-Prozess so etwas tut ...
... dann wird der Daemon - Prozess könnte erwerben
/dev/console
als Steueranschluss, je nachdem , ob der Daemon - Prozess ist ein Session - Leiter, und in Abhängigkeit von der Systemimplementierung. Das Programm kann garantieren, dass der obige Aufruf kein steuerndes Terminal erhält, wenn das Programm zuerst sicherstellt, dass es kein Sitzungsleiter ist.Normalerweise wird beim Starten eines Dämons
setsid
(vom untergeordneten Prozess nach dem Aufruffork
) aufgerufen , um den Dämon von seinem steuernden Terminal zu trennen. Aufrufensetsid
bedeutet jedoch auch, dass der aufrufende Prozess der Sitzungsleiter der neuen Sitzung ist, wodurch die Möglichkeit offen bleibt, dass der Dämon ein steuerndes Terminal erneut abrufen kann. Die Double-Fork-Technik stellt sicher, dass der Daemon-Prozess nicht der Sitzungsleiter ist, wodurch garantiert wird, dass ein Aufruf vonopen
, wie im obigen Beispiel, nicht dazu führt, dass der Daemon-Prozess ein steuerndes Terminal erneut erhält.Die Doppelgabeltechnik ist etwas paranoid. Dies ist möglicherweise nicht erforderlich, wenn Sie wissen, dass der Dämon niemals eine Endgerätedatei öffnet. Auf einigen Systemen ist dies möglicherweise auch dann nicht erforderlich, wenn der Dämon eine Endgerätedatei öffnet, da dieses Verhalten durch die Implementierung definiert ist. Eine nicht implementierungsdefinierte Sache ist jedoch, dass nur ein Sitzungsleiter das steuernde Terminal zuweisen kann. Wenn ein Prozess kein Sitzungsleiter ist, kann er kein steuerndes Terminal zuweisen. Wenn Sie also paranoid sein möchten und sicher sein möchten, dass der Daemon-Prozess unabhängig von implementierungsdefinierten Besonderheiten nicht versehentlich ein steuerndes Terminal erwerben kann, ist die Double-Fork-Technik unerlässlich.
quelle
LogFile=/dev/console
. Programme haben nicht immer die Kontrolle über die Kompilierungszeit, welche Dateien sie öffnen könnten;)Entnommen aus Bad CTK :
"Bei einigen Unix-Versionen müssen Sie beim Start eine Doppelgabelung ausführen, um in den Dämonmodus zu wechseln. Dies liegt daran, dass sich die Einzelgabelung nicht garantiert vom steuernden Terminal löst."
quelle
setsid
nach einer anfänglichen Abzweigung aufruft . Anschließend wird sichergestellt, dass es von einem steuernden Terminal getrennt bleibt, indem es erneut gegabelt wird und der Sitzungsleiter (der aufgerufene Prozesssetsid
) beendet wird.fork
dass es sich vom steuernden Terminal löst. Dassetsid
macht es. Abersetsid
wird scheitern , wenn es aus einem Prozessgruppenleiter genannt wird. Daherfork
muss zuvor eine Initiale erstellt werden,setsid
um sicherzustellen, dasssetsid
sie von einem Prozess aufgerufen wird, der kein Prozessgruppenleiter ist. Der zweitefork
stellt sicher, dass der letzte Prozess (derjenige, der der Dämon sein wird) kein Sitzungsleiter ist. Nur Sitzungsleiter können ein steuerndes Terminal erwerben, sodass diese zweite Abzweigung garantiert, dass der Dämon nicht versehentlich ein steuerndes Terminal wiedererlangt. Dies gilt für jedes POSIX-Betriebssystem.Laut "Advanced Programming in the Unix Environment" von Stephens und Rago ist die zweite Verzweigung eher eine Empfehlung und soll sicherstellen, dass der Dämon auf System V-basierten Systemen kein steuerndes Terminal erhält.
quelle
Ein Grund dafür ist, dass der übergeordnete Prozess sofort auf das untergeordnete Element warten und es dann vergessen kann. Wenn dann das Enkelkind stirbt, ist sein Elternteil init und es wird darauf warten () - und es aus dem Zombie-Zustand entfernen.
Das Ergebnis ist, dass der übergeordnete Prozess die gegabelten untergeordneten Prozesse nicht kennen muss und es auch möglich ist, lang laufende Prozesse aus Bibliotheken usw. zu verzweigen.
quelle
Der Aufruf von daemon () hat den übergeordneten Aufruf _exit (), wenn er erfolgreich ist. Die ursprüngliche Motivation könnte darin bestanden haben, den Eltern zu erlauben, zusätzliche Arbeit zu leisten, während das Kind dämonisiert.
Es kann auch auf einer falschen Annahme beruhen, dass dies notwendig ist, um sicherzustellen, dass der Dämon keinen übergeordneten Prozess hat und auf init repariert wird - dies geschieht jedoch trotzdem, sobald der übergeordnete Prozess im Fall einer einzelnen Gabelung stirbt.
Ich nehme an, am Ende läuft alles nur auf Tradition hinaus - eine einzige Gabel reicht aus, solange der Elternteil ohnehin in kurzer Zeit stirbt.
quelle
Eine anständige Diskussion darüber scheint unter http://www.developerweb.net/forum/showthread.php?t=3025 zu sein
Zitiert mlampkin von dort:
quelle
Auf diese Weise ist es möglicherweise einfacher zu verstehen:
quelle