使用popen的非阻塞管道?

问题描述:

我想用popen()打开一个管道,并对其进行非阻塞的“读取”访问。使用popen的非阻塞管道?

我该如何做到这一点?

(我发现的例子都是阻塞/同步)

设置是这样的:

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

你看着这个男人页面为POPEN的“又见”部分()?

快速谷歌搜索显示此页:http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#blocking谈论阻塞和非阻塞访问文件描述符。

从来没有尝试过,但我不明白为什么你不能用fileno()获取文件描述符,使用fcntl()设置为非阻塞,并使用read()/ write()。值得一试。

+0

我会那样做的!谢谢! – jldupont 2009-11-14 22:28:33

+2

我可以确认此过程有效。 – jldupont 2009-11-16 18:29:39

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) 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