Unterschiede zwischen Fork und Exec

Lesezeit: 10 Minuten

Benutzeravatar von Sashi
Saschi

Was sind die Unterschiede zw fork und exec?

  • Eine gute, detaillierte Zusammenfassung von Fork-, Exec- und anderen Prozesssteuerungsfunktionen finden Sie unter yolinux.com/TUTORIALS/ForkExecProcesses.html

    – Jonathan Finland

    31. Oktober 2009 um 4:38 Uhr

  • @Justin, weil wir SO werden wollen das Anlaufstelle für Programmierfragen.

    – paxdiablo

    27. Januar 2010 um 21:35 Uhr

  • Also fork ist im Grunde Klonen :O

    – Sebastian Hojas

    24. Oktober 2014 um 13:39 Uhr


  • Auch diese Anleitung ist sehr hilfreich! devconnected.com/understanding-processes-on-linux

    – Viktor

    5. Januar 2021 um 19:41 Uhr

Benutzeravatar von paxdiablo
paxdiablo

Die Verwendung von fork und exec veranschaulicht den Geist von UNIX, indem es eine sehr einfache Möglichkeit bietet, neue Prozesse zu starten.

Das fork Aufruf erstellt im Grunde ein Duplikat des aktuellen Prozesses, identisch in fast jeder Weg. Nicht alles wird kopiert (z. B. Ressourcenbeschränkungen in einigen Implementierungen), aber die Idee ist, eine möglichst genaue Kopie zu erstellen.

Der neue Prozess (Kind) erhält eine andere Prozess-ID (PID) und hat die PID des alten Prozesses (Eltern) als Eltern-PID (PPID). Da die beiden Prozesse jetzt genau denselben Code ausführen, können sie anhand des Rückgabecodes erkennen, welcher welcher ist fork – Das Kind erhält 0, der Elternteil erhält die PID des Kindes. Dies alles natürlich unter der Voraussetzung fork Aufruf funktioniert – wenn nicht, wird kein Kind erstellt und der Elternteil erhält einen Fehlercode.

Das exec call ist eine Möglichkeit, den gesamten aktuellen Prozess im Grunde durch ein neues Programm zu ersetzen. Es lädt das Programm in den aktuellen Prozessraum und führt es vom Einstiegspunkt aus aus.

So, fork und exec werden häufig nacheinander verwendet, um ein neues Programm als untergeordnetes Element eines aktuellen Prozesses auszuführen. Shells tun dies normalerweise immer dann, wenn Sie versuchen, ein Programm wie auszuführen find – die Schale gabelt sich, dann lädt das Kind die find Programm in den Speicher, Einrichten aller Befehlszeilenargumente, Standard-I/O und so weiter.

Aber sie müssen nicht zusammen verwendet werden. Es ist vollkommen akzeptabel für ein Programm fork selbst ohne execWenn beispielsweise das Programm sowohl übergeordneten als auch untergeordneten Code enthält (Sie müssen vorsichtig sein, was Sie tun, jede Implementierung kann Einschränkungen haben). Dies wurde ziemlich häufig (und wird immer noch) für Daemons verwendet, die einfach auf einem TCP-Port lauschen und fork eine Kopie von sich selbst, um eine bestimmte Anfrage zu bearbeiten, während der Elternteil wieder zuhört.

Ebenso müssen Programme, die wissen, dass sie fertig sind und nur ein anderes Programm ausführen möchten, dies nicht tun fork, exec und dann wait für das Kind. Sie können das Kind einfach direkt in ihren Prozessraum laden.

Einige UNIX-Implementierungen haben eine optimierte fork die verwendet, was sie Copy-on-Write nennen. Dies ist ein Trick, um das Kopieren des Prozessraums zu verzögern fork bis das Programm versucht, etwas in diesem Bereich zu ändern. Dies ist nur für die Programme nützlich, die es verwenden fork und nicht exec dass sie nicht einen ganzen Prozessraum kopieren müssen.

Wenn die exec ist nachfolgend genannt fork (und das passiert meistens), was einen Schreibvorgang in den Prozessbereich verursacht und dann für den untergeordneten Prozess kopiert wird.

