2009-11-14 130 views

回答

25

設置是這樣的:

FILE *f = popen("./output", "r"); 
int d = fileno(f); 
fcntl(d, F_SETFL, O_NONBLOCK); 

現在你可以閱讀:

ssize_t r = read(d, buf, count); 
if (r == -1 && errno == EAGAIN) 
    no data yet 
else if (r > 0) 
    received data 
else 
    pipe closed 

當你」重做,清理:

pclose(f); 
+0

美麗地工作...謝謝! – jldupont 2009-11-16 18:30:10

+0

作爲FILE指針的管道是固有緩衝的,是否有任何保證,通過直接使用文件描述符,你不會錯過被拉入文件緩衝區的東西,或者只要你不先打電話給fget/fread/etc? – stu 2016-06-03 17:10:16

2

從來沒有嘗試過,但我不明白爲什麼你不能用fileno()獲取文件描述符,使用fcntl()設置爲非阻塞,並使用read()/ write()。值得一試。

+0

我會那樣做的!謝謝! – jldupont 2009-11-14 22:28:33

+2

我可以確認此過程有效。 – jldupont 2009-11-16 18:29:39

4

popen()內部調用pipe()fork()dup2()(指向子進程的FDS 0/1/2的管道)和execve()。你有沒有考慮過使用這些?在這種情況下,您可以使用fcntl()將您讀取的管道設置爲非阻塞。

更新:下面是一個例子,只是爲了說明目的:

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

不應該是:if(pipe(p)<0)返回-1; ? – Aktau 2013-04-14 11:00:54

+1

@Aktau我更喜歡我的版本。系統調用將成功返回0。 if語句測試非零。 – asveikau 2013-04-15 04:34:51

+1

你是對的,你的版本也是完全正確的,我正在考慮其他系統調用! – Aktau 2013-04-15 12:15:16