Derniers journaux de Moonz :
- [28/10@19:21] Apache et permissions
- [02/09@09:43] Se débarasser de X
Journal : petit problème avec popen()
Posté par Moonz () le 16 mars 2004J'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).
Re: petit problème avec popen()
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()
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()
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
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()
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++
-

Les journaux sont destinés à des informations qui ne sont pas suffisamment intéressantes
pour être validées en dépêche (sinon n'hésitez pas à proposer votre information en
dépêche), qui sont sans rapport avec Linux ou le libre, ou simplement pour donner votre
avis. Si vous désirez poser une question, merci d'utiliser 

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.