Beachten Sie, dass es eine ganze Familie von gibt exec Anrufe (execl, execle, execve usw.) aber exec im Kontext bedeutet hier jeder von ihnen.

Das folgende Diagramm veranschaulicht den typischen fork/exec Betrieb, wo die bash Shell wird verwendet, um ein Verzeichnis mit der ls Befehl:

+--------+
| pid=7  |
| ppid=4 |
| bash   |
+--------+
    |
    | calls fork
    V
+--------+             +--------+
| pid=7  |    forks    | pid=22 |
| ppid=4 | ----------> | ppid=7 |
| bash   |             | bash   |
+--------+             +--------+
    |                      |
    | waits for pid 22     | calls exec to run ls
    |                      V
    |                  +--------+
    |                  | pid=22 |
    |                  | ppid=7 |
    |                  | ls     |
    V                  +--------+
+--------+                 |
| pid=7  |                 | exits
| ppid=4 | <---------------+
| bash   |
+--------+
    |
    | continues
    V

Benutzeravatar von Doug T
Doug T.

fork() teilt den aktuellen Prozess in zwei Prozesse auf. Oder mit anderen Worten, Ihr nettes, lineares, einfach zu denkendes Programm wird plötzlich zu zwei separaten Programmen, die ein Stück Code ausführen:

 int pid = fork();

 if (pid == 0)
 {
     printf("I'm the child");
 }
 else
 {
     printf("I'm the parent, my child is %i", pid);
     // here we can kill the child, but that's not very parently of us
 }

Das kann dich umhauen. Jetzt haben Sie einen Codeabschnitt mit ziemlich identischem Status, der von zwei Prozessen ausgeführt wird. Der untergeordnete Prozess erbt den gesamten Code und Speicher des Prozesses, der ihn gerade erstellt hat, einschließlich des Beginns von wo fork() Anruf einfach abgebrochen. Der einzige Unterschied ist die fork() Rückgabecode, um Ihnen mitzuteilen, ob Sie der Elternteil oder das Kind sind. Wenn Sie der Elternteil sind, ist der Rückgabewert die ID des Kindes.

exec ist ein bisschen leichter zu verstehen, sagen Sie einfach exec um einen Prozess mit der ausführbaren Zieldatei auszuführen, und Sie haben nicht zwei Prozesse, die denselben Code ausführen oder denselben Zustand erben. Wie @Steve Hawkins sagt, exec kann nach dir verwendet werden forkum im aktuellen Prozess die ausführbare Zieldatei auszuführen.

  • es gibt auch die Bedingung wann pid < 0 und die fork() Anruf scheiterte

    – Jonathan Finland

    31. Oktober 2009 um 4:37 Uhr

  • Das haut mich überhaupt nicht um 🙂 Ein Stück Code, das von zwei Prozessen ausgeführt wird, passiert jedes Mal, wenn eine gemeinsam genutzte Bibliothek oder DLL verwendet wird.

    – paxdiablo

    31. Oktober 2009 um 5:01 Uhr

Benutzeravatar von Michael Burr
Michael Burr

Ich denke, einige Konzepte aus „Fortgeschrittene Unix-Programmierung“ von Marc Rochkind waren hilfreich, um die verschiedenen Rollen von zu verstehen fork()/exec()besonders für jemanden, der an Windows gewöhnt ist CreateProcess() Modell:

EIN Programm ist eine Sammlung von Anweisungen und Daten, die in einer regulären Datei auf der Festplatte gespeichert werden. (ab 1.1.2 Programme, Prozesse und Threads)

.

Um ein Programm auszuführen, wird der Kernel zunächst aufgefordert, ein neues zu erstellen Prozess, das ist eine Umgebung, in der ein Programm ausgeführt wird. (auch ab 1.1.2 Programme, Prozesse und Threads)

.

