IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Linux Discussion :

Fork() : y'a un truc que je pige pas


Sujet :

Linux

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 33
    Points : 23
    Points
    23
    Par défaut Fork() : y'a un truc que je pige pas
    Soit le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <errno.h>
     
    int main(void) 
    {
        pid_t  pid;
        if((pid = fork()) == -1)
        {
             fprintf(stderr,"Echec de fork erreur numéro %d.\n", errno) ;
             exit(1) ;
        }
     
        if(pid == 0)
            printf(" Cet affichage est réalisé par le fiston.\n");
         else
             printf("Cet affichage est réalisé par le papa.\n");
    }
    Quand on fait un fork, on fait une copie et donc ma question est : est-ce que le fils peut faire un fork lui aussi ?
    Ca m'embrouille :s parce que le fils execute cette instruction if((pid = fork()) == -1) non?

    En fait si je pose cette question c'est parce que mon programme a un comportement bizarre : son but est de créer un nombre donné en argument de fork; Puis chaque fork affiche son pid et attend deux secondes. Pendant ce temps le pere attend la mort des fork et affiche le pid d'un fork une fois celui ci mort.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/wait.h>
    #include <errno.h>
    #include <time.h>
     
    int main(int argc, char * argv[])
    {
    	unsigned nbFolk; // Nombre de fois que le programme doit se cloner
    	pid_t pid;
    	pid_t pidFilsMort;
     
    	int err;
    	unsigned i;
     
    	if (argc < 2)
    	{
    		fprintf(stderr, "Lancer le programme avec un argument\n");
    		exit(EXIT_FAILURE);
    	}
    	else
    	{
    		err = sscanf(argv[1], "%d", &nbFolk);
    		if (err < 1)
    		{
    			fprintf(stderr, "Erreur survenu sur l'argument\n");
    			printf("Verifier que l'argument soit correct :\n");
    			printf("Usage : nombre entier\n");
    			exit(EXIT_FAILURE);		
    		}
    		if (err == EOF)
    		{
    			perror("Erreur survenu sur l'argument : ");
    			exit(EXIT_FAILURE);	
    		}
     
    		for (i = 0; i < nbFolk; i++)
    		{
    			if((pid = fork()) == -1)
    			{
    				fprintf(stderr, "Erreur de fork %d", errno);
    				exit(EXIT_FAILURE);
    			}
    		}
     
    		switch (pid)
    		{
    			case 0 :
    				printf("PID = %ld\n", (long) getpid());
    				sleep(nbFolk * 2);
    				break;
    			default :
    				while ((pidFilsMort = wait(NULL)) != -1)
    					printf("\nPID du fils mort : %ld\n", (long) pidFilsMort);
    		}
    	}
     
    	return EXIT_SUCCESS;
    }
    Avec 1 en argument le comportement est correct, avec 2 voici ci dessous le résultat, avec 3 c'est encore pire..
    sinan@sinux:~$ ./test 2
    PID = 9429
    PID = 9430

    PID du fils mort : 9429
    PID du fils mort : 9428
    PID du fils mort : 9430

  2. #2
    Membre averti
    Inscrit en
    Septembre 2006
    Messages
    414
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 414
    Points : 354
    Points
    354
    Par défaut
    bon alors je suis pas sur de ce que je vais te dire, mais voila comment je comprend la chose:
    je suppose que fork va enregistrer dans une variable le pid du pere.
    lorsque fork est appelé chez le fils et qu'il trouve que le pid du processus qu l'appel != pid sauvegardé alors il retourne 0...

    et si ca marche, c'est parceque tout le contexte est recopié, donc la memoire aussi, donc la variable contenant le pid sauvegardé.
    __________
    "Any sufficiently advanced technology is indistinguishable from magic" Arthur C. Clarke

  3. #3
    Membre averti
    Inscrit en
    Septembre 2006
    Messages
    414
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 414
    Points : 354
    Points
    354
    Par défaut
    c'est normal...ce que tu cherche a faire est tiré par les cheveux ^^
    ce comportement s'explique par le fait que tu fais une boucle ou tu frok(), tu ne sais pas qui va appeler fork(). le pere ? le fils ? en fait les deux ! meme l'ariere petit fils si tu entre 3...

    comme je te l'ai dis: le fils ne va pas forker sur le fork() dont il est issue, mais sur les suivant oui !
    explication, qui appel quoi (pour 2)

    pere-
    fils1
    fils1.2
    fils 2



    (pour 3):
    pere-
    fils1
    fils 1.2
    fils 1.2.3
    fils 1.3
    fils2
    fils 2.3
    fils3

    suis je assez clair ?
    __________
    "Any sufficiently advanced technology is indistinguishable from magic" Arthur C. Clarke

  4. #4
    Membre averti
    Inscrit en
    Septembre 2006
    Messages
    414
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 414
    Points : 354
    Points
    354
    Par défaut
    voila, j'ai corrigé en partie ton code (pas tésté, tout n'est pas fais)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    int i;
    int nbfork;
    int pid;
    int father;
    /*...*/
    pid = father = getpid();
    for(i = 0 ; i < nbfork ; i++){
      if (pid == father){
        pid = fork();
      }
      else if(pid == -1){
        //affiche erreur, pas la peine de continuer
        //attendre les fisl créés et uniquement les fils créés
        return -ENOMEM;
      }
    }
    //code comun a tous les enfants:
    switch(pid){
      case 0:
        //afficher PID du fils
        exit(0);
        break;
      default:
        //attendre TOUS les fils
        exit(0);
        break;
    }
    //se retrouver ici == erreur: un exit raté !
    //afficher pid
    return -1;
    __________
    "Any sufficiently advanced technology is indistinguishable from magic" Arthur C. Clarke

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 33
    Points : 23
    Points
    23
    Par défaut
    Jsuis en train de lire ta réponse, mais ça me parait bizarre :
    pid = father = getpid();
    for(i = 0 ; i < nbfork ; i++){
    if (pid == father){
    pid = fork();
    }
    Le fils va aussi executer l'instruction pid = father = getpid() et donc pid == father aussi pour le fils, non ?

    Edit: je viens de tester, du coup ça me cree un seul fork quelque soit l'argument, ce qui est logique puisque après le premier pid = fork, on a pid différent de father :s
    Du coup j'ai modifié le morceau de code ci dessus, ce qui donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    for (i = 0; i < nbFork; i++)
    {
        if (pidPere == getpid())
        {
            pid = fork();
        }
    else if ...
    Et cette fois ça marche !

    Merci pour ton aide

  6. #6
    Membre averti
    Inscrit en
    Septembre 2006
    Messages
    414
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 414
    Points : 354
    Points
    354
    Par défaut
    ah oui autant pour moi, je me suis emmélé les pinceaux...
    je recorrige ca tout de suite !
    __________
    "Any sufficiently advanced technology is indistinguishable from magic" Arthur C. Clarke

  7. #7
    Membre averti
    Inscrit en
    Septembre 2006
    Messages
    414
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 414
    Points : 354
    Points
    354
    Par défaut
    ca devrait etre bon
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    int i;
    int nbfork;
    int pid;
    /*...*/
    pid = 1;//valeur positive bidon
    for(i = 0 ; i < nbfork, pid > 0 ; i++){
      pid = fork();
    }
    //code comun a tous le monde:
    switch(pid){
     
      case -1:
        //afficher erreur
        //attendre les fils créés et uniquement les fils créés
        exit(1); 
      case 0:
        //afficher PID du fils
        exit(0);
      default:
        //attendre TOUS les fils
        exit(0)
    }
    __________
    "Any sufficiently advanced technology is indistinguishable from magic" Arthur C. Clarke

  8. #8
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 33
    Points : 23
    Points
    23
    Par défaut
    Je sais pas si t'as vu, j'ai fait un edit de mon precedent post avec ma solution, et pendant ce temps tu a commencer à y répondre^^
    Jpense aussi que ton code marche mais je vais garder mon truc
    C'est juste pour m'entrainer sur les fork, maintenant je comprend le fonctionnement, merci

  9. #9
    Membre averti
    Inscrit en
    Septembre 2006
    Messages
    414
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 414
    Points : 354
    Points
    354
    Par défaut
    Citation Envoyé par Sin-an Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    for (i = 0; i < nbFork; i++)
    {
        if (pidPere == getpid())
        {
            pid = fork();
        }
    else if ...
    Et cette fois ça marche !

    Merci pour ton aide
    oui mais en fait tu n'as même pas besoin de getpid... je n'avais pas vraiment reflechi...
    il suffi de verifier si pid > 0

    puis mon else if etait un peut sal... il vaut mieu tout regrouper dans le switch, c'est plus propre
    __________
    "Any sufficiently advanced technology is indistinguishable from magic" Arthur C. Clarke

  10. #10
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 33
    Points : 23
    Points
    23
    Par défaut
    Ué en fait t'as raison c'est mieux de mettre pid > 0 dans le for
    par contre je me disais que je connaissais pas cette notation if(initialisation; condition, condition, ...; incrementation) => le compilateur non plus ^^, j'ai remplacé par &&
    Puis par contre, on peut pas mettre case -1 dans le switch parce que pid contient le résultat du dernier fork(), or si un fork différent du dernier échoue ça déclenchera pas d'erreur, enfin dis moi si je me trompe?

  11. #11
    Membre averti
    Inscrit en
    Septembre 2006
    Messages
    414
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 414
    Points : 354
    Points
    354
    Par défaut
    bah si ! vu que tu teste pid > 0 ! et -1 c'est c'est plus petit que 0 ! donc les suivant ne sont meme pas forkés !
    c'est pour ca que j'ai précisé en cas d'erreur d'attendre uniquement ceux qui ont été créés !
    __________
    "Any sufficiently advanced technology is indistinguishable from magic" Arthur C. Clarke

  12. #12
    Membre averti
    Inscrit en
    Septembre 2006
    Messages
    414
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 414
    Points : 354
    Points
    354
    Par défaut
    Citation Envoyé par Sin-an Voir le message
    Ué en fait t'as raison c'est mieux de mettre pid > 0 dans le for
    par contre je me disais que je connaissais pas cette notation if(initialisation; condition, condition, ...; incrementation) => le compilateur non plus ^^, j'ai remplacé par &&
    oui en fait ca marche que pour l'initialisation et l'incrementation
    if(init1, init2; condition ; inc1, inc2)
    __________
    "Any sufficiently advanced technology is indistinguishable from magic" Arthur C. Clarke

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Débutant] Fonction surface ya un truc que je pige pas
    Par PaM... dans le forum MATLAB
    Réponses: 6
    Dernier message: 17/02/2009, 10h11
  2. Entre Paint et PaintComponent y a un truc que je pige pas?
    Par doul21 dans le forum Débuter avec Java
    Réponses: 6
    Dernier message: 11/04/2008, 10h17
  3. Quelques trucs que je ne comprends pas
    Par darkbob dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 30/10/2006, 10h15
  4. Petit truc tout simple que je comprend pas
    Par Olaf MENJI dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 29/11/2005, 16h56
  5. erreur que j ai pas comprise ds mon pg informix
    Par zineb dans le forum Informix
    Réponses: 2
    Dernier message: 16/07/2003, 13h53

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo