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 :

Utilisation des pipes


Sujet :

C

  1. #1
    Responsable Systèmes


    Homme Profil pro
    Gestion de parcs informatique
    Inscrit en
    Août 2011
    Messages
    17 437
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Gestion de parcs informatique
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Août 2011
    Messages : 17 437
    Points : 43 078
    Points
    43 078
    Par défaut Utilisation des pipes
    Bonjour,

    Je cherche à créer un pipe entre 2 fork/execvp

    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
    int pipefd[2];
    int retour_pipefd=pipe(pipefd);
    pid_t process=fork();
    if (process==0)
    {
        handler_pipe=freopen(pipefd[0],"a",stdout);
        int retour=execvp(arg_list[0],arg_list);
    }
    else
    {
        pid_t process2=fork();
        if (process2==0)
        {
            handler_pipe2=freopen(pipefd[1],"r",stdin);
            int retour=execvp(arg_list2[0],arg_list2);
        }
    En ayant la commande cat en list_arg, j'ai un message
    cat : sortie standard : mauvais descripteur de fichier.
    Quelqu'un peut-il m'aider ?

    Merci d'avance.
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur le P2V, mon article sur le cloud
    Consultez nos FAQ : Windows, Linux, Virtualisation

  2. #2
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 685
    Points : 30 974
    Points
    30 974
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par chrtophe Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    handler_pipe=freopen(pipefd[0],"a",stdout);
    handler_pipe2=freopen(pipefd[1],"r",stdin);
    Bonjour

    Tu n'as jamais pensé qu'à l'instar des descripteurs 0 (stdin) et 1 (stdout), la lecture était dévolue au coté [0] du pipe et que l'écriture était dévolue au coté [1] ???
    Et euh juste en passant, freopen() utilise des noms de fichiers en premier paramètre, pas des descripteurs int. Pour ceux-là, tu dois utiliser dup2() avec STDIN_FILENO et STDOUT_FILENO...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  3. #3
    Responsable Systèmes


    Homme Profil pro
    Gestion de parcs informatique
    Inscrit en
    Août 2011
    Messages
    17 437
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Gestion de parcs informatique
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Août 2011
    Messages : 17 437
    Points : 43 078
    Points
    43 078
    Par défaut
    Bonjour Sve@r, merci pour ta réponse.

    Tu n'as jamais pensé qu'à l'instar des descripteurs 0 (stdin) et 1 (stdout), la lecture était dévolue au coté [0] du pipe et que l'écriture était dévolue au coté [1] ???
    Si mais comme ça ne fonctionnait pas, j'ai inversé pour voir si j'avais pas compris quelque chose de travers.

    En remplaçant freopen par dup2, j'ai du progrès, plus de message d'erreurs, l'appel de la commande cat fichier.txt|more avec cat fichier.txt pour arg_list et more pour arg_list2.

    Par contre, a la fin de ma commande, je n'ai plus de stdin, j'ai mal géré qq part, il faut que je cherche pourquoi mes commandes dup2 fait dans des fork ce répercute dans le père. Par ailleurs, je ne comprend pas trop la différence entre stdin et STDIN_FILENO, (et pareil pour stdout). En tout cas avec stdin ça ne fonctionne pas.

    Voici mon code actuel :

    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
     
    int pipefd[2];
    int retour_pipefd=pipe(pipefd);
    if (retour_pipefd==0)
    {
     printf("***zone de creation des process***\n");
     pid_t process=fork();
     if (process==0)
     {
      printf("creation process 1\n");
      int handler_pipe=dup2(pipefd[1],STDOUT_FILENO);
      int retour=execvp(arg_list[0],arg_list);
      if (retour==-1|handler_pipe==-1) printf("%s\n",strerror(errno));
      }
     else
     {
      if (process!=-1)
      {
      pid_t process2=fork();
      if (process2==0)
      {
       printf("creation process 2\n");
       int handler_pipe2=dup2(pipefd[0],STDIN_FILENO);
       int retour=execvp(arg_list2[0],arg_list2);
       if (retour==-1|handler_pipe2==-1) printf("%s\n",strerror(errno));
      }
     else
     {
      wait(&process2);
     }
    }
     
    }
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur le P2V, mon article sur le cloud
    Consultez nos FAQ : Windows, Linux, Virtualisation

  4. #4
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 685
    Points : 30 974
    Points
    30 974
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par chrtophe Voir le message
    Par contre, a la fin de ma commande, je n'ai plus de stdin, j'ai mal géré qq part, il faut que je cherche pourquoi mes commandes dup2 faites dans des fork se répercutent dans le père.
    Moi non plus. Mais déjà quand tu auras indenté plus proprement ton code tout le monde y verras plus clair (à commencer par toi). Sans déconner, quand j'ai voulu le compiler j'ai du rajouter 3 accolades à la fin, toutes les 3 bien entendu au même niveau que celle qui y est déjà. Un code c'est avant tout quelque chose de lisible (ce qui aide aussi grandement quand il faut le faire évoluer).
    Et ce n'est pas parce que t'as quitté le lycée que le français a cessé d'exister. Parce que les règles de grammaire servent d'abord à rendre un texte facilement lisible par tous. Si ton lecteur doit relire 4 fois ton texte parce que le sens des mots va à l'encontre du sens général de la phrase, et qu'il doit en plus déchiffrer un code écrit de façon tout aussi laxiste, ne t'étonne pas si personne ne s'intéresse à ton problème...

    Citation Envoyé par chrtophe Voir le message
    Par ailleurs, je ne comprend pas trop la différence entre stdin et STDIN_FILENO, (et pareil pour stdout). En tout cas avec stdin ça ne fonctionne pas.
    stdin est une variable de type FILE* ce qui te permet de l'intégrer dans les fonctions manipulant les fichiers bufferisés type fgetc(), fread() et fgets().
    STDIN_FILENO est une macro représentant la valeur numérique de stdin telle qu'attendue par les processus Unix (ici 0) ce qui te permet de l'intégrer dans les fonctions manipulant des fichiers au bas niveau telles que read() ou dup().
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  5. #5
    Responsable Systèmes


    Homme Profil pro
    Gestion de parcs informatique
    Inscrit en
    Août 2011
    Messages
    17 437
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Gestion de parcs informatique
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Août 2011
    Messages : 17 437
    Points : 43 078
    Points
    43 078
    Par défaut
    Désolé pour indentation, prob. de copier/coller (idem pour les accolades), j'ai du refaire une indentation à la main dans le post car c'était encore pire
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur le P2V, mon article sur le cloud
    Consultez nos FAQ : Windows, Linux, Virtualisation

  6. #6
    Membre expérimenté
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    Mai 2010
    Messages
    543
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Mai 2010
    Messages : 543
    Points : 1 745
    Points
    1 745
    Par défaut
    Bonsoir tu peux toujours essayer d'écrire simplement (voir exemple ci-dessous)
    (attention le code est susceptible de contenir des erreurs )
    Code C : 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
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    #include <unistd.h>
    #include <sys/wait.h>
    #include <sys/types.h>
     
    #define _MAX_	2
    #define	_WRITE_	1
    #define _READS_	0
     
    int main( void ){
     
    	int i_Flag = 0;
    	int i_Tube[_MAX_];
     
    	if( pipe(i_Tube) ){
    		perror("Erreur tube\n");
    	}
     
    	i_Flag = fork();
    	switch( i_Flag ){
     
    	/*	Erreur	*/
    	case -1:
    		perror("Erreur Process\n");
    		exit( EXIT_FAILURE );
    	/*	Fils	*/
    	case 0:
    		close( STDOUT_FILENO );
    		if( (-1) == dup( i_Tube[_WRITE_] ) ){
    			perror("Erreur Dup (1)");
    			exit( EXIT_FAILURE );
    		}
     
    		close( i_Tube[_WRITE_] );
    		close( i_Tube[_READS_] );
    		execlp( "ls", "ls", "-la", NULL);
    		break;
    	/*	Père	*/
    	default:
    		close( STDIN_FILENO );
    		if( (-1) == dup( i_Tube[_READS_] ) ){
    			perror("Erreur Dup (2) \n");
    			exit( EXIT_FAILURE );
    		}
    		close( i_Tube[_READS_] );
    		close( i_Tube[_WRITE_] );
    		execlp( "uname", "uname", "-a", NULL);
    	}
     
    	return( EXIT_SUCCESS );
    }
    à bientôt
    Celui qui peut, agit. Celui qui ne peut pas, enseigne.
    Il y a deux sortes de savants: les spécialistes, qui connaissent tout sur rien,
    et les philosophes, qui ne connaissent rien sur tout.
    George Bernard Shaw

  7. #7
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 685
    Points : 30 974
    Points
    30 974
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par sambia39 Voir le message
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
     
    #define _MAX_	2
     
    int main( void ){
    	int i_Tube[_MAX_];
    	...
    }
    Mouais. Autant les macros je trouve ça super quand ça aide une possible évolutivité ; autant quand c'est franchement inutile je trouve ça exagéré
    Je ne sais pas quand on aura des tubes à plus de 2 cotés mais le jour où ça arrive, je serai super curieux de voir le principe...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  8. #8
    Responsable Systèmes


    Homme Profil pro
    Gestion de parcs informatique
    Inscrit en
    Août 2011
    Messages
    17 437
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Gestion de parcs informatique
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Août 2011
    Messages : 17 437
    Points : 43 078
    Points
    43 078
    Par défaut
    En tout cas je tourne en rond.

    voici mon dernier 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
    21
    22
    23
    24
    25
    26
     
    int pipefd[2];
    pipe(pipefd);
    pid_t process=fork();
    switch (process) {
    case -1:
         printf("%s\n",strerror(errno));
         break;
    case 0:
         dup2(pipefd[1], 1);
         execvp(arg_list[0],arg_list);
         break;
    default:
            wait(-1);
    }
    pid_t process2=fork();
    switch (process2) {
    case -1:
         printf("%s\n",strerror(errno));
         break;
    case 0:
         dup2(pipefd[0], 0);
         execvp(arg_list2[0],arg_list2);
         break;
    default:
    wait(-1);
    J'ai aussi fait un strace sur ce script :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    #!/bin/sh
    cat file.txt|more
    Il fait ce que je fait.

    Ca viendrait pas de la gestion des signaux entre père et fils ?

    un ctrl-c fonctionne.
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur le P2V, mon article sur le cloud
    Consultez nos FAQ : Windows, Linux, Virtualisation

  9. #9
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 685
    Points : 30 974
    Points
    30 974
    Billets dans le blog
    1
    Par défaut
    A partir de la ligne 16, tout ce que tu écris est exécuté à la fois dans le père et à la fois dans le premier fils créé à la ligne 4. Donc à cet endroit le père crée un autre fils et le fils de la ligne 4 en crée un aussi.
    Tu as donc l'arbre des processus suivants:
    Est-ce bien ce que tu voulais ???
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  10. #10
    Responsable Systèmes


    Homme Profil pro
    Gestion de parcs informatique
    Inscrit en
    Août 2011
    Messages
    17 437
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Gestion de parcs informatique
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Août 2011
    Messages : 17 437
    Points : 43 078
    Points
    43 078
    Par défaut
    Bonsoir Sve@r,

    J'ai réussi ce matin, faut que je teste encore pour être sûr mais ça semble bon.

    Je pense que le prob. venait du fait que mon premier fils crée le second (mon process de départ étant donc son grand-père). Je pense que c'est le sens de ta réponse.

    voici mon résultat :
    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
     
    int pipefd[2];
    pipe(pipefd);
    pid_t process=fork();
    switch (process) {
           case -1:
           printf("%s\n",strerror(errno));
           break;
    case 0:
         dup2(pipefd[1],STDOUT_FILENO);
         execvp(arg_list[0],arg_list);
         break;
    default:
            close(pipefd[1]);
            wait(-1);
    }
    pid_t process2=fork();
    switch (process2) {
    case -1:
         printf("%s\n",strerror(errno));
         break;
    case 0:
         dup2(pipefd[0],STDIN_FILENO);
         execvp(arg_list2[0],arg_list2);
         break;
    default:
            close(pipefd[0]);
            wait(-1);
    }
    Merci encore pour ton investissement.

    @sambia39 :
    J'ai utilisé comme conseillé des switch, c'est effectivement beaucoup plus lisible.
    Par contre, les macros, non car usage unique.
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur le P2V, mon article sur le cloud
    Consultez nos FAQ : Windows, Linux, Virtualisation

  11. #11
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 685
    Points : 30 974
    Points
    30 974
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par chrtophe Voir le message
    J'ai réussi ce matin, faut que je teste encore pour être sûr mais ça semble bon.
    Je pense que c'est le sens de ta réponse.
    En fait je me suis trompé. Je n'avais pas fait attention au execvp() du fils F1 en ligne 11. Or execvp() supprime le code courant pour le remplacer par le nouveau code. Donc F1 commute sur le programme demandé et ne déroule pas le reste du code. Donc effectivement ça a l'air correct...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

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

Discussions similaires

  1. Utilisation des fork et des pipes
    Par akrogames dans le forum Réseau
    Réponses: 7
    Dernier message: 22/10/2009, 19h22
  2. Utilisation des pipes en mode console
    Par thierryG dans le forum Windows
    Réponses: 7
    Dernier message: 18/10/2007, 14h49
  3. Utilisation des pipes
    Par Thes32 dans le forum Scripts/Batch
    Réponses: 3
    Dernier message: 02/08/2007, 21h12
  4. [Crystal Report] Utilisation des vues de sql serveur
    Par Olivierakadev dans le forum SAP Crystal Reports
    Réponses: 2
    Dernier message: 15/11/2002, 17h44
  5. [BCB5] Utilisation des Ressources (.res)
    Par Vince78 dans le forum C++Builder
    Réponses: 2
    Dernier message: 04/04/2002, 16h01

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