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

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  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é.

  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 ?

  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;

  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 !

  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
    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

+ 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, 11h11
  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, 11h17
  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, 11h15
  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, 17h56
  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, 14h53

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