Werden beim Aufruf von fork Threads kopiert?

31

Wenn ich ein Programm mit Threads habe und fork()ein Unix-basiertes System aufrufe, werden die Threads kopiert? Ich weiß, dass der virtuelle Speicher für den aktuellen Prozess 1: 1 in den neu erzeugten Prozess kopiert wird. Ich weiß, dass Threads einen eigenen Stapel im virtuellen Speicher eines Prozesses haben. Daher sollte zumindest auch der Thread-Stapel kopiert werden. Ich weiß jedoch nicht, ob Threads mehr enthalten, die sich nicht im virtuellen Speicher befinden und daher NICHT kopiert werden. Wenn dies nicht der Fall ist, teilen sich die beiden Prozesse die Threads oder handelt es sich um unabhängige Kopien?

Jean-Baptiste Yunès
quelle

Antworten:

29

Nein.

Threads werden nicht kopiert fork(). In der POSIX-Spezifikation heißt es (Hervorheben ist meine):

Gabel - Erstellen Sie einen neuen Prozess

Ein Prozess soll mit einem einzigen Thread erstellt werden . Wenn ein Multithread-Prozess fork () aufruft, muss der neue Prozess eine Replik des aufrufenden Threads und seines gesamten Adressraums enthalten, möglicherweise einschließlich der Zustände von Mutexen und anderen Ressourcen. Um Fehler zu vermeiden, kann der untergeordnete Prozess daher nur asynchronsignalsichere Operationen ausführen, bis eine der Ausführungsfunktionen aufgerufen wird.

Um dieses Problem zu umgehen, gibt es eine pthread_atfork()Hilfe.

Jean-Baptiste Yunès
quelle
7

Mann Gabel :

Der untergeordnete Prozess wird mit einem einzelnen Thread erstellt, der fork () aufgerufen hat. Der gesamte virtuelle Adressraum des übergeordneten Elements wird im untergeordneten Element repliziert, einschließlich der Status von Mutexen, Bedingungsvariablen und anderen pthreads-Objekten. Die Verwendung von pthread_atfork (3) kann hilfreich sein, um Probleme zu lösen, die dies verursachen kann.

Kaylum
quelle
Aber das scheint seltsam: Warum sollte der Stapel für die Threads im Prozess, der Fork aufruft, kopiert werden, wenn die tatsächlichen Threads (von denen ich nicht weiß, dass sie Speicherplatz an einem anderen Ort als dem virtuellen Speicher enthalten) nicht vorhanden sind?
Nun, das Warum ist eine ganz andere Frage. Ich kenne die ursprünglichen Entwurfsentscheidungen nicht, die zu dieser Implementierung geführt haben. Wenn Sie interessiert sind, sollten Sie dies als separate Frage stellen.
Kaylum
@dip aber Stapel anderer Threads werden nicht kopiert, wer hat das gesagt?
Jean-Baptiste Yunès
1
@ Jean-BaptisteYunès In Unix-Systemen gibt es eine Struktur, die den virtuellen Speicher für einen Prozess darstellt. Das ist derjenige, der kopiert wurde. Nicht nur der Haufen und bss
6
Sie erhalten den gesamten Speicherplatz - und damit die Stapel aller Threads. Sie benötigen dies, da es keine Einschränkung gibt, wohin die Zeiger im Stapel (oder im statischen Speicher), auf die der verbleibende Thread
zugreifen kann,
4

Von The Open Group Basisspezifikationen Ausgabe 7, 2018 Ausgabe der Gabel :

Ein Prozess soll mit einem einzigen Thread erstellt werden. Wenn ein Multithread-Prozess fork () aufruft , muss der neue Prozess eine Replik des aufrufenden Threads und seines gesamten Adressraums enthalten, möglicherweise einschließlich der Zustände von Mutexen und anderen Ressourcen. Folglich Um Fehler zu vermeiden, kann das Kind Prozess nur Asynchron-Signal-sicheren Betrieb bis zu dem Zeitpunkt auszuführen , wie eine der exec - Funktionen aufgerufen wird.

Wenn die Anwendung fork () von einem Signalhandler aufruft und einer der von pthread_atfork () registrierten Fork-Handler eine Funktion aufruft, die nicht async-signal-sicher ist, ist das Verhalten undefiniert.

Ian Abbott
quelle
-2

Ursprünglich wurde "Fork" erreicht, indem die Aufgabe auf die Festplatte geschrieben und dann, anstatt in einem anderen Thread zu lesen (was geschehen würde, wenn die Aufgabe durch einen anderen ersetzt würde), die Aufgaben-ID des noch im Speicher befindlichen Bildes geändert und fortgefahren würde mit seiner Ausführung (als neue Aufgabe). Dies war eine sehr einfache Modifikation des grundlegenden Mechanismus zum Umschalten von Aufgaben, bei dem jeweils nur eine Aufgabe RAM-Speicher belegen würde.

Mit zunehmender Ausarbeitung der Speicherverwaltung wurde dieses Schema natürlich an die neue Umgebung angepasst.

Hot Licks
quelle
Neugierig, warum dies abgelehnt wurde. So hat es Unix gemacht.
Hot Licks
Dies ist eine interessante Erkenntnis, aber wo werden Threads erwähnt? Sieht für mich nicht nach einer Antwort aus.
Wastl