Ich portiere Windows-Anwendung auf Linux. Ich verwende CreateProcess
unter Windows, um untergeordnete Prozesse auszuführen und alle Standard-Streams umzuleiten (ein, aus, Fehler). Die Umleitung von Streams ist kritisch. Der Hauptprozess sendet Daten an untergeordnete Elemente und empfängt deren Ausgaben und Fehlermeldungen. Hauptprozess ist sehr groß mit viel Speicher und Threads, und untergeordnete Prozesse sind klein. Unter Linux sehe ich, dass fork
-Funktion ähnliche Funktionalität wie CreateProcess
unter Windows hat. Das Handbuch sagt jedoch, dass fork
"Elternprozesskopie" erstellt, einschließlich Code, Daten und Stapel. Bedeutet es, dass ich, wenn ich eine Kopie eines riesigen Prozesses anlege, der 1 GB Speicher verbraucht, nur um ein sehr einfaches Kommandozeilen-Tool auszuführen, das 1 MB Speicher selbst verwendet, muss ich zuerst 1 GB Speicher mit fork
duplizieren, und dann diese 1 GB durch 1 MB Prozess ersetzen? Also, wenn ich 100 Threads habe, wird es erforderlich sein, 100 GB Speicher zu haben, um 100 Prozesse auszuführen, die nur 100 MB Speicher benötigen, um zu laufen? Was ist mit anderen Threads im Parent-Prozess, die über fork
execution nicht wissen, was werden sie tun? Was fork
Funktion tut "unter der Haube" und ist es wirklich effektive Möglichkeit, eine Menge von kleinen Kind-Prozesse von riesigen Eltern zu erstellen?
Wenn Sie fork()
aufrufen, wird zunächst nur Ihre virtuelle Maschine kopiert, und alle Seiten werden als schreibgeschützt markiert. Ihr neuer untergeordneter Prozess verfügt über eine logische Kopie der VM Ihrer übergeordneten Prozesse, benötigt jedoch kein zusätzliches RAM, bis Sie tatsächlich mit dem Schreiben beginnen.
Wie bei Threads erstellt fork
nur einen neuen Thread im untergeordneten Prozess, der einer Kopie des aufrufenden Threads ähnelt.
Sobald Sie eine der exec
-Familien aufrufen (was ich annehmen möchte), wird Ihr gesamtes Prozessabbild durch ein neues ersetzt und nur Dateideskriptoren werden beibehalten.
Wenn Ihr Parent-Prozess viele offene Dateideskriptoren enthält, sollten Sie /proc/self/fd
durchgehen und alle Dateideskriptoren in dem Kind, das Sie nicht benötigen, schließen.
Die Kopien sind "copy-on-write". Wenn also Ihr untergeordneter Prozess die Daten nicht ändert, wird kein Speicher neben dem Vaterprozess verwendet. Nach einem fork()
erstellt der untergeordnete Prozess normalerweise exec()
, um das Programm dieses Prozesses durch einen anderen zu ersetzen, und dann wird der gesamte Speicher trotzdem gelöscht.
fork
teilt Ihren Prozess im Wesentlichen in zwei Teile auf, wobei sowohl der Eltern- als auch der Kindprozess nach dem Funktionsaufruf fork
an der Anweisung fortgesetzt werden. Der Rückgabewert im untergeordneten Prozess ist jedoch 0, während es im übergeordneten Prozess die Prozess-ID des untergeordneten Prozesses ist.
Die Erstellung des Child-Prozesses ist extrem schnell, da es die gleichen Seiten wie die Eltern verwendet. Die Seiten sind als Copy-on-Write (COW) markiert, so dass, wenn einer der Prozesse die Seite ändert, der andere nicht davon betroffen ist. Sobald der Kindprozess existiert, ruft er normalerweise eine der exec
-Funktionen auf, um sich durch ein Bild zu ersetzen. Windows hat keine Entsprechung zu fork
, stattdessen können Sie mit dem Aufruf CreateProcess
nur einen neuen Prozess starten.
Es gibt eine Alternative zu fork
namens klon , die Ihnen viel mehr Kontrolle darüber gibt, was passiert, wenn die neuer Prozess wird gestartet. Zum Beispiel können Sie eine Funktion angeben, um den neuen Prozess aufzurufen.
Ich habe CreateProcess
nicht verwendet, aber fork()
ist keine exakte Kopie des Prozesses. Es erstellt einen untergeordneten Prozess, aber das Kind beginnt seine Ausführung mit der Anweisung selbe , in der das übergeordnete Element fork
aufgerufen hat, und wird von dort fortgesetzt.
Ich empfehle, Kapitel 5 von Drei einfache Stücke OS-Buch. Dies könnte Ihnen den Einstieg erleichtern und Sie könnten den von Ihnen gesuchten Kind-Launch-Anruf finden.
Der gegabelte untergeordnete Prozess hat fast alle übergeordneten Funktionen kopiert: Speicher, Deskriptoren, Text usw. Die einzige Ausnahme sind die Threads der Eltern, sie werden nicht kopiert.