2009-11-14 17 views

Antwort

25

-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); 
+0

Funktioniert wunderbar ... danke! – jldupont

+0

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

2

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.

+0

Ich werde das tun! Vielen Dank! – jldupont

+2

Ich kann bestätigen, dass dieses Verfahren funktioniert. – jldupont

4

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); 
    } 
} 
+0

Sollte das nicht sein: if (pipe (p) <0) -1 zurückliefern; ? – Aktau

+1

@Aktau Ich mag meine Version besser. Der Systemaufruf gibt 0 bei Erfolg zurück. Die if-Anweisung testet auf nicht Null. – asveikau

+1

du hast recht, deine version ist auch völlig korrekt, ich habe an andere syscalls gedacht! – Aktau