fork()war der ursprüngliche UNIX-Systemaufruf. Es können nur neue Prozesse erstellt werden, keine Threads. Auch ist es tragbar.
Unter Linux gibt clone()es einen neuen, vielseitigen Systemaufruf, mit dem ein neuer Ausführungsthread erstellt werden kann. Abhängig von den übergebenen Optionen kann sich der neue Ausführungsthread an die Semantik eines UNIX-Prozesses, eines POSIX-Threads, an etwas dazwischen oder an etwas völlig anderes (wie einen anderen Container) halten. Sie können alle Arten von Optionen angeben, die festlegen, ob Speicher, Dateideskriptoren, verschiedene Namespaces, Signalhandler usw. gemeinsam genutzt oder kopiert werden.
Da clone()es sich um den Superset-Systemaufruf handelt, ruft die Implementierung des fork()Systemaufruf-Wrappers in glibc tatsächlich auf clone(), dies ist jedoch ein Implementierungsdetail, das Programmierer nicht kennen müssen. Der eigentliche fork()Systemaufruf ist aus Gründen der Abwärtskompatibilität im Linux-Kernel noch vorhanden, obwohl er überflüssig geworden ist, da Programme, die sehr alte Versionen von libc oder eine andere libc als glibc verwenden, ihn möglicherweise verwenden.
clone()wird auch verwendet, um die pthread_create()POSIX-Funktion zum Erstellen von Threads zu implementieren .
Dies ist der "clone ()", der durch "doing" beschrieben wird man 2 clone.
Wenn Sie diese Manpage nah genug gelesen haben, sehen Sie Folgendes:
It is actually a library function layered on top of the
underlying clone() system call.
Anscheinend soll das Threading mithilfe der "Bibliotheksfunktion" implementiert werden, die auf dem verwirrend identisch benannten Systemaufruf liegt.
Ich habe ein kurzes Programm geschrieben:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int
main(int ac, char **av)
{
pid_t cpid;
switch (cpid = fork()) {
case 0: // Child process
break;
case -1: // Error
break;
default: // parent process
break;
}
return 0;
}
Kompilierte es mit: c99 -Wall -Wextraund ließ es unter strace -flaufen, um zu sehen, was Systemaufrufe tatsächlich tun. Ich habe dies straceauf einem Linux 2.6.18-Rechner (x86_64-CPU) herausgefunden:
In der straceAusgabe erscheint kein "Fork" -Aufruf. Der clone()in der straceAusgabe angezeigte Aufruf hat ganz andere Argumente als der Manpage-Klon. child_stack=0als erstes argument ist anders als int (*fn)(void *).
Es scheint, dass der fork(2)Systemaufruf in Bezug auf den Real implementiert ist clone(), genau wie die "Bibliotheksfunktion" clone()implementiert ist. Der Realclone() hat andere Argumente als der Manpage-Klon.
Vereinfacht gesagt, sind beide Ihrer scheinbar widersprüchlichen Aussagen zu fork()und clone()richtig. Der "Klon" ist jedoch anders.
"Es ist eigentlich eine Bibliotheksfunktion, die über dem zugrunde liegenden clone () - Systemaufruf liegt." - Dies gilt im Allgemeinen für jeden Systemaufruf. Programmierer rufen in libc praktisch immer Funktionen auf, die nach dem Systemaufruf benannt sind. Dies liegt daran, dass ein tatsächlicher realer Systemaufruf direkt von C aus plattformspezifische Magie erfordert (in der Regel durch Erzwingen einer CPU-Falle, abhängig von der ABI-Architektur) und Computercode, die am besten an libc delegiert wird.
Celada
1
@ Celada - ja, einverstanden. Es ist nur so, dass man 2 clonees genau so ausdrückt, was meiner Meinung nach das Problem verwirrt und den Fragesteller daran hindert, eine gute Antwort zu erhalten.
Bruce Ediger
2
Ich glaube, die Manpage zeigt an, dass sich die Argumentliste der cloneBibliotheksfunktion wesentlich von der vom zugrunde liegenden Systemaufruf akzeptierten Argumentliste unterscheidet. Insbesondere gibt der Systemaufruf immer zweimal auf demselben Stapel zurück, wie dies bei herkömmlichen Methoden der Fall forkist. Alle Argumente, die sich auf den untergeordneten Stapel beziehen, werden streng im Benutzerbereich behandelt. Siehe zum Beispiel sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/…
zwol 30.04.15
1
Ich wollte deine Antwort am besten beantworten, weil es rockt, aber ich wurde von der Herde beeinflusst und ging mit der ersten Antwort. Sie bekommt Punkte für die Reaktionszeit. Danke für Ihre Erklärung.
Gregg Leventhal
6
fork()ist nur ein bestimmter Satz von Flags für den Systemaufruf clone(). clone()ist allgemein genug, um entweder einen "Prozess" oder einen "Thread" oder sogar seltsame Dinge zu erstellen, die irgendwo zwischen Prozessen und Threads liegen (z. B. verschiedene "Prozesse", die dieselbe Dateideskriptortabelle verwenden).
Im Wesentlichen können Sie für jeden "Informationstyp", der einem Ausführungskontext im Kernel zugeordnet ist, clone()auswählen, ob diese Informationen als Alias verwendet oder kopiert werden sollen. Themen entsprechen Aliasing, Prozesse dem Kopieren. Durch die Angabe von Zwischenkombinationen von Flags für clone()können Sie seltsame Dinge erstellen, die keine Threads oder Prozesse sind. Normalerweise sollte man das nicht tun, und ich stelle mir vor, dass während der Entwicklung des Linux-Kernels eine Debatte darüber stattgefunden hat, ob ein so allgemeiner Mechanismus wie dieser möglich sein sollte clone().
Es scheint, dass
clone()
in Linux 2.6 zwei Dinge im Umlauf sindEs gibt einen Systemaufruf:
Dies ist der "clone ()", der durch "doing" beschrieben wird
man 2 clone
.Wenn Sie diese Manpage nah genug gelesen haben, sehen Sie Folgendes:
Anscheinend soll das Threading mithilfe der "Bibliotheksfunktion" implementiert werden, die auf dem verwirrend identisch benannten Systemaufruf liegt.
Ich habe ein kurzes Programm geschrieben:
Kompilierte es mit:
c99 -Wall -Wextra
und ließ es unterstrace -f
laufen, um zu sehen, was Systemaufrufe tatsächlich tun. Ich habe diesstrace
auf einem Linux 2.6.18-Rechner (x86_64-CPU) herausgefunden:In der
strace
Ausgabe erscheint kein "Fork" -Aufruf. Derclone()
in derstrace
Ausgabe angezeigte Aufruf hat ganz andere Argumente als der Manpage-Klon.child_stack=0
als erstes argument ist anders alsint (*fn)(void *)
.Es scheint, dass der
fork(2)
Systemaufruf in Bezug auf den Real implementiert istclone()
, genau wie die "Bibliotheksfunktion"clone()
implementiert ist. Der Realclone()
hat andere Argumente als der Manpage-Klon.Vereinfacht gesagt, sind beide Ihrer scheinbar widersprüchlichen Aussagen zu
fork()
undclone()
richtig. Der "Klon" ist jedoch anders.quelle
man 2 clone
es genau so ausdrückt, was meiner Meinung nach das Problem verwirrt und den Fragesteller daran hindert, eine gute Antwort zu erhalten.clone
Bibliotheksfunktion wesentlich von der vom zugrunde liegenden Systemaufruf akzeptierten Argumentliste unterscheidet. Insbesondere gibt der Systemaufruf immer zweimal auf demselben Stapel zurück, wie dies bei herkömmlichen Methoden der Fallfork
ist. Alle Argumente, die sich auf den untergeordneten Stapel beziehen, werden streng im Benutzerbereich behandelt. Siehe zum Beispiel sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/…fork()
ist nur ein bestimmter Satz von Flags für den Systemaufrufclone()
.clone()
ist allgemein genug, um entweder einen "Prozess" oder einen "Thread" oder sogar seltsame Dinge zu erstellen, die irgendwo zwischen Prozessen und Threads liegen (z. B. verschiedene "Prozesse", die dieselbe Dateideskriptortabelle verwenden).Im Wesentlichen können Sie für jeden "Informationstyp", der einem Ausführungskontext im Kernel zugeordnet ist,
clone()
auswählen, ob diese Informationen als Alias verwendet oder kopiert werden sollen. Themen entsprechen Aliasing, Prozesse dem Kopieren. Durch die Angabe von Zwischenkombinationen von Flags fürclone()
können Sie seltsame Dinge erstellen, die keine Threads oder Prozesse sind. Normalerweise sollte man das nicht tun, und ich stelle mir vor, dass während der Entwicklung des Linux-Kernels eine Debatte darüber stattgefunden hat, ob ein so allgemeiner Mechanismus wie dieser möglich sein sollteclone()
.quelle