Je souhaite ouvrir un tube en utilisant popen()
et avoir un accès «lecture» non bloquant.Tube non bloquant utilisant du popen?
Comment puis-je y parvenir?
(Les exemples que j'ai trouvés tout blocage/synchrone)
Je souhaite ouvrir un tube en utilisant popen()
et avoir un accès «lecture» non bloquant.Tube non bloquant utilisant du popen?
Comment puis-je y parvenir?
(Les exemples que j'ai trouvés tout blocage/synchrone)
installation comme ceci:
FILE *f = popen("./output", "r");
int d = fileno(f);
fcntl(d, F_SETFL, O_NONBLOCK);
Maintenant, vous pouvez lire:
ssize_t r = read(d, buf, count);
if (r == -1 && errno == EAGAIN)
no data yet
else if (r > 0)
received data
else
pipe closed
Lorsque vous » re fait, nettoyage:
pclose(f);
Avez-vous regardé la section « Voir aussi » de la page de manuel pour popen()?
La recherche rapide sur google a révélé cette page: http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#blocking Parler de blocage et d'accès non bloquant aux descripteurs de fichiers.
Je ne l'ai jamais essayé mais je ne vois pas pourquoi vous n'avez pas pu récupérer les descripteurs de fichier avec fileno(), utilisez fcntl() pour définir non-bloquant, et utilisez read()/write(). Ça vaut le coup d'essayer.
popen()
appelle en interne pipe()
, fork()
, dup2()
(pour pointer les fds de processus enfant 0/1/2 aux tuyaux) et execve()
. Avez-vous envisagé de les utiliser à la place? Dans ce cas, vous pouvez définir le canal que vous avez lu comme non bloquant à l'aide de fcntl()
.
mise à jour: Voici un exemple, juste à titre d'exemple:
int read_pipe_for_command(const char **argv)
{
int p[2];
/* Create the pipe. */
if (pipe(p))
{
return -1;
}
/* Set non-blocking on the readable end. */
if (fcntl(p[0], F_SETFL, O_NONBLOCK))
{
close(p[0]);
close(p[1]);
return -1;
}
/* Create child process. */
switch (fork())
{
case -1:
close(p[0]);
close(p[1]);
return -1;
case 0:
/* We're the parent process, close the writable part of the pipe */
close(p[1]);
return p[0];
default:
/* Close readable end of pipe */
close(p[0]);
/* Make stdout into writable end */
dup2(p[1], 1);
/* Run program */
execvp(*argv, argv);
/* If we got this far there was an error... */
perror(*argv);
exit(-1);
}
}
Cela ne devrait pas être: if (pipe (p) <0) renvoie -1; ? – Aktau
@Aktau J'aime mieux ma version. Le syscall retournera 0 en cas de succès. L'instruction if teste pour non zéro. – asveikau
vous avez raison, votre version est aussi complètement correcte, je pensais à d'autres syscalls! – Aktau
Fonctionne magnifiquement ... merci! – jldupont
le pipe, étant un pointeur FILE, est intrinsèquement tamponné, il n'y a aucune assurance qu'en utilisant le descripteur de fichier directement vous ne manquerez pas quelque chose qui a été tiré dans le tampon de fichier, ou peut-il être garanti aussi longtemps que vous N'appelez pas fget/fread/etc en premier? – stu