答案 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谈论对文件描述符的阻止和非阻止访问。