使用popen的无阻塞管道?

时间:2009-11-14 22:14:29

标签: c linux pipe popen

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

我怎样才能做到这一点?

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

4 个答案:

答案 0 :(得分:26)

像这样设置:

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

答案 1 :(得分:6)

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 child process, close read 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);
      default:
          /* We're the parent process, close write end of pipe */
          close(p[1]);
          return p[0];
   }
}

答案 2 :(得分:2)

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

答案 3 :(得分:0)

您是否看过popen()手册页的“另见”部分?

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