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 :

Communication d'un processus avec ses deux fils


Sujet :

Linux

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Avril 2010
    Messages : 129
    Points : 84
    Points
    84
    Par défaut Communication d'un processus avec ses deux fils
    Bonjour,

    Je lis le fichier suivant ligne par ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    1
    -5
    6
    -8
    -33
    21
    Le père envoie les nombres négatifs à un processus fils, et envoie les nombres positifs à un second processus 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
    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
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
     
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/wait.h>
     
    void Fils1(int *tube1)
    {
      int n;
      int cpt = 0;
      close (tube1[1]);
     
      while (read (tube1[0], &n, 1) >0)
      {
        cpt+=n;
      }
     
      printf("Fils1 a compté : %i \n", cpt);
      exit (1) ;
    }
     
    void Fils2(int *tube2)
    {
      int n;
      int cpt = 0;
      close (tube2[1]);
     
      while (read (tube2[0], &n, 1) >0)
      {
        cpt+=n;
      }
     
      printf("Fils2 a compté : %i \n", cpt);
      exit (1) ;
    }
     
     
    int main(int argc, char *argv[])
    {
     FILE* file;
     int n;
     
     file = fopen (argv[1], "r");
     
     if (file == NULL){
          printf("Impossible d'ouvrir le fichier %s\n", argv[1]);
          exit(1);
      }
     /*------------------------------------Création des tubes-------------------------*/
     int tube1[2];
     int tube2[2];
     
     /*Création du tube entre père et Fils1*/
     if (pipe(tube1) != 0)
     {
       fprintf(stderr, "Erreur de création du 1er tube\n");
       return EXIT_FAILURE;
     }
     
     /*Création du tube entre père et Fils2*/
     if (pipe(tube2) != 0)
     {
       fprintf(stderr, "Erreur de création du 1er tube\n");
       return EXIT_FAILURE;
     }
     
     int pid1 = fork();
     
     if(pid1 == 0)
     {
        printf("Création du Fils 1 ! \n");
        Fils1 (tube1);
     }
     else
     {
        int pid2 = fork();
        if(pid2 == 0)
        {
          printf("Création du Fils 2 ! \n");
          Fils2 (tube2);
        }
        else
        {
           printf("Je suis le père ! \n");
     
           close (tube1[0]);
           close (tube2[0]);
     
           while (!feof(file))
           {
             fscanf (file,"%d",&n);
             if (n>0)
             {
        	     write (tube1[1], &n, 1);
             }
             else
             {
               write (tube2[1], &n, 1);
             }
           }
          fclose (file); //Fermeture du fichier
     
          if(wait(NULL) == -1) //On attend la mort du Fils 1 et du Fils 2
          {
            printf("Erreur: echec du wait()\n");
            exit(1);
          }
        }
     }
     
     return EXIT_SUCCESS;
    }
    Chacun des deux fils fait le compte, et affiche cela à l'écran.

    Quand j'éxecute, j'ai que ça, après on attends sans rien du tout :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Je suis le père !
    Création du Fils 1 !
    Création du Fils 2 !
    Merci de m'aider, ça fait des heures que je tourne en rond

  2. #2
    Membre averti Avatar de Mandraxx
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Mai 2011
    Messages
    182
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Lot et Garonne (Aquitaine)

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2011
    Messages : 182
    Points : 410
    Points
    410
    Par défaut
    Bonjour,

    Ton read est bloquant : il attend des données.
    Et ton process père fait un wait de processus fils qui attendent des données.

    Tout ça forme ce que l'on appelle un deadlock.

    A mon avis, si tu rajoutes le code suivant juste après ton fclose, ça doit se débloquer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    close(tube1[1]);
    close(tube2[1]);
    Et oui : le tube est une ressource qui génère implicitement 2 descripteurs de fichiers donc 4 après le fork... Il faut donc fermer les quatre (2 descripteurs côté père et 2 autres côté fils).

    Le truc, c'est que cette méthode va te faire sortir de la boucle en erreur (relais brisé), donc c'est pas super propre.

    Deux solutions pour améliorer le système :

    1. mettre au point un protocole de communication (envoyer EOF par exemple dans le tube avant de le fermer)
    2. envoyer un signal aux processus fils pour leur signaler qu'il n'y a plus de données

    @+
    Le choix motivé par le seul argument de modernité est intrinsèquement dépourvu de créativité.

  3. #3
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 368
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 368
    Points : 23 620
    Points
    23 620
    Par défaut
    Hello,

    Citation Envoyé par Mandraxx Voir le message
    Le truc, c'est que cette méthode va te faire sortir de la boucle en erreur (relais brisé), donc c'est pas super propre.

    Deux solutions pour améliorer le système :

    1. mettre au point un protocole de communication (envoyer EOF par exemple dans le tube avant de le fermer)
    2. envoyer un signal aux processus fils pour leur signaler qu'il n'y a plus de données

    @+
    Si c'est l'écrivain qui referme son tube le premier, il n'y aura pas de tube brisé. Cela sera géré par le système comme un EOF.

    Quelques remarques en revanche :

    Citation Envoyé par seanbean
    feof() ne fait pas ce que tu crois : http://c.developpez.com/faq/?page=es_general#ES_feof

    Citation Envoyé par seanbean
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
             if (n>0)
             {
        	     write (tube1[1], &n, 1);
             }
             else
             {
               write (tube2[1], &n, 1);
             }
           }
    Contrairement à fwrite() et fread() qui permettent de spécifier la taille de l'élément envoyé, read() et write() ne travaillent qu'au niveau de l'octet (enfin, du byte). Lorsque tu écris ceci, tu n'envoie pas le contenu de l'entier que tu as lu avec fscanf(), mais uniquement son premier octet en mémoire. Comme les Intel travaillent en little endian (si tu travailles sur PC), tu retomberas sur tes pattes à la condition que tous les nombres lus dans ton fichier soient compris entre 0 et 255.

  4. #4
    Membre averti Avatar de Mandraxx
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Mai 2011
    Messages
    182
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Lot et Garonne (Aquitaine)

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2011
    Messages : 182
    Points : 410
    Points
    410
    Par défaut
    Salut,

    Citation Envoyé par Obsidian Voir le message
    Si c'est l'écrivain qui referme son tube le premier, il n'y aura pas de tube brisé. Cela sera géré par le système comme un EOF.
    Ok, je n'étais pas bien sûr de ça.

    Merci.

    @+
    Le choix motivé par le seul argument de modernité est intrinsèquement dépourvu de créativité.

Discussions similaires

  1. Réponses: 2
    Dernier message: 27/04/2012, 12h57
  2. Killer un processus et ses fils avec python 2.4
    Par doudoubens dans le forum Général Python
    Réponses: 4
    Dernier message: 17/04/2012, 16h19
  3. Réponses: 0
    Dernier message: 19/07/2010, 16h25
  4. Tuer un processus et ses fils
    Par dvp_zero dans le forum Linux
    Réponses: 1
    Dernier message: 30/03/2010, 17h30
  5. communication entre le pere et ses fils
    Par facilus68 dans le forum Réseau
    Réponses: 2
    Dernier message: 13/12/2006, 23h02

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