Ich möchte eine Pipe mit popen()
öffnen und nicht blockierenden Lesezugriff darauf haben.Nicht blockierende Leitung mit popen?
Wie kann ich das erreichen?
(Die Beispiele, die ich fand, waren alle Blockierung/synchron)
Ich möchte eine Pipe mit popen()
öffnen und nicht blockierenden Lesezugriff darauf haben.Nicht blockierende Leitung mit popen?
Wie kann ich das erreichen?
(Die Beispiele, die ich fand, waren alle Blockierung/synchron)
-Setup wie folgt aus:
FILE *f = popen("./output", "r");
int d = fileno(f);
fcntl(d, F_SETFL, O_NONBLOCK);
Jetzt können Sie lesen:
ssize_t r = read(d, buf, count);
if (r == -1 && errno == EAGAIN)
no data yet
else if (r > 0)
received data
else
pipe closed
Wenn Sie‘ re getan, Reinigung:
pclose(f);
Haben Sie an der sah „auch“ auf der man-Seite für popen()?
Schnelle Google-Suche ergab diese Seite: http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#blocking Gespräche über blockierende und nicht-blockierende Zugriff auf Dateideskriptoren.
Ich habe es nie versucht, aber ich sehe nicht, warum Sie nicht die Dateideskriptoren mit fileno() greifen konnten, verwenden Sie fcntl(), um nicht blockierend zu setzen, und verwenden Sie read()/write(). Einen Versuch wert.
popen()
ruft intern pipe()
, fork()
, dup2()
und execve()
(zu den fds 0/1/2 an den Rohren des Kindes Prozess Punkt). Hast du in Betracht gezogen, diese stattdessen zu verwenden? In diesem Fall können Sie die zu lesende Pipe mithilfe von fcntl()
auf nicht blockierend setzen.
Update: nur zu Veranschaulichungszwecken Hier ist ein Beispiel,:
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);
}
}
Sollte das nicht sein: if (pipe (p) <0) -1 zurückliefern; ? – Aktau
@Aktau Ich mag meine Version besser. Der Systemaufruf gibt 0 bei Erfolg zurück. Die if-Anweisung testet auf nicht Null. – asveikau
du hast recht, deine version ist auch völlig korrekt, ich habe an andere syscalls gedacht! – Aktau
Funktioniert wunderbar ... danke! – jldupont
die Pipe, die ein FILE-Pointer ist, ist inhärent gepuffert, gibt es irgendeine Gewissheit, dass durch die direkte Verwendung des Dateideskriptors etwas, das in den Dateipuffer gezogen wurde, nicht verloren geht, oder kann dies garantiert werden, solange Sie es nicht tun FGF/FRET/etc nicht zuerst anrufen? – stu