Vorrei aprire una pipe usando popen()
e avere accesso "non leggibile" a tale blocco.Tubo non bloccante che utilizza il popen?
Come posso ottenere questo risultato?
(Gli esempi che ho trovato erano tutti blocco/sincrono)
Vorrei aprire una pipe usando popen()
e avere accesso "non leggibile" a tale blocco.Tubo non bloccante che utilizza il popen?
Come posso ottenere questo risultato?
(Gli esempi che ho trovato erano tutti blocco/sincrono)
Setup in questo modo:
FILE *f = popen("./output", "r");
int d = fileno(f);
fcntl(d, F_SETFL, O_NONBLOCK);
Ora si può leggere:
ssize_t r = read(d, buf, count);
if (r == -1 && errno == EAGAIN)
no data yet
else if (r > 0)
received data
else
pipe closed
Quando si' fatto, pulizia:
pclose(f);
hai guardato la sezione "vedi anche" della pagina di manuale per popen()?
Ricerca google veloce ha rivelato questa pagina: http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#blocking Parla di blocco e accesso non bloccante ai descrittori di file.
popen()
chiama internamente pipe()
, fork()
, dup2()
(per puntare FDS del processo figlio 0/1/2 ai tubi) e execve()
. Hai preso in considerazione l'utilizzo di questi invece? In tal caso, puoi impostare la pipe che hai letto per non bloccare usando fcntl()
.
aggiornamento: Ecco un esempio, solo a scopo illustrativo:
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);
}
}
Non dovrebbe essere: if (pipe (p) <0) return -1; ? – Aktau
@Aktau Mi piace la mia versione migliore. Syscall restituirà 0 in caso di successo. L'istruzione if verifica per i non zero. – asveikau
hai ragione, la tua versione è anche completamente corretta, stavo pensando ad altre syscalls! – Aktau
Funziona magnificamente ... grazie! – jldupont
la pipa, essendo un puntatore FILE, è intrinsecamente bufferizzata, c'è la certezza che usando il descrittore di file direttamente non si perderà qualcosa che è stato inserito nel buffer dei file, o può essere garantito fino a quando non si chiamare prima fget/fread/etc prima? – stu