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

C Discussion :

Fork langage C


Sujet :

C

  1. #1
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2011
    Messages : 6
    Points : 3
    Points
    3
    Par défaut Fork langage C
    Bonjour, je suis débutant en programmation j aimerais savoir comment créer un programme père qui crée 2 fils, chaque fils crée deux fils, chaque processus écrit: je suis PID mon père est PPID. Merci d'avance.

    voici mon code pour un programme père qui crée un fils:




    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
    int main (int argc, char * argv[]){ 
     
    pid_t pid; 
     
    if ((pid = fork())<0){ 
    fprintf (stderr,"Il y a une erreur \n"); 
    exit(EXIT_FAILURE); 
    } 
    else if (pid == 0){ 
    printf("FILS: Je suis le fils, mon pid est: %d, celui de mon père: %d \n",getpid(), getppid()); 
    exit(EXIT_SUCCESS); 
    } 
    else { 
    printf("PÈRE: Je suis le père, mon pid est: %d, celui de mon fils: %d \n",getpid(), pid); 
    int fin = wait(0); 
    printf ("PÈRE: Mon fils se termine: son pid %d \n",fin); 
    exit (EXIT_SUCCESS); 
    } 
    }

  2. #2
    Membre expérimenté Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Points : 1 396
    Points
    1 396
    Par défaut
    Salut,

    Il y a une balise CODE pour que le code soit formaté

    Ensuite c'est pas très compliqué si tu as compris comment analyser le résultat du fork. Si tu dessines sur papier tu comprendras peut-être mieux.

    Ce qui peut t'aider c'est de faire deux fonctions : une pour les fils et une pour les petits fils. Commence par celle du petit fils dans laquelle tu ne fais que afficher et puis tu quittes. Ensuite dans celle du fils tu fais une boucle de fork et tu appels la fonction petit fils. Tu attends les deux petits fils (2 wait()) et puis tu quittes. Puis dans le père tu fais pareil

    Il y a aussi moyen de faire plus élégant avec une seule fonction (car tu répètes du code, tu vois bien que le père et ses fils font la même chose).

  3. #3
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2011
    Messages : 6
    Points : 3
    Points
    3
    Par défaut
    Merci beaucoup de ton aide j ai compris .

  4. #4
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    N'ayant jamais utilisé fork(), je me suis dis que c'était le moment. J'ai donc essayé de faire le premier niveau (père + 2 fils) et je me pose une question sur l'utilisation de wait(). Voici mon code :

    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
    #include <stdio.h>
    #include <sys/types.h> // pour pid_t
    #include <unistd.h>  // pour fork(), getpid(), getppid()
    #include <sys/wait.h>  // pour wait()
     
    #define NBR_FILS 2
     
    int main (void)
    {
        pid_t fils[10];
        pid_t pere = getpid();
        int i=0;
     
        // Generation des fils
        for(i=0;i<NBR_FILS;i++)
        {
            fils[i] = fork();
            if(getpid() != pere)
                break;
            // Traitement lors du fork
            if(fils[i]<0)
            {
                fprintf(stderr,"Fork impossible");
                return -1;
            }
        }
     
        // Determination en fonction de la place genealogique
        pid_t pid = getpid();
        if (pid==pere)
        {
            fprintf(stdout, "Je suis le pere, monsieur %d\n", pere);
            // Attendre tous les fils
            for(i=0;i<NBR_FILS;wait(NULL),i++)
                ;
            fprintf(stdout, "Tous mes fils sont termines");
            return 1;
     
        } else if (pid!=pere)
        {
             fprintf(stdout,"Je suis le fils %d\t",getpid() );
             fprintf(stdout,"J'aime mon papa %d = %d\n", getppid(), pere );
             return 2;
        }
        return 0;
    }
    De ce que j'ai compris, wait() attend la fin d'un fils. Dans mon code, ma boucle ne fait met pas en attente de tous les fils, comme on pourrait faire un join avec les threads non ?

  5. #5
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2011
    Messages : 6
    Points : 3
    Points
    3
    Par défaut
    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
     
    int main (int argc, char * argv[])
     
        {
            pid_t pid;
            int fils=0,i;
            printf("Je suis le pere id: %d\n",getpid());
            for (i=0;i<2;i++)
            {
                fils++;
                pid=fork();
                if (pid==0)
                {
                    printf("Je suis le fils numero : %d pid:%d ppid: %d\n",fils,getpid(),getppid());
     
     
                    int fils=0,i;
                    for (i=0;i<2;i++)
                    {
                        fils++;
                        pid=fork();
                        if (pid==0)
                        {
                            printf("Je suis le petit fils numero : %d pid: %d ppid: %d \n",fils,getpid(),getppid());
                            exit(EXIT_SUCCESS);
                        }
                    }
                    exit(EXIT_SUCCESS);
                }
            }
    }
    Voila mon code (corrigez moi si il est incorrecte) mais il reste le problème des wait() que je ne sais pas ou placer pour que chaque père attende ses fils respectifs. Ou dois-je les mettre ?

  6. #6
    Membre expérimenté Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Points : 1 396
    Points
    1 396
    Par défaut
    A Bktero, il vaut mieux tester si tu es dans le père où le fils via la valeur de retour du fork et non via getpid(). Fork renvoie 0 si tu es dans le fils et le pid du fils si tu es dans le père. Sinon petite curiosité dans ton code, pourquoi utilises-tu fprintf(stdout,..); au lieu de printf ? Ça fait la même chose et printf est plus court.

    Chaque processus n'a la responsabilité que de ses fils, donc il faut que le père attende ses fils et que les fils du père attendent leur fils à eux.

    Le code ci-dessous est la correction, mais je te conseille d'essayer de placer les wait tout seul avant. Il faut évidemment comprendre où et quand le code de chaque partie est exécutée et c'est plus facile si tu fais des fonctions comme précisé plus haut. D'une autre part il faut que tu tests les retours de tes fork !

    Compilé avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    >gcc programme -std=c99
    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
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
     
    #define NB_FILS 2
     
    void petit_fils()
    {
      printf("Petit fils | PID %d | PPID %d \n", getpid(), getppid());
      exit(EXIT_SUCCESS);
    }
     
    void fils()
    {
      printf("Fils | PID %d | PPID %d \n", getpid(), getppid());
     
      for(int i=0; i < NB_FILS; ++i)
      {
        pid_t pid = fork();
        if(pid == -1)
        {
          perror("fork");
          exit(EXIT_FAILURE);
        }
     
        if(pid == 0)
          petit_fils();
      }
      for(int i=0, status; i < NB_FILS; ++i)
        wait(&status);
     
      exit(EXIT_SUCCESS);
    }
     
    int main(int argc, char* argv[])
    {
     
      for(int i=0; i < NB_FILS; ++i)
      {
        pid_t pid = fork();
        if(pid == -1)
        {
          perror("fork");
          exit(EXIT_FAILURE);
        }
     
        if(pid == 0)
          fils();
      } 
      printf("Pere | PID %d | PPID %d \n", getpid(), getppid());
     
      for(int i=0, status; i < NB_FILS; ++i)
        wait(&status);
     
      return EXIT_SUCCESS;
    }
    Si tu veux, tu peux essayer de faire le même programme avec un nombre de générations paramétrables. Ici ça serait 2. Si tu veux je pourrai te mettre la "correction" quand tu auras montré ce que tu as fait.

  7. #7
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2011
    Messages : 6
    Points : 3
    Points
    3
    Par défaut
    Trademark, est ce que tu pourrais m'expliquer cette partie de con code stp :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
        for(int i=0, status; i < NB_FILS; ++i)
            wait(&status);
    ça me serais vraiment utile car j aimerais refaire le code par moi même après avoir compris le tien.

  8. #8
    Membre expérimenté Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Points : 1 396
    Points
    1 396
    Par défaut
    Oui bien sûr

    Voici l'algorithme de base mais simplifié :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // Création des fils.
    for(int i=0; i < NB_FILS; ++i)
    {
      pid_t pid = fork();
      if(pid == 0)
        fils();
    }
    // Attente des fils.
    for(int i=0, status; i < NB_FILS; ++i)
      wait(&status);
    La première boucle sert à créer les fils, évidemment la fonction fils contient un exit(EXIT_SUCCESS) sinon je te laisse deviner ce qui se passerait.

    Il n'y a donc que le père qui boucle, quand il a lancé tous les fils il ne reste plus qu'à aller attendre exactement le même nombre de fils, d'où une deuxième boucle contenant cette fois un wait() pour chaque fils.

  9. #9
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Trademark Voir le message
    A Bktero, il vaut mieux tester si tu es dans le père où le fils via la valeur de retour du fork et non via getpid(). Fork renvoie 0 si tu es dans le fils et le pid du fils si tu es dans le père. Sinon petite curiosité dans ton code, pourquoi utilises-tu fprintf(stdout,..); au lieu de printf ? Ça fait la même chose et printf est plus court.
    Point 1 : je connais la valeur que renvoie fork(). Je ne vois pas trop pourquoi c'est "mieux". Si j'ai mémorisé le pid du père dans une variable, alors le père comme le fils possède cette variable avec la valeur qui va bien et que je peux comparer au retour de getpid().

    Point 2 : parce que j'ai d'abord écrit un fprintf avec un stderr et j'ai copié-collé et j'ai changé stderr en stdout et puis je sais pas en fait...

    Pour l'histoire du wait() qu'en penses-tu ?

    J'avais posté un message avec un autre code qui permet de générer un nombre illimité de générations, avec un nombre paramétrable de processus par génération... mais le message a dû resté dans les tuyaux !

  10. #10
    Membre expérimenté Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Points : 1 396
    Points
    1 396
    Par défaut
    ma boucle ne fait met pas en attente de tous les fils
    Je dois t'avouer que j'ai pas bien compris ^^. Mais pour comparer à pthread_join qui attend un thread en particulier, waitpid attend un pid en particulier

    Ensuite, pour ton "point 1", c'est mieux d'utiliser le retour du fork() ainsi tu épargnes un appel de fonction qui est couteux vu que c'est un appel système.

  11. #11
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2011
    Messages : 6
    Points : 3
    Points
    3
    Par défaut
    Merci pour l explication j avais un peut de mal avec les wait() mais je pense avoir bien compris, reste plus que a s entrainer pour que la logique rentre ^^.

  12. #12
    Membre éprouvé Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Points : 997
    Points
    997
    Par défaut
    Bonjour.
    Je viens de tomber sur ce topic, et je me rends compte qu'il y a certaines questions sans réponse.
    Depuis le temps, ce n'est peut-être plus d'actualité, mais bon…

    Chez moi, le code de @Bktero fonctionne normalement.
    Je ne saurais dire ce qui clochait…
    On utilise bel et bien wait() pour des processus et join() pour des threads de la même manière.

    Pour ce qui est de getpid(), tu l'appelles au tout début du programme, puis 2 fois à chaque création de fils (une fois dans le père et une fois dans le fils), puis encore 2 fois quand tu veux déterminer si tu es dans le père ou le fils (une fois dans le père et une fois dans le fils), et une dernière fois par fils.
    Soit au total 1 + 2*n + 2*n + n = 5*n + 1, n étant le nombre de processus fils.
    Sachant que seul 1 appel par processus (soit n+1 au total), ça fait beaucoup de gâchis.
    Surtout que comme l'a rappelé @Trademark, c'est un appel système coûteux.

    Sinon, j'ai un peu réorganisé ton code.
    • Vu que dans cet exemple tu n'utilises pas le PID des fils, j'ai supprimé de tableau, mais ça ne change rien avec.
    • Si un fork() échoue alors que des fils ont été créés avec succès, on peut quand même les attendre.
    • Lors de l'attente des fils, plutôt que faire varier i de 0 à NBR_FILS, sa valeur représente le nombre de fils à attendre.
    • Et évidemment, il n'y a plus qu'un seul appel à getpid() par processus.


    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
    #include <stdio.h>
    #include <unistd.h>         // pour fork(), getpid(), getppid()
    #include <sys/types.h>      // pour pid_t
    #include <sys/wait.h>       // pour wait()
     
    #define NBR_FILS 2
     
    int main()
    {
        pid_t pid;
        pid_t pere = getpid();
        int i;
        int ret = 1
     
        // Generation des fils
        for (i = 0; i < NBR_FILS; ++i) {
            pid = fork();
            if (pid == 0)
                break;
            // Traitement lors du fork
            if (pid < 0) {
                fputs("Fork impossible\n", stderr);
                ret = -1;
                break;
            }
        }
        // i contient le nombre de fils correctement créés
     
        // Determination en fonction de la place genealogique
        if (pid > 0) {
            printf("Je suis le pere, monsieur %d\n", pere);
            // Attendre tous les fils
            for( ; i > 0; --i)
                wait(NULL);
            puts("Tous mes fils sont termines");
            return ret;
        }
        else if (fils == 0) {
            printf("Je suis le fils %d\t", getpid());
            printf("J'aime mon papa %d = %d\n", getppid(), pere);
            return 2;
        }
        return 0;
    }
    Ou, en un peu plus simple…
    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
    #include <stdio.h>
    #include <unistd.h>         // pour fork(), getpid(), getppid()
    #include <sys/types.h>      // pour pid_t
    #include <sys/wait.h>       // pour wait()
     
    #define NBR_FILS 2
     
    int main()
    {
        pid_t pid;
        pid_t pere = getpid();
        int i;
        int ret = 1;
     
        // Generation des fils
        for (i = 0; i < NBR_FILS; ++i) {
            pid = fork();
            // Traitement lors du fork
            if (pid < 0) {
                fputs("Fork impossible\n", stderr);
                ret = -1;
                break;
            }
            else if (pid == 0) {
                printf("Je suis le fils %d\t", getpid());
                printf("J'aime mon papa %d = %d\n", getppid(), pere);
                return 2;
            }
        }
        // i contient le nombre de fils correctement créés
     
        printf("Je suis le pere, monsieur %d\n", pere);
        // Attendre tous les fils
        for( ; i > 0; --i)
            wait(NULL);
        puts("Tous mes fils sont termines");
        return ret;
    }

Discussions similaires

  1. [langage] [Fork] Détecter un fichier
    Par GLDavid dans le forum Langage
    Réponses: 11
    Dernier message: 08/07/2004, 01h05
  2. [langage] Je cherche un bon livre ?
    Par Anonymous dans le forum Langage
    Réponses: 13
    Dernier message: 09/04/2003, 13h16
  3. [langage] comment créer des fichiers ?
    Par Anonymous dans le forum Langage
    Réponses: 3
    Dernier message: 05/05/2002, 16h33
  4. Comparer des fichiers de données : Quel Langage ?
    Par Anonymous dans le forum Langages de programmation
    Réponses: 6
    Dernier message: 24/04/2002, 22h37
  5. Cours, tutoriels, logiciels, F.A.Q,... pour le langage SQL
    Par Marc Lussac dans le forum Langage SQL
    Réponses: 0
    Dernier message: 04/04/2002, 10h21

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