Derniers journaux de Moonz :

Journal : petit problème avec popen()

Posté par Moonz () le 16 mars 2004
0
Bonjour tout le monde,
J'aimerais pouvoir avoir en temps réel la sortie d'une commande. Mon ami google m'a donné une fonction popen() qui répond presque à mes besoins. Mais voilà, la fonction popen() est bloquante, et moi je ne le veut pas. J'aimerais que le programme suivant affiche 10 (attente d'1 seconde) 9 (attente d'1 seconde) 8 (attente d'1 seconde) 7 (attente d'1 seconde) 6 (attente d'1 seconde) 5 (attente d'1 seconde) 4 (attente d'1 seconde) 3 (attente d'1 seconde) 2 (attente d'1 seconde) 1 (attente d'1 seconde) 0 (attente d'1 seconde)

#include
#include

using namespace std;

int main (int argc, char *argv[]) {
FILE* tmp = popen("for i in 10 9 8 7 6 5 4 3 2 1; do echo $i; sleep 1; done", "r");
char c;

while(fread(&c, sizeof(char), 1, tmp)) {
cout << c;
}
fclose(tmp);

return 0;
}

Or, il attend 11 secondes et affiche l'un coup 10 9 8 7 6 5 4 3 2 1 0. Une petite idée pour faire la même chose mais en non bloquant ? (si possible quelque chose de portable au moins sous windows et *nix)

Merci.

> Lire le journal (13 commentaires, moyenne: 2,1).  

Cette discussion est archivée, il n'est plus possible de laisser des commentaires.

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.

Re: petit problème avec popen()

Posté par TImaniac (page perso, ) le 16/03/2004 à 19:02. (lien). Évalué à 1.

lances la commande dans un thread : regardes du côté de fork et redirige la sortie que tu veux exploiter.

  • [^]Re: petit problème avec popen()

    Posté par gawal () le 16/03/2004 à 19:04. (lien). Évalué à 3.

    Avec fork, tu lances un processus séparé. Pour les threads, il faut voir les pthreads. man pthread_create par exemple.

    • [^]Re: petit problème avec popen()

      Posté par TImaniac (page perso, ) le 16/03/2004 à 19:05. (lien). Évalué à 2.

      oui pardon je voulais dire un processus séparé, enfin le principe est le même, après c'est une question de "lourdeur" ;)

      • [^]Re: petit problème avec popen()

        Posté par cykl (Jabber id, ) le 16/03/2004 à 19:09. (lien). Évalué à 2.

        Non le principe est pas vraiment du tout le meme du tout !
        Simplement le fait de partager ou pas ton espace d'addressage me semble etre une bonne raison pour ne pas dire une betise parreil :-)

        Comme quoi le lapsus etait revelateur !

        • [^]Re: petit problème avec popen()

          Posté par TImaniac (page perso, ) le 16/03/2004 à 19:17. (lien). Évalué à 1.

          si le principe d'avoir 2 exécutions en // est le même quand même :)

  • [^]Re: petit problème avec popen()

    Posté par TazForEver () le 16/03/2004 à 23:34. (lien). Évalué à 1.

    n'imp ...

    et puis de toutes façons tu crois qu'il fait quoi popen ?

Re: petit problème avec popen()

Posté par Troy McClure (page perso, ) le 16/03/2004 à 19:25. (lien). Évalué à 1.

fais des lectures non-bloquantes avec fcntl(...O_NONBLOCK) ou bien utilises select
Mais à mon avis c'est pas compatible ouinouin, il faudra que tu passes par une bibli de plus haut niveau, la glib doit proposer ça je pense

Re: petit problème avec popen()

Posté par Mathieu Malaterre (page perso, ) le 16/03/2004 à 19:30. (lien). Évalué à 1.

Je crois que tu as besoin de la fonction select (sur les fichiers)

http://www.opengroup.org/onlinepubs/007904975/functions/select.html(...)

Tu peux tuer tes process et tout et tout !

Raaahhh

Posté par Vivi (page perso, ) le 16/03/2004 à 22:36. (lien). Évalué à 3.

misère ...

popen est non bloquant (évidemment). Mais comme tu ne flush pas ta sortie standard, tout déboule à la fin du programme.

Et il faut utiliser pclose pour fermer le flux (pour faire un wait sur le fils). Et tu devrais tester les valeurs de retour de popen et pclose.

  • [^]Re: Raaahhh

    Posté par mnemosyne () le 16/03/2004 à 23:06. (lien). Évalué à 3.

    Hmm...

    Le problème ne vient pas vraiment la sortie standard : elle est bien "flushée" (on dit quoi en français ? vidée ?) après chaque retour chariot inséré par echo. C'est en revanche l'entrée standard du processus fils (celui créé par popen) qui ne l'est pas.

    Pour être encore plus constructif, donnons la solution à ce petit problème : il faut utiliser la fonction setvbuf ; en l'occurence il faut placer après le popen (et avant le fread) un setvbuf(tmp, _IONBF, 0).

Re: petit problème avec popen()

Posté par TazForEver () le 16/03/2004 à 23:34. (lien). Évalué à 5.

c'est à cause de la bufferisation de FILE* (d'ailleurs ton C++ il en a que le nom)


#include <stdio.h>

int main(int argc, char *argv[])
{
int c;
FILE* tmp = popen("for i in 10 9 8 7 6 5 4 3 2 1; do echo $i; sleep 1; done", "r");

setvbuf(tmp, NULL, _IONBF, 0);

while( (c=fgetc(tmp)) != EOF)
{
putchar(c);
}

fclose(tmp);

return 0;
}


et voilà !

man setbuf
man setvbuf

  • [^]Re: petit problème avec popen()

    Posté par Moonz () le 17/03/2004 à 10:47. (lien). Évalué à 3.

    Merci à tous pour vois réponses (malheureusement j'ai pas eu assez de [+] pour plusser tout le monde) =)

    (d'ailleurs ton C++ il en a que le nom)
    C'est parce que ce n'était qu'un exemple =)

    • [^]Re: petit problème avec popen()

      Posté par TazForEver () le 17/03/2004 à 18:53. (lien). Évalué à 1.

      jète un oeil a des bibliothèques C++ qui enrobe tout bien mieux. doit y avoir ça de bien fait dans GNUCommonC++

Revenir en haut de page