Wo beginnt das Kind nach fork () mit der Ausführung?

22

Ich versuche UNIX-Programmierung zu lernen und bin auf eine Frage bezüglich fork () gestoßen. Ich verstehe, dass fork () einen identischen Prozess wie der aktuell ausgeführte Prozess erstellt, aber wo beginnt er? Zum Beispiel, wenn ich Code habe

int main (int argc, char **argv)
{
    int retval;
    printf ("This is most definitely the parent process\n");
    fflush (stdout);
    retval = fork ();
    printf ("Which process printed this?\n");

    return (EXIT_SUCCESS);
}

Die Ausgabe ist:

Dies ist mit Sicherheit der übergeordnete Prozess.
Welcher Prozess hat dies gedruckt?
Welcher Prozess hat das gedruckt?

Ich dachte, das fork()schafft den gleichen Prozess, also habe ich anfangs gedacht, dass in diesem Programm der fork()Aufruf für immer rekursiv aufgerufen wird. Ich vermute, dass ein neuer Prozess, der von erstellt wurde, fork()nach dem fork()Aufruf startet ?

Wenn ich den folgenden Code hinzufüge, um zwischen einem übergeordneten und einem untergeordneten Prozess zu unterscheiden,

if (child_pid = fork ()) printf ("This is the parent, child pid is %d\n", child_pid);
else printf ("This is the child, pid is %d\n",getpid ());

Wo beginnt nach dem Aufruf von fork () die Ausführung des untergeordneten Prozesses?

Gilles 'SO - hör auf böse zu sein'
quelle
5
man forkist sicher genug, um deine Frage zu beantworten, übrigens
alex

Antworten:

23

Der neue Prozess wird innerhalb des fork()Aufrufs erstellt und kehrt zunächst genau wie der übergeordnete Prozess von dort zurück. Der Rückgabewert (in dem Sie gespeichert haben retval) von fork()lautet:

  • 0 im untergeordneten Prozess
  • Die PID des untergeordneten Elements im übergeordneten Prozess
  • -1 im Elternteil, wenn ein Fehler aufgetreten ist (natürlich gibt es kein Kind)

Ihr Testcode funktioniert ordnungsgemäß. Es speichert den Rückgabewert von fork()in child_pidund ifprüft, ob es 0 ist oder nicht (obwohl es nicht auf Fehler prüft).

Michael Mrozek
quelle
13

Ich dachte, dass fork () den gleichen Prozess erzeugt, also habe ich zunächst angenommen, dass der Aufruf fork () in diesem Programm für immer rekursiv aufgerufen wird. Ich vermute, dass ein neuer Prozess, der mit fork () erstellt wurde, nach dem Aufruf von fork () startet.

Ja. Lassen Sie uns die Zeilen nummerieren:

int main (int argc, char **argv)
{
    int retval;                                               /* 1 */
    printf ("This is most definitely the parent process\n");  /* 2 */
    fflush (stdout);                                          /* 3 */
    retval = fork ();                                         /* 4 */
    printf ("Which process printed this?\n");                 /* 5 */
    return (EXIT_SUCCESS);                                    /* 6 */
}

Der Ablauf der Ausführung ist:

caller process     fork()  ...
                          
original program            exec()  2  3  4  5  6
                                               
forked program                                   5  6

... was genau die Ausgabe erklärt, die Sie erhalten haben.

Wenn Sie wissen möchten, wie sich das ursprüngliche und das gegabelte Programm möglicherweise unterschiedlich verhalten können, da sie notwendigerweise denselben Code verwenden, lesen Sie die Antwort von Michael Mrozek.

badp
quelle
Beachten Sie, dass 1 eigentlich keine Anweisung ist. Beachten Sie auch, dass das ursprüngliche und das gegabelte Programm nicht gleichzeitig ausgeführt werden - eines muss warten, bis das andere nachgibt / vorbelastet wird.
badp
1
Auf Multi-Core- / Multi-CPU-Systemen können beide Programme gleichzeitig ausgeführt werden.
Juli
@jilliagre Bei Multicore-Systemen geht es wirklich um Multithreading. Was Systeme mit mehreren CPUs betrifft, weiß ich nicht, ob dies in der Praxis der Fall ist oder nicht . Ich bin kein Experte auf diesem Gebiet - und es scheint nur so ein unwahrscheinliches Szenario. Wenn wir uns einig sind, dass das Betriebssystem mehrere Prozesse gleichzeitig ausführen kann (wie würde es dann die Parallelität behandeln?), Sind die anderen CPUs wahrscheinlich sowieso damit beschäftigt, andere Prozesse auszuführen, bis das ursprüngliche Programm Befehl 4 auf einer CPU ausführt.
badp
Ich würde sagen, dass dies ein sehr wahrscheinliches Szenario ist, insbesondere, da in Schritt 5 ein zugrunde liegender Systemaufruf mit einigen E / A-Vorgängen stattfindet. Die Tatsache, dass alle CPUs ausgelastet sind, ist eigentlich keine häufige Situation, da die CPU bei aktuellen Computern selten der Engpass ist. Es scheint auch, dass Sie Multi-Threading und Multi-Core verwirren.
Juli
8
Kann ich nur sagen, dass diese diagonalen Pfeile fantastisch sind .
JBirch
0

Die wirkliche Lösung dafür ist

switch (fork()) {
    case -1 :
        fprintf (stderr, "fork failed (%s)\n", strerror(errno));
        break;
    case 0 :  // child process comes here
        break;
    default : // parent process
        break;
}

// all continue here
ott--
quelle
-1

Unabhängig davon, ob der Code direkt nach dem fork()in den untergeordneten Prozess kopiert wird und der übergeordnete und der untergeordnete Prozess nicht vertauscht werden, handelt es sich um zwei verschiedene Entitäten mit derselben (duplizierten, nicht gemeinsam genutzten) Umgebung.

Nun sehen Sie Ihre Ausgabe ...

user2670535
quelle