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 entre plusieurs applications.


Sujet :

Linux

  1. #1
    Membre expérimenté
    Avatar de granquet
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2005
    Messages
    1 201
    Détails du profil
    Informations personnelles :
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2005
    Messages : 1 201
    Points : 1 421
    Points
    1 421
    Par défaut Communication entre plusieurs applications.
    j'essaye de realiser un programme tout bete ...
    je dois realiser l'interface entre 1 programme, et plusieurs autres aux moyens de pipes.

    le premier programme apelle le mien;
    mon programme se charge de lancer plusieurs autres programmes et attend des requetes sur son stdin (reçu via une pipe dans le premier programme). ensuite mon programme vas interroger tour a tour d'autres applications et recuperer les resultats (via plusieurs pipes) pour ensuite envoyer un resultat final (stdout :: pipe) a ce fameux premier programme. (vous m'avez suivi? :X)
    pas de critique sur la conception, j'ai pas trop le choix ... (malgres que tout les programmes soit open source)

    voila mon probleme (on y viens): les programmes appelés se comportent comme ce programme de test:

    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
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    int
    main ()
    {
      char inbuff[10000];
      char *ptr;
      while (fgets (inbuff, 10000, stdin) != NULL)
        {
    		if((ptr = strchr(inbuff,'\n')) != NULL)
    			*ptr = 0;
          printf ("bien recu %s\n", inbuff);
    	  fprintf(stderr,"debug: %s\n",inbuff);
    		if(inbuff[0] == 'q')
    			break;
        }
      return 0;
    }
    (le stderr n'est pas pipé)
    le fait est que je ne reçoi strictement rien ... SAUF si je met un fflush(stdout) dans la boucle de mon programme de test (celui ci dessus)

    je met le programme appelant entierement (fin, c'est la version test pipe, tout le reste n'y est pas), etant encore debutant il se peux que l'erreur soit ailleurs (si vous voyez d'autres choses ... meme qui ne soit pas relatives au sujet, n'hesitez surtout pas !)

    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
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <memory.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <unistd.h>
     
    /*
    PARENT_READ		pfd_c2p[2*i]
    CHILD_WRITE		pfd_c2p[1+2*i]
    CHILD_READ		pfd_p2c[2*i]
    PARENT_WRITE	pfd_p2c[1+2*i]
    */
    static int
    readcfg_file (char ***cmd, char ***parms)
    {
    /* mode debug */
      return 3;
    }
     
    static int
    my_read (int fd, char *outbuff, int maxlen)
    {
      int i,ret=1;
      for (i = 0; i < maxlen && outbuff[i - 1] != '\n' && ret > 0; i++)
        {
          //ici rien n'est lut. (test avec printf)
          ret = read (fd, &outbuff[i], 1);
        }
      return i;
    }
     
    int
    main (int argc, char **argv)
    {
      int *pfd_c2p = NULL;
      int *pfd_p2c = NULL;
      pid_t *pid = NULL;
      char **parms = NULL, **cmd = NULL;
      int n, i, nbytes, ret;
      char inbuff[10000];
      char outbuff[10000];
    //read the config file  
      fprintf (stdout, "reading cfg_file !\n");
      n = readcfg_file (&cmd, &parms);
      if (n > 0)
        {
          //allocate
          pfd_c2p = malloc (2 * n * sizeof (int));
          pfd_p2c = malloc (2 * n * sizeof (int));
          pid = malloc (n * sizeof (pid_t));
          if ((pid == NULL) || (pfd_c2p == NULL) || (pfd_p2c == NULL))
    	{
    	  perror ("malloc");
    	  return EXIT_FAILURE;
    	}
        }
    //create the pipes
      for (i = 0; i < n; i++)
        {
          ret = pipe (&pfd_c2p[2 * i]);
          if (ret == -1)
    	{
    	  perror ("pipe c2p");
    	  return EXIT_FAILURE;
    	}
          ret = pipe (&pfd_p2c[2 * i]);
          if (ret == -1)
    	{
    	  perror ("pipe p2c");
    	  return EXIT_FAILURE;
    	}
        }
    //spawn the processes !
      fprintf (stdout, "spawning processes\n");
      for (i = 0; i < n; i++)
        {
          pid[i] = fork ();
          if (pid[i] == 0)		//fils
    	{
    	  close (pfd_p2c[1 + 2 * i]);
    	  close (pfd_c2p[2 * i]);
     
    	  dup2 (pfd_p2c[2 * i], STDIN_FILENO);
    	  close (pfd_p2c[2 * i]);
    	  dup2 (pfd_c2p[1 + 2 * i], STDOUT_FILENO);
    	  close (pfd_c2p[1 + 2 * i]);
    	  //execv (cmd[i],parms[i]);
    	  fprintf (stderr, "launching command !\n");
    	  //execlp ("ls", "ls", (char *) 0);
    	  execv ("test-chain-red", NULL);
    	  fprintf (stderr, "erreur execv pour le processus %d:%s %s\n", i,
    		   parms[i], cmd[i]);
    	  return EXIT_FAILURE;
    	}
          else if (pid[i] > 0)	//pere
    	{
    	  close (pfd_p2c[2 * i]);
    	  close (pfd_c2p[1 + 2 * i]);
    	}
          else
    	{
    	  perror ("fork");
    	}
        }				//for
     
      //process the requets
      fprintf (stdout, "processing requests\n");
      fprintf (stdout, "input now!\n");
      while (fgets (inbuff, 10000, stdin) != NULL)
        {
          for (i = 0; i < n; i++)
    	{
    	  fprintf (stdout, "writing pipe:%d\n", i);
    	  nbytes = write (pfd_p2c[1 + 2 * i], inbuff, strlen (inbuff));
    	  if (nbytes > 0)
    	    {
    	      fprintf (stdout, "reading pipe:%d\n", i);
    //------!!!!---le prog reste "coincé" dans la fonction my_read-------!!!!!!---
    	      nbytes = my_read (pfd_c2p[2 * i], outbuff, sizeof (outbuff)-1);
    	      if (nbytes > 0)
    		{
    	          fprintf (stdout, "out: <%s>\n", outbuff);
    		}
    	      else
    		{
    		  perror ("read");
    		  return EXIT_FAILURE;
    		}
    	    }
    	  else
    	    {
    	      perror ("write");
    	      return EXIT_FAILURE;
    	    }
    	}			//for
        }				//while fgets
      return EXIT_SUCCESS;
    }
    en lisant le man, ils deconseillent de "mix" read//write et les fonctions basé sur des streams.
    j'ai transformé mes read//write en fgets//fputs en utilisant fdopen (j'ai fait deux tableaux de FILE*) et en mettant mes streams en non buffered avec setvbuf; cela n'as rien changé (je n'ai pas cette version du code sous la main par contre). j'ai essayé le mode raw sur mes file descriptors aussi ... pas mieux !

    pour resumer: ca marche quand le programmé appelé (via fork -> execv) fait un fflush(stdout). mais rien s'il n'en fait pas (pourtant il envoie des \n ?)
    et je ne peux pas modifier le comportement des programmes appelés (c'est justement pour eviter d'avoir a le faire que je fait tout ce *merdier*)
    bref, si vous avez une idée ... n'importe laquelle ... hesitez pas

    edit: haben forcement, quand je tire a pile ou face pour choisir le forum sur lequel poster, ca tombe sur le mauvais

    maintenant que c'est tombé dans le forum linux, je peux le dire ...
    ce truc devrais servir a communiquer entre squid (programme appelant) et plusieurs redirecteurs (notemment squidguard et squidclam).
    les solutions comme Willowbark ne me convenant pas ... codage de ce truc .
    click my www
    ............|___
    ...................\
    .................._|_
    ..................\ /
    ..................."

  2. #2
    Membre actif Avatar de je®ome
    Inscrit en
    Octobre 2005
    Messages
    285
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 285
    Points : 225
    Points
    225
    Par défaut
    Salut,

    je viens seulement de commencer les traitements de tuyeaux, donc j'espère ne pas raconter trop de conneries.

    Dans la partie " spawning the processes", est-ce normal que tu fermes le descripteur avant de le dupliquer ?

    Que fait la fonction recvbuff ?
    Wer nicht probiert, verliert !!

  3. #3
    Membre expérimenté
    Avatar de granquet
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2005
    Messages
    1 201
    Détails du profil
    Informations personnelles :
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2005
    Messages : 1 201
    Points : 1 421
    Points
    1 421
    Par défaut
    j'ai mal choisi mes noms de variables ... on y vois pas clair.
    mais je ne ferme les fd qu'apres les avoir dupliqué.

    les 2 premiers close ne sont pas sur les mêmes fds.

    je precise que j'ai enlevé la fonction de traitement d'erreur sur les close//dup2 pour alleger le code, mais sinon, elle y est !

    Que fait la fonction recvbuff ?
    oops, typo ... corrigé ... (ben oui, j'ai refait des bouts de code parce que j'avais pas la derniere version du code sous la main : jvais compiler et executer ce que j'ai posté ... ce seras plus serieux)
    click my www
    ............|___
    ...................\
    .................._|_
    ..................\ /
    ..................."

  4. #4
    Membre actif Avatar de je®ome
    Inscrit en
    Octobre 2005
    Messages
    285
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 285
    Points : 225
    Points
    225
    Par défaut
    désolé, je n'avais pas bien lu les noms de variables.

    je ne pense pas que ça pose problème, mais tu fermes deux fois

    close (pfd_p2c[1 + 2 * i]);
    Wer nicht probiert, verliert !!

  5. #5
    Membre actif Avatar de je®ome
    Inscrit en
    Octobre 2005
    Messages
    285
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 285
    Points : 225
    Points
    225
    Par défaut
    En faisant quelques tests, je viens de m'apercevoir que ta fonction my_read n'est même pas appelé.
    A mon avis, et d'après mes tests, l 'écrivain de pfd_p2c[1 + 2 * i] dans process the request
    est bloquant.
    ton tuyeau n'est-il pas plein ?

    Comme dit, je suis plus que novice dans les tuyeaux ( également en C, mais bon)
    Wer nicht probiert, verliert !!

  6. #6
    Membre expérimenté
    Avatar de granquet
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2005
    Messages
    1 201
    Détails du profil
    Informations personnelles :
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2005
    Messages : 1 201
    Points : 1 421
    Points
    1 421
    Par défaut
    je suis aussi novice avec les pipes (le premier qui en profite pour dire une betise ... )

    sur les 2 systemes linux sur lesquels j'ai essayé (gcc 4.1.1 x86_64 et gcc 4.0.1 i686)
    c'est la lecture qui est blocante, l'ecriture se fait convenablement:
    voici la sortie chez moi (commentaires rajoutés entre --):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    reading cfg_file !
    spawning processes
    launching command !
    launching command !
    launching command !
    processing requests
    input now!
    hello ! -tappé au clavier, le programme attend une entrée clavier (fgets)-
    writing pipe:0
    debug: hello ! -ecriture succés: c'est directement le stderr du programme appelé-
    reading pipe:0 -on s'apprete a lire-
    my_read called ! -j'ai rajouté un printf a l'entrée de la fonction my_read-
    note: en principe ca arrive plus dans le desordre que ça ... j'ai eu un coup de bol
    et la donc ... plus rien ...
    en rajoutant un fflush(stdout); a la fin du while du prog appelé: (je remet pas le debut qui est identique au precedent)
    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
    my_read called !
    out: <bien recu hello !
    >
    writing pipe:1
    reading pipe:1
    my_read called !
    out: <bien recu hello !
    >
    writing pipe:2
    reading pipe:2
    my_read called !
    out: <bien recu hello !
    >
    debug: hello !
    debug: hello !
    si tu peux coller l'output que tu obtiens ...
    click my www
    ............|___
    ...................\
    .................._|_
    ..................\ /
    ..................."

  7. #7
    Membre actif Avatar de je®ome
    Inscrit en
    Octobre 2005
    Messages
    285
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 285
    Points : 225
    Points
    225
    Par défaut
    Bonsoir,

    voici mon output:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    reading cfg_file !
    spawning processes
    launching command !
    launching command !
    launching command !
    processing requests
    input now!
    salut
    writing pipe:0
    contenu inbuff apres 'fprintf ': salut
    J'ai ajouté un printf juste aprés le write qui devrait afficher le nbre d'octets écrit,
    mais comme tu vois, il n'y est pas.

    J' utilise gcc-3.3.6 et gcc-4.0.2 et l'output est le même.
    Le fait d' ajouter fflush(stdout) ne change rien au output.
    Wer nicht probiert, verliert !!

  8. #8
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Quelques remarques :

    Dans cette boucle :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for (i = 0; i < maxlen && outbuff[i - 1] != '\n' && ret > 0; i++)
    Ce test provoque un débordement de tableau...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    outbuff[i - 1] != '\n'
    Ensuite :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    execv ("test-chain-red", NULL);
    J'ai en tête qu'il faut répéter le nom de l'exécutable.

    Enfin, si t'es sous linux, pourquoi ne pas utiliser select pour transformer ta lectere bloquante en lecture non bloquante?

    Jc

  9. #9
    Membre expérimenté
    Avatar de granquet
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2005
    Messages
    1 201
    Détails du profil
    Informations personnelles :
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2005
    Messages : 1 201
    Points : 1 421
    Points
    1 421
    Par défaut
    pour le write qui se passe mal chez toi jerome,je t'avouerais que j'ai du mal a comprendre.

    Citation Envoyé par fearyourself
    Ce test provoque un débordement de tableau...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    outbuff[i - 1] != '\n'
    j'ai pas l'esprit clair, il vas falloir que j'y reflechisse .

    Ensuite :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    execv ("test-chain-red", NULL);
    J'ai en tête qu'il faut répéter le nom de l'exécutable.
    ah oui, man a l'appuie

    Enfin, si t'es sous linux, pourquoi ne pas utiliser select pour transformer ta lectere bloquante en lecture non bloquante?

    Jc
    parce que mon programme fonctionne de maniére sequentielle et que je n'ai pas besoin de lire la sortie du programme suivant (ni meme d'y ecrire) tant que le 'courant' n'as pas donné de reponse.
    click my www
    ............|___
    ...................\
    .................._|_
    ..................\ /
    ..................."

  10. #10
    Membre expérimenté
    Avatar de granquet
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2005
    Messages
    1 201
    Détails du profil
    Informations personnelles :
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2005
    Messages : 1 201
    Points : 1 421
    Points
    1 421
    Par défaut
    bon, probleme resolut. j'ai raté une ligne de code dans les programmes que je lance, ils sont bien tous en line buffered (setvbuf(stdout, NULL, _IOLBF, 0)) ou font des fflush(stdout). donc il n'y as plus de probleme :p
    jvais prendre un bout de papier et un stylo pour reflechir sur cette condition dans la boucle for.
    si vous avez d'autres remarques ... je prend

    ---
    nan peche que ca m'ennerve d'avoir passé une journée sur un probleme qui existe pas ...
    click my www
    ............|___
    ...................\
    .................._|_
    ..................\ /
    ..................."

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 28/03/2007, 11h32
  2. communication entre deux applications
    Par ilhamita dans le forum Langage
    Réponses: 1
    Dernier message: 06/03/2007, 15h28
  3. Réponses: 6
    Dernier message: 09/11/2006, 10h29
  4. communication entre 2 applications (exe)
    Par hal9000 dans le forum MFC
    Réponses: 26
    Dernier message: 24/10/2006, 11h47
  5. Réponses: 12
    Dernier message: 14/08/2006, 12h55

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