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() et pipe(), eof non lu


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre très actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2009
    Messages
    172
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2009
    Messages : 172
    Par défaut fork() et pipe(), eof non lu
    Salut à tous,

    J'ai un petit problème concernant une application que je suis en train de développer. Je précise que je suis tout frais dans le mode du C.

    Le principe est assez simple, le voici :

    Je fais un appel à pipe() pour créer un tube, puis j'utilise fork() après avoir correctement redirigé les entrées et sorties standards pour que le fils puisse lancer l'application ctags. ctags lira les fichier à traiter dans son entrée standard pendant que le père enverra les fichiers sur sa (celle du père), sortie standard. Voici le principe en bouts de code (Je précise que j'ai tout écrit à la main donc si il y'a des erreurs de syntaxe il s'agit simplement de faute de frappe. Tout A L'AIR de bien fonctionner, ctags crée et remplie bien le fichier de tags)

    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
     
    int * tube;
     
    if(pipe(tube)){
      [...]
    }
     
    switch(fork()){
       [...]
        case 0:
             close(tube[1]);
             dup2(tube[0], STDIN_FILENO);
              [ ...
                    <lance "ctags -L -" avec execvp() pour lire l entrée standard>
               ... ];
     
       default:
             close(tube[0]);
             dup2(tube[1], STDOUT_FILENO);
             [ ...
                  <lance la fonction qui ecrit les fichier à traiter dans la sortie standard!>
             ... ]
    }
     
    [ <le reste traite normalement avec stdin et stdout> ]
    Tout marche bien, le ctags me sort bien un fichier de tags Seulement voilà la fonction en question dans le père est sensée écrire un EOF dans le tube (sa sortie standard). Ce que je fais avec un fwrite(stdout, "%d", stdout) car j'ai lu que fputc() convertit de façon transparente un entier, quel qu'il soit, en caractère (Je débute encore en C et ces notions sont encore un peu vague pour moi donc dans le doute...!). Puis la "fonction père" ferme sa sortie standard (ce que je fais avec un close() ).

    Mon problème est que lorsque j'envoie le EOF dans stdout et même quand je ferme mon stdout dans le père, le ctags reste quand même bloqué et attend encore d'autres noms de fichiers.

    Alors voici ma question, y'a-t-il un moyen genre un attribut du pipe, portable si possible, que je pourrais changer pour que le EOF soit transmis directement au fils? Bien sûr j'ai posé ma question en étant sûr que çà vient de là mais je débute vraiment en C alors si je me gourre n'hésitez pas à me lyncher! A ce propos d'ailleurs je précise que j'ai fais un test en envoyant, juste pour tester, un nombre de EOF correspondant à la taille d'un buffer pour les pipe mais là ctags m'affiche je ne sais combien de fois un caractère bizarre avant de me dire que le nom de fichier est trop long.

    Donc j'en profite pour poser une deuxième question histoire d'être sûr :
    Mon caractère EOF (-1 sur mon système linux), est-il bien passé tel quel à la sortie standard?? Et de façon plus générale quelle serait la meilleure fonction pour écrire des données "brutes" dans ce genre de situation sans formattage par fprintf et autres??

  2. #2
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2008
    Messages
    1 515
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 515
    Par défaut
    On n'écrit pas "EOF" comme tu essaies de le faire. EOF n'est pas une valeur qu'on transmet, c'est juste une manière pour fread() d'indiquer qu'on a atteint la fin des données. Si fread() renvoit EOF c'est parce que la fin du fichier a été atteinte, pas parce qu'un caractère "EOF" a été lu dans le fichier. En pratique dans le cas d'un pipe on a EOF quand il n'y a plus de données à lire dans le pipe, et que l'autre bout a été fermé.

    Donc dans le père il faut simplement faire un fclose() du fichier dans lequel tu écrit les données (en passant, tu n'as pas besoin de faire un dup2, tu peux très bien écrire les données dans tube[0]).

    Tu sembles mélanger des fonctions sur les fd (close) et des fonctions sur les streams (fwrite). Il ne faut pas.

    Si tu veux plus d'aide il faudrait le code du père qui envoie les données au fils.

  3. #3
    Membre très actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2009
    Messages
    172
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2009
    Messages : 172
    Par défaut
    Salut et merci de ta réponse,

    En fait le dup2 c'est pour pouvoir travailler avec la sortie standard dans le père et l'entrée standard dans le fils vu que ctag va lire dedans.



    La fonction du père ne fais rien d'autre qu'écrire dans sa sortie standard des chaines de caractères. je te donne un exemple plus court :

    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 main(void){
       int * tube;
       char * commande[]= {"ctags", "-L", "-", (char *) NULL};
     
       pipe(tube);
     
       switch(fork()){
          case 0:
                 close(tube[1]);
                 dup2(tube[0], STDIN_FILENO);
                  if(execvp("ctags", commande)){
                      strerror(errno);
                      exit(1);
                  break;
     
           default:
                 close(tube[0]);
                 dup2(tube[1], STDOUT_FILENO);
                  sleep(5); /* le temps que ctags se lance */
                  fprintf(stdout, "test.c\n");
                  fflush(stdout);
                  fclose(stdout);
                  return(0);
       }
    }
    j'ai volontairement omis le traitement des erreurs.

    Maintenant je ne controle pas ctags donc je ne peux pas faire un fclose sur stdin dans le fils. Et le problème c'est que ctags reste en attente sur stdin. Je voudrais juste simuler l'appui d'un ^d (eof) en mode interractif quand la fonction du père a fini. seulement le fd reste ouvert dans ctags et je n'y peut rien. le fd ne se ferme que lorsque je tape une touche dans le shell. Donc je suppose que pour fermer ctags, il faut lui envoyer explicitement le eof, mais comment? Comment simuler le ctrl-d dans le fd?

    merci encore

  4. #4
    Membre très actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2009
    Messages
    172
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2009
    Messages : 172
    Par défaut
    Rebonjour,

    bon alors il n'y a vraiment personne qui aurait un semblant de réponse???

  5. #5
    Membre très actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2010
    Messages
    254
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2010
    Messages : 254
    Par défaut
    Au lieu d'uiliser un sleep pour temporiser, utilise plutot une fonction de la famille wait. Ces fonctions vont attendre que le fils termine sont execution avant de continuer l'execution du père.

  6. #6
    Membre très actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2009
    Messages
    172
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2009
    Messages : 172
    Par défaut
    Merci de ta réponse mais je n'utilise pas ces fonctions car comme tu as pu le voir dans mon code le père ne se contente pas d'attendre la fin du fils et heureusement car le fils lui attend les "instruction" du père via son entrée standard. Une fonction de la famille wait waitpid etc... bloquerait mon programme indéfiniment.

    Mais là on s'écarte du sujet. Pour mon problème de EOF? Personne n'a vraiment jamais envoyé de EOF sur autre chose qu'un terminal?

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

Discussions similaires

  1. EOF non détecté sur appel sqlplus
    Par theophanie77460 dans le forum SGBD
    Réponses: 1
    Dernier message: 23/03/2012, 17h21
  2. Fork et pipe
    Par Ylias dans le forum Shell et commandes GNU
    Réponses: 6
    Dernier message: 30/05/2006, 09h13
  3. Caractère EOF non reconnu
    Par rod59 dans le forum C
    Réponses: 14
    Dernier message: 11/11/2005, 17h15
  4. [PERL] Problème en essayant de comprendre fork et pipe
    Par LE NEINDRE dans le forum Langage
    Réponses: 6
    Dernier message: 04/10/2005, 15h23
  5. Réponses: 3
    Dernier message: 16/03/2004, 16h42

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