GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Fork vs. Clone auf 2.6 Kernel Linux

fork() war der ursprüngliche UNIX-Systemaufruf. Es kann nur verwendet werden, um neue Prozesse zu erstellen, keine Threads. Außerdem ist es tragbar.

Unter Linux clone() ist ein neuer, vielseitiger Systemaufruf, der verwendet werden kann, um einen neuen Ausführungs-Thread zu erstellen. Abhängig von den übergebenen Optionen kann der neue Ausführungsthread der Semantik eines UNIX-Prozesses, eines POSIX-Threads, etwas dazwischen oder etwas völlig anderem (wie einem anderen Container) entsprechen. Sie können alle möglichen Optionen angeben, die bestimmen, ob Speicher, Dateideskriptoren, verschiedene Namespaces, Signalhandler usw. gemeinsam genutzt oder kopiert werden.

Seit clone() ist der übergeordnete Systemaufruf, die Implementierung von fork() Systemaufruf-Wrapper in glibc ruft tatsächlich clone() auf , aber dies ist ein Implementierungsdetail, über das Programmierer nichts wissen müssen. Die eigentliche echte fork() Der Systemaufruf existiert aus Gründen der Abwärtskompatibilität immer noch im Linux-Kernel, obwohl er überflüssig geworden ist, da Programme, die sehr alte Versionen von libc oder einer anderen libc außer glibc verwenden, ihn möglicherweise verwenden.

clone() wird auch verwendet, um den pthread_create() zu implementieren POSIX-Funktion zum Erstellen von Threads.

Portable Programme sollten fork() aufrufen und pthread_create() , nicht clone() .


Es scheint, dass es zwei clone() gibt Dinge, die in Linux 2.6 herumschwirren

Es gibt einen Systemaufruf:

int clone(int (*fn)(void *), void *child_stack,
          int flags, void *arg, ...
          /* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ );

Dies ist der "clone()", der durch Ausführen von man 2 clone beschrieben wird .

Wenn Sie diese Manpage genau genug lesen, werden Sie Folgendes sehen:

It is actually a library function layered on top of the
underlying clone() system call.

Anscheinend sollen Sie Threading implementieren, indem Sie die "Bibliotheksfunktion" verwenden, die auf dem verwirrend identisch benannten Systemaufruf geschichtet ist.

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;
}

Kompiliert mit:c99 -Wall -Wextra , und führte es unter strace -f aus um zu sehen, was das Forking von Systemaufrufen tatsächlich bewirkt. Ich habe das aus strace herausgeholt auf einem Linux 2.6.18-Rechner (x86_64-CPU):

20097 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x2b4ee9213770) = 20098
20097 exit_group(0)                     = ?
20098 exit_group(0)

Im strace erscheint kein "fork"-Aufruf Ausgang. Die clone() Anruf, der in strace angezeigt wird output hat ganz andere Argumente als der man-page-clone. child_stack=0 da das erste Argument anders ist als int (*fn)(void *) .

Es scheint, dass der fork(2) Systemaufruf ist in Form von real implementiert clone() , genau wie die "Bibliotheksfunktion" clone() ist implementiert. Das Echte clone() hat einen anderen Satz von Argumenten als der man-page-clone.

Vereinfacht gesagt, Ihre beiden scheinbar widersprüchlichen Aussagen zu fork() und clone() sind richtig. Der betroffene "Klon" ist jedoch anders.


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 sich irgendwo zwischen Prozessen und Threads befinden (zum Beispiel verschiedene "Prozesse", die dieselbe Dateideskriptortabelle verwenden).

Im Wesentlichen gilt für jeden "Typ" von Informationen, die einem Ausführungskontext im Kernel zugeordnet sind, clone() gibt Ihnen die Wahl, diese Informationen zu aliasen oder zu kopieren. Threads entsprechen Aliasing, Prozesse entsprechen dem Kopieren. Durch Angabe von Zwischenkombinationen von Flags bis clone() , können Sie seltsame Dinge erstellen, die keine Threads oder Prozesse sind. Normalerweise sollten Sie das nicht tun, und ich kann mir vorstellen, dass es während der Entwicklung des Linux-Kernels einige Diskussionen darüber gab, ob er einen so allgemeinen Mechanismus wie clone() zulassen sollte .


Linux
  1. Der Lebenszyklus des Linux-Kernel-Testens

  2. So aktualisieren Sie den Kernel auf dem Linux-Desktop

  3. Linux – Kernel:Namespaces-Unterstützung?

  4. Schnellster Linux-Systemaufruf

  5. Welche Datei im Kernel gibt fork(), vfork()... an, um den Systemaufruf sys_clone() zu verwenden

Ist Linux ein Betriebssystem oder ein Kernel?

Linux-Kernel vs. Mac-Kernel

Linux-Kernel und seine Funktionen

Was tun bei einer Linux-Kernel-Panik?

Vollständiges Handbuch zur Linux-Protokollierung

Linux – Diagramm des Linux-Kernels vs. Performance-Tools?