web-dev-qa-db-fra.com

Fonction Fork () en C

Vous trouverez ci-dessous un exemple de la fonction Fork en action. Ci-dessous se trouve également la sortie. Ma principale question a trait au fait que la fourche est appelée comment les valeurs sont changées. Donc, pid1,2 et 3 commencent à 0 et sont modifiés au fur et à mesure que les fourches se produisent. Est-ce parce que chaque fois qu'un fork survient, les valeurs sont copiées dans l'enfant et la valeur spécifique est modifiée dans le parent? Fondamentalement, comment les valeurs changent-elles avec les fonctions fork?

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main() {
    pid_t pid1, pid2, pid3;
    pid1=0, pid2=0, pid3=0;
    pid1= fork(); /* A */
    if(pid1==0){
        pid2=fork(); /* B */
        pid3=fork(); /* C */
    } else {
        pid3=fork(); /* D */
        if(pid3==0) {
            pid2=fork(); /* E */
        }
        if((pid1 == 0)&&(pid2 == 0))
            printf("Level 1\n");
        if(pid1 !=0)
            printf("Level 2\n");
        if(pid2 !=0)
           printf("Level 3\n");
        if(pid3 !=0)
           printf("Level 4\n");
       return 0;
    }
}

Alors ceci est l'exécution.

----A----D--------- (pid1!=0, pid2==0(as initialized), pid3!=0, print "Level 2" and "Level 4")
    |    |
    |    +----E---- (pid1!=0, pid2!=0, pid3==0, print "Level 2" and "Level 3")
    |         |
    |         +---- (pid1!=0, pid2==0, pid3==0, print "Level 2")
    |
    +----B----C---- (pid1==0, pid2!=0, pid3!=0, print nothing)
         |    |
         |    +---- (pid1==0, pid2==0, pid3==0, print nothing)
         |
         +----C---- (pid1==0, pid2==0, pid3!=0, print nothing)
              |
              +---- (pid1==0, pid2==0, pid3==0, print nothing)

Idéalement, voici comment j'aimerais que cela soit expliqué car cette façon de procéder me semble sensée. Les * sont où se trouve ma principale confusion. Quand l'enfant bifurque par exemple, pid1 = fork(); crée un processus avec toutes les valeurs du parent, mais transmet-il ensuite une valeur telle que disons 1 aux parents pid1? Ce qui signifie que l'enfant aurait pid 1 = 0, pid2 = 0 et pid3 = 0 et le parent alors pid1 = 2 et pid2 et 3 égal à 0? enter image description here

18
Plisken

L'appel système fork () est utilisé pour créer des processus. Il ne prend aucun argument et retourne un ID de processus. Fork () a pour but de créer un nouveau processus, qui devient le processus enfant de l'appelant. Après la création d’un nouveau processus enfant, les deux processus exécuteront l’instruction suivante à la suite de l’appel système fork (). Par conséquent, nous devons distinguer le parent de l'enfant. Cela peut être fait en testant la valeur retournée de fork ()

Fork est un appel système et vous ne devriez pas y voir une fonction C normale. Lorsqu'un fork () se produit , vous créez effectivement deux nouveaux processus avec leur propre espace d'adressage. Les variables initialisées avant l'appel de fork () stockent les mêmes valeurs dans l'espace d'adressage. Cependant, les valeurs modifiées dans l'espace d'adressage de l'un des processus ne sont pas affectées par un autre processus , l'un étant parent et l'autre étant enfant. Donc si,

pid=fork();

Si, dans les blocs de code suivants, vous vérifiez la valeur de pid, les processus s'exécutent sur toute la longueur de votre code. Alors, comment pouvons-nous les distinguer. Encore une fois Fork est un appel système et voici la différence . À l'intérieur du processus enfant nouvellement créé, pid stockera 0, tandis que dans le processus parent, il stockera une valeur positive. .Une valeur négative dans pid indique une erreur de branche.

Lorsque nous testons la valeur de pid pour déterminer si elle est égale à zéro ou supérieure à celle-ci, nous découvrons effectivement si nous sommes dans le processus enfant ou dans le processus parent.

En savoir plus sur Fork

24
Rahul Jha
int a = fork(); 

Crée un processus en double "clone?", Qui partage la pile d'exécution. La différence entre le parent et l'enfant est la valeur de retour de la fonction.

L'enfant obtenant 0 est revenu et le parent récupère le nouveau pid.

Chaque fois, les adresses et les valeurs des variables de la pile sont copiées. L'exécution continue au point où elle se trouvait déjà dans le code.

À chaque fork, une seule valeur est modifiée - la valeur de retour de fork.

6
mksteve

D'abord un lien vers de la documentation de fork ()

http://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html

Le pid est fourni par le noyau. Chaque fois que le noyau crée un nouveau processus, il augmente le compteur de pid interne et assigne ce nouveau processus à un nouveau pid unique, tout en évitant les doublons. Une fois que le pid a atteint un nombre élevé, il sera emballé et recommencera.

Donc, vous ne savez jamais quel pid vous obtiendrez de fork (), seulement que le parent conservera son pid unique et que fork s'assurera que le processus enfant aura un nouveau pid unique. Ceci est indiqué dans la documentation fournie ci-dessus.

Si vous continuez à lire la documentation, vous verrez que fork () renvoie 0 pour le processus enfant et que le nouveau pid unique de l'enfant est renvoyé au parent. Si l'enfant veut savoir qu'il a son propre nouveau pid, vous devrez le rechercher à l'aide de getpid ().

pid_t pid = fork()
if(pid == 0) {
    printf("this is a child: my new unique pid is %d\n", getpid());
} else {
    printf("this is the parent: my pid is %d and I have a child with pid %d \n", getpid(), pid);
}

et ci-dessous quelques commentaires en ligne sur votre code

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main() {
    pid_t pid1, pid2, pid3;
    pid1=0, pid2=0, pid3=0;
    pid1= fork(); /* A */
    if(pid1 == 0){
        /* This is child A */
        pid2=fork(); /* B */
        pid3=fork(); /* C */
    } else {
        /* This is parent A */
        /* Child B and C will never reach this code */
        pid3=fork(); /* D */
        if(pid3==0) {
            /* This is child D fork'ed from parent A */
            pid2=fork(); /* E */
        }
        if((pid1 == 0)&&(pid2 == 0)) {
            /* pid1 will never be 0 here so this is dead code */
            printf("Level 1\n");
        }
        if(pid1 !=0) {
            /* This is always true for both parent and child E */
            printf("Level 2\n");
        }
        if(pid2 !=0) {
           /* This is parent E (same as parent A) */
           printf("Level 3\n");
        }
        if(pid3 !=0) {
           /* This is parent D (same as parent A) */
           printf("Level 4\n");
        }
    }
    return 0;
}
3
leakim