Après fork (), où l'enfant commence-t-il son exécution?

22

J'essaie d'apprendre la programmation UNIX et suis tombé sur une question concernant fork (). Je comprends que fork () crée un processus identique au processus en cours d'exécution, mais où commence-t-il? Par exemple, si j'ai du code

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

La sortie est:

Il s'agit très certainement du processus parent
Quel processus a imprimé cela?
Quel processus l'a imprimé?

Je pensais que cela fork()créait un même processus, donc j'ai d'abord pensé que dans ce programme, l' fork()appel serait récursivement appelé pour toujours. Je suppose que ce nouveau processus créé à partir de fork()commence après l' fork()appel?

Si j'ajoute le code suivant, pour faire la différence entre un processus parent et enfant,

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 ());

après l'appel fork (), où le processus enfant commence-t-il son exécution?

Gilles 'SO- arrête d'être méchant'
la source
5
man forkest sûr de répondre à votre question, btw
alex

Réponses:

23

Le nouveau processus sera créé au sein de l' fork()appel, et commencera par y revenir comme le parent. La valeur de retour (dans laquelle vous avez stocké retval) fork()sera:

  • 0 dans le processus enfant
  • Le PID de l'enfant dans le processus parent
  • -1 chez le parent en cas d'échec (il n'y a pas d'enfant, naturellement)

Votre code de test fonctionne correctement; il stocke la valeur de retour de fork()in child_pidet utilise ifpour vérifier si c'est 0 ou non (bien qu'il ne vérifie pas d'erreur)

Michael Mrozek
la source
13

Je pensais que fork () créait le même processus, donc j'ai initialement que dans ce programme, l'appel fork () serait récursivement appelé pour toujours. Je suppose que le nouveau processus créé à partir de fork () commence après l'appel fork ()?

Oui. Numérotons les lignes:

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 */
}

Le flux d'exécution est le suivant:

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

... ce qui explique exactement la sortie que vous avez reçue.

Si vous voulez savoir comment le programme original et le programme forké peuvent éventuellement se comporter différemment, car ils partagent nécessairement le même code, voir la réponse de Michael Mrozek.

badp
la source
Notez que 1 n'est pas réellement une instruction. Notez également que les programmes originaux et forkés ne s'exécutent pas en même temps - l'un ou l'autre devra attendre que l'autre cède / soit préempté.
badp
1
Sur les systèmes multi-cœurs / multi-processeurs, les deux programmes peuvent réellement s'exécuter en même temps.
jlliagre
@jilliagre Les systèmes multicœurs concernent vraiment le multithreading. Quant aux systèmes à plusieurs processeurs, je ne sais pas si c'est le cas ou non dans la pratique. Je ne suis pas un expert dans ce domaine - et cela semble être un scénario aussi improbable. Si nous convenons que le système d'exploitation peut exécuter plusieurs processus en même temps (alors comment gérerait-il la concurrence?), Au moment où le programme d'origine exécute l'instruction 4 sur un processeur, les autres processeurs sont probablement occupés à exécuter d' autres processus de toute façon.
badp
Je dirais que c'est un scénario très probable, d'autant plus qu'il y a un appel système sous-jacent avec des E / S à l'étape 5. Avoir tous les processeurs occupés n'est en fait pas une situation courante car le processeur est rarement le goulot d'étranglement avec les machines actuelles. Il semble aussi que vous confondiez multi-thread et multi-core.
jlliagre
8
Puis-je simplement dire que ces flèches diagonales sont fantastiques .
JBirch
0

La vraie solution à cela est

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--
la source
-1

quel que soit le code juste après le fork(), est copié dans le processus enfant, et ne mélangez pas le processus parent et enfant, ce sont deux entités différentes, qui ont le même environnement (dupliqué, non partagé).

Maintenant, voyez votre sortie ...

user2670535
la source