web-dev-qa-db-fra.com

fork () branches plus que prévu?

Considérez le morceau de code suivant:

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

int main(void)
{
    int i;
    for(i = 0; i < 2; i++)
    {
        fork();
        printf(".");
    }
    return 0;
}

Ce programme génère 8 points. Comment est-ce possible? Ne devrait-il pas y avoir 6 points à la place?

186
Nikolay Kovalenko

La primitive fork() étire souvent l'imagination. Jusqu'à ce que vous vous en rendiez compte, vous devez tracer sur papier ce qu'est chaque opération et tenir compte du nombre de processus. N'oubliez pas que fork () crée une copie presque parfaite du processus actuel. La différence la plus significative (dans la plupart des cas) est que la valeur de retour de fork() diffère entre le parent et l'enfant. (Comme ce code ignore la valeur de retour, cela ne fait aucune différence.)

Donc, au début, il y a un processus. Cela crée un deuxième processus, qui imprime tous deux un point et une boucle. À leur deuxième itération, chacun crée une autre copie, il y a donc quatre processus: imprime un point, puis quitte. Nous pouvons donc facilement représenter six points, comme vous vous en doutez.

Cependant, ce que printf() fait vraiment, c'est tamponner sa sortie. Ainsi, le premier point à partir du moment où il n'y avait que deux processus n'apparaît pas lors de l'écriture. Ces points restent dans le tampon, qui est dupliqué à fork (). Ce n'est que lorsque le processus est sur le point de se terminer que le point tamponné apparaît. Quatre processus d'impression d'un point tamponné, plus le nouveau donne 8 points.

Si vous souhaitez éviter ce comportement, appelez fflush(stdout); après printf().

245
wallyk

Vous avez tampons non validés dans les flux de sortie. stdout est mis en mémoire tampon de ligne et le tampon est répliqué avec le reste du processus. À la fin du programme, le tampon non engagé est écrit deux fois (une fois pour chaque processus). Les deux utilisant

printf("a\n");

et

printf("a "); fflush(stdout);

ne présente pas le problème.

Dans votre premier exemple, vous créez quatre processus qui ont chacun deux points dans leur tampon de flux de sortie. Lorsque chaque flux se termine, il vide son tampon, générant huit points.

70
thiton

quand i =

Process_1: texte tamponné = 1 point

Process_2 (créé par Process_1): texte tamponné = 1 point

quand i = 1

Process_3 (créé par Process_1): héritez 1 point tamponné de Process_1 et imprime 1 point par lui-même. Au total, Process_3 imprime 2 points.

Process_4 (créé par Process_2): héritez 1 point tamponné de Process_2 et imprime 1 point par lui-même. Au total, Process_4 imprime 2 points.

Process_1: imprime 2 points (un point tamponné lorsque i = 0 et un autre point lorsque i = 1)

Process_2: imprime 2 points (un point tamponné lorsque i = 0 et un autre point lorsque i = 1)

Sortie finale: 8 points. :)

2
Tauseef