Es ist unmöglich, die Systemaufrufe exec oder fork zu verstehen, ohne den Unterschied zwischen einem Prozess und einem Programm vollständig zu verstehen. Wenn diese Bedingungen neu für Sie sind, können Sie zurückgehen und Abschnitt 1.1.2 lesen. Wenn Sie jetzt fortfahren möchten, fassen wir die Unterscheidung in einem Satz zusammen: Ein Prozess ist eine Ausführungsumgebung, die aus Anweisungen, Benutzerdaten und Systemdatensegmenten sowie vielen anderen Ressourcen besteht, die zur Laufzeit erfasst werden , während ein Programm eine Datei ist, die Anweisungen und Daten enthält, die verwendet werden, um die Anweisungs- und Benutzerdatensegmente eines Prozesses zu initialisieren. (vom 5.3 exec Systemaufrufe)

Sobald Sie den Unterschied zwischen einem Programm und einem Prozess verstanden haben, wird das Verhalten von fork() und exec() Funktion lässt sich wie folgt zusammenfassen:

  • fork() erstellt ein Duplikat des aktuellen Prozesses
  • exec() ersetzt das Programm im aktuellen Prozess durch ein anderes Programm

(Dies ist im Wesentlichen eine vereinfachte “für Dummies” -Version von Paxdiablos viel detaillierterer Antwort.)

Benutzeravatar von Sandesh Kobal
Sandesh Kobal

Fork erstellt eine Kopie eines aufrufenden Prozesses. folgt im Allgemeinen der Struktur
Geben Sie hier die Bildbeschreibung ein

int cpid = fork( );

if (cpid = = 0) 
{

  //child code

  exit(0);

}

//parent code

wait(cpid);

// end

(Für den untergeordneten Prozess ist text(code),data,stack dasselbe wie der aufrufende Prozess) Der untergeordnete Prozess führt den Code im if-Block aus.

EXEC ersetzt den aktuellen Prozess durch den Code, die Daten und den Stack des neuen Prozesses. folgt im Allgemeinen der Struktur
Geben Sie hier die Bildbeschreibung ein

int cpid = fork( );

if (cpid = = 0) 
{   
  //child code

  exec(foo);

  exit(0);    
}

//parent code

wait(cpid);

// end

(Nachdem der Aufruf von exec löscht der Unix-Kernel den Text, die Daten und den Stapel des untergeordneten Prozesses und füllt ihn mit foo-prozessbezogenem Text/Daten) Daher hat der untergeordnete Prozess einen anderen Code (der Code von foo {nicht derselbe wie der übergeordnete})

Benutzeravatar von Steve Hawkins
Steve Hawkins

Sie werden zusammen verwendet, um einen neuen untergeordneten Prozess zu erstellen. Zuerst anrufen fork erstellt eine Kopie des aktuellen Prozesses (des untergeordneten Prozesses). Dann, exec wird innerhalb des untergeordneten Prozesses aufgerufen, um die Kopie des übergeordneten Prozesses durch den neuen Prozess zu “ersetzen”.

Der Prozess läuft in etwa so ab:

child = fork();  //Fork returns a PID for the parent process, or 0 for the child, or -1 for Fail

if (child < 0) {
    std::cout << "Failed to fork GUI process...Exiting" << std::endl;
    exit (-1);
} else if (child == 0) {       // This is the Child Process
    // Call one of the "exec" functions to create the child process
    execvp (argv[0], const_cast<char**>(argv));
} else {                       // This is the Parent Process
    //Continue executing parent process
}

  • In der siebten Zeile wird erwähnt, dass die Funktion exec() den untergeordneten Prozess erstellt. Ist es wirklich so, weil fork() den untergeordneten Prozess bereits erstellt hat und der Aufruf von exec() nur das Programm des gerade erstellten neuen Prozesses ersetzt

    – Binder

    25. Mai 2014 um 2:54 Uhr

Benutzeravatar von Abdulhakim Zeinu
Abdulhakim Zeinu

Der Hauptunterschied zw fork() und exec() ist das,

Das fork() Systemaufruf erstellt einen Klon des aktuell laufenden Programms. Das ursprüngliche Programm setzt die Ausführung mit der nächsten Codezeile nach dem Aufruf der Funktion fork() fort. Der Klon beginnt auch mit der Ausführung in der nächsten Codezeile. Schauen Sie sich den folgenden Code an, den ich bekommen habe http://timmurphy.org/2014/04/26/using-fork-in-cc-a-minimum-working-example/

