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

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    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
    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 .

  2. #2
    Membre éclairé Avatar de je®ome
    Inscrit en
    Octobre 2005
    Messages
    285
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 285
    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 ?

  3. #3
    Membre éprouvé
    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
    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)

  4. #4
    Membre éclairé Avatar de je®ome
    Inscrit en
    Octobre 2005
    Messages
    285
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 285
    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]);

  5. #5
    Membre éclairé Avatar de je®ome
    Inscrit en
    Octobre 2005
    Messages
    285
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 285
    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)

  6. #6
    Membre éprouvé
    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
    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 ...

+ 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