#include <stdio.h>
#include <unistd.h>
int main(int argc, char **argv)
{
    printf("--beginning of program\n");
    int counter = 0;
    pid_t pid = fork();
    if (pid == 0)
    {
        // child process
        int i = 0;
        for (; i < 5; ++i)
        {
            printf("child process: counter=%d\n", ++counter);
        }
    }
    else if (pid > 0)
    {
        // parent process
        int j = 0;
        for (; j < 5; ++j)
        {
            printf("parent process: counter=%d\n", ++counter);
        }
    }
    else
    {
        // fork failed
        printf("fork() failed!\n");
        return 1;
    }
    printf("--end of program--\n");
    return 0;
}

Dieses Programm deklariert zuvor eine auf Null gesetzte Zählervariable fork()ing. Nach dem Fork-Aufruf laufen zwei Prozesse parallel, die beide ihre eigene Version des Zählers erhöhen. Jeder Prozess wird bis zum Abschluss ausgeführt und beendet. Da die Prozesse parallel ablaufen, wissen wir nicht, wer zuerst fertig wird. Wenn Sie dieses Programm ausführen, wird etwas Ähnliches wie unten gezeigt gedruckt, obwohl die Ergebnisse von einem Lauf zum nächsten variieren können.

--beginning of program
parent process: counter=1
parent process: counter=2
parent process: counter=3
child process: counter=1
parent process: counter=4
child process: counter=2
parent process: counter=5
child process: counter=3
--end of program--
child process: counter=4
child process: counter=5
--end of program--

Das exec() Familie von Systemaufrufen ersetzt den aktuell ausgeführten Code eines Prozesses durch einen anderen Codeabschnitt. Der Prozess behält seine PID, wird aber zu einem neuen Programm. Betrachten Sie beispielsweise den folgenden Code:

#include <stdio.h> 
#include <unistd.h> 
main() {
 char program[80],*args[3];
 int i; 
printf("Ready to exec()...\n"); 
strcpy(program,"date"); 
args[0]="date"; 
args[1]="-u"; 
args[2]=NULL; 
i=execvp(program,args); 
printf("i=%d ... did it work?\n",i); 
} 

Dieses Programm ruft die execvp() Funktion, um ihren Code durch das Datumsprogramm zu ersetzen. Wenn der Code in einer Datei namens exec1.c gespeichert ist, erzeugt die Ausführung die folgende Ausgabe:

Ready to exec()... 
Tue Jul 15 20:17:53 UTC 2008 

Das Programm gibt die Zeile „Ready to exec()“ aus. . . “ und ersetzt nach dem Aufruf der Funktion execvp() deren Code durch das Datumsprogramm. Beachten Sie, dass die Zeile ― . . . hat es geklappt“ wird nicht angezeigt, da der Code an dieser Stelle ersetzt wurde. Stattdessen sehen wir die Ausgabe der Ausführung von „date -u“.

  • In der siebten Zeile wird erwähnt, dass die Funktion exec() den untergeordneten Prozess erstellt. Ist es wirklich so, weil fork() den untergeordneten Prozess bereits erstellt hat und der Aufruf von exec() nur das Programm des gerade erstellten neuen Prozesses ersetzt

    – Binder

    25. Mai 2014 um 2:54 Uhr

fork() erstellt eine Kopie des aktuellen Prozesses, wobei die Ausführung im neuen untergeordneten Prozess unmittelbar nach dem Aufruf von fork() beginnt. Nach dem fork() sind sie bis auf den Rückgabewert der Funktion fork() identisch. (RTFM für weitere Details.) Die beiden Prozesse können dann noch weiter auseinanderlaufen, wobei einer den anderen nicht stören kann, außer möglicherweise durch gemeinsam genutzte Dateihandles.

exec() ersetzt den aktuellen Prozess durch einen neuen. Es hat nichts mit fork() zu tun, außer dass ein exec() oft auf fork() folgt, wenn es darum geht, einen anderen untergeordneten Prozess zu starten, anstatt den aktuellen zu ersetzen.

1426100cookie-checkUnterschiede zwischen Fork und Exec